tool_exec
Run a JavaScript script inside the engine, against the engine's own tool catalogue. Use this instead of several separate tool calls whenever you need to filter, loop over, or combine results: the intermediate data stays in the script rather than passing through the conversation.
Two globals, and nothing else:
zero..(...args) call a tool. Every call returns a promise, so await it. zero.libs...(...args) call a tool a library ships (its toolbox is registered as @::) tools.toolboxes() every toolbox: { toolbox, purpose, toolCount } tools.list(toolbox) the tools in one: { name, signature, description } tools.describe(name) one tool in full: args, returns, examples, types tools.search(query, toolbox?) find a tool by what you want to do tools.use(toolbox, tool, ...args) call by computed name
Start with tools.toolboxes() or tools.search(...) if you do not already know the tool you want, then tools.describe(name) for its exact arguments: they are positional and typed. zero. also reaches a library's toolbox when no other toolbox has that name; a name several hold is refused naming each. await works at the top level. return a value to hand it back; keep it small, and reduce inside the script rather than returning everything you fetched. console.log is captured and returned in logs. The language is ZeroJS: modern JavaScript and its standard library, with no Node or browser APIs.
Sequencing is yours to choose: await a; await b; runs them one after another, while await Promise.all([a, b]) runs them at the same time, which genuinely overlaps, so prefer it for independent calls.
The answer is { ok, value, error, failure, trace, logs }. value is what the script returned. When ok is false, error says what failed and where, and failure.kind is tool (a tool call's rejection ended the script; failure.step and failure.tool name the call), script (the script threw), syntax (it did not parse; the position counts the script's own lines), timeout (it outlived timeoutMs; a value it had returned stays in value), budget (it made more than 200 tool calls) or setup (the script environment could not be prepared). trace lists every call with its step, outcome and duration.
Example:
const hits = await tools.search("read a file"); const [info, text] = await Promise.all([zero.wld.info(), zero.files.read("/source/notes.md")]); return { mode: info.mode, lines: text.split("\n").length, firstHit: hits[0].name };
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| as | No | Your own name, when you are one of several agents sharing one connection to this engine (the sub-agents one agent session runs share its connection, so without it the engine sees all of them as one caller). Pass the same name on every call you make. The engine then treats you as a caller of your own: your roster name is this name, and your play session, the play-shadow writes and refusals that say who wrote what, engine.modeOwner, your shell session and your notices are yours alone. Lowercase letters, digits, '-' and '_'. Leave it out when you are the only agent on your connection. | |
| script | Yes | The JavaScript to run. `await` works at the top level; `return` hands back the result. | |
| timeoutMs | No | Wall-clock budget for the whole script, including its tool calls. Default 30000. |