Skip to content

Programmatic tool calling

programmatic_tool_caller lets the model use its other tools by writing a short program, instead of calling them one at a time and waiting for each result. It is on by default.

The model calls the tool with a code string of Python. That code runs in isolation with every other registered tool exposed as an async function, so the model can chain calls, loop over them, filter results, and run independent calls in parallel, all in a single turn. Only text the code sends to print returns to the model; a tool’s return value stays in the code’s local scope unless the code prints it. That is the point: a step that touches many tools produces one concise result rather than filling the conversation with every intermediate payload.

For example, the model can read several files, keep only the matches it cares about, and print a summary, without the full contents of each file ever entering the context window.

The tool calls the code makes run through the agent’s normal executor, so an autonomous intervention policy (a Cedar policy or a natural-language risk policy) that denies a call blocks it, and the code sees a catchable error. Interrupt-based human approval cannot prompt from inside the code, so a call gated that way raises a catchable error rather than pausing for input.

The code runs in Monty, a Python interpreter that isolates the code it runs. Filesystem, environment, network, and process access do not exist in it, so the only thing model-authored code can reach is the set of tool functions handed in. Monty runs in a separate worker process with memory, time, and recursion limits.

Output is capped (a runaway print cannot blow up the context window), and awaited code is bounded by a default timeout.

The tool is selected by name through builtin_tools. Drop programmatic_tool_caller from the list to turn it off; see add tools and instructions for how selection works.