Tool Flows
A tool flow lets the model run several tool calls inside one short Python-subset
script. When one call’s result feeds the next call’s arguments, a normal
conversation needs a round trip per call: the model requests a tool, waits for
the result, then requests the next tool. A tool flow collapses that sequence
into a single tool_flow call. The model writes the script, Polytoken runs it
against the tools you approved, and Polytoken returns the flow’s result in a
single response.
When to use a tool flow
Section titled “When to use a tool flow”A tool flow fits work whose sequence the model already knows: read a file, search its contents, fetch a page named in the results, then combine everything. The model decides the logic up front and the script carries it out without further model involvement.
Independent calls that share nothing do not need a flow. The model can batch those in one turn already, and a flow would only add a script between the model and its tools.
Writing a script
Section titled “Writing a script”A tool_flow call carries the code, a name for the flow, and the list of
tools the script may call. Two optional settings tune the run:
timeout_seconds (twenty minutes by default) and background.
readme = file_read(path="README.md")hits = grep(pattern="tool_flow", path="rs")print(hits["text"][:200]){"readme": readme["text"][:200], "matches": hits["text"]}Each requested tool becomes a function in the script. Polytoken wraps
plain-text tool output in an object with a text field and parses JSON tool
output into data. The example indexes readme["text"] to work with the file
content as a string. Polytoken
uses the registry name when it is a valid Python identifier and otherwise
creates a valid, unique alias. Call tools with keyword arguments, use print() for
diagnostic output, and leave the value you want returned as the trailing
expression. That final expression becomes the flow’s result. The Python subset
provides access only through the approved tools: it does not offer direct
filesystem, shell, network, or process-spawning APIs.
The result envelope
Section titled “The result envelope”A finished flow returns a JSON envelope with six fields:
status: the script outcome (okorerror).prints: captured output fromprint().result: the value of the script’s trailing expression.calls: a log of the tool calls the script made.stats: the call count, print-output bytes, and execution time.truncation: a marker that reports whether Polytoken shortened output.
Polytoken shortens large output so the envelope fits the conversation. If the
envelope still overflows, Polytoken returns only status and truncation.
The truncation marker reports trimmed prints, a shortened result, or
omitted call-log entries. Each entry in calls keeps only the tail of a long
result, but that shortening does not set the marker. Polytoken keeps the
fuller content in the expanded tool card.
Approval and permissions
Section titled “Approval and permissions”Polytoken requests approval for a flow’s exact script and tool set before starting the flow. That approval never applies to a later flow with different code or different tools.
Nested calls follow the active permission mode. In standard and autonomous
modes, deny rules and hard secret-protection denies produce catchable errors
inside the script. The flow’s approval satisfies secret-file reads that would
otherwise require your approval, while Polytoken still filters search results
that would surface a secret. Bypass skips permission rules and secret
protections. Bypass+ retains explicit deny rules but skips secret protections.
A .agentblock entry blocks nested file access in every mode and produces a
catchable error. Nested calls never pause the flow for further approval
prompts.
A flow can call only the tools named in its tools list. Eligible built-in
tools opt in explicitly: the file reading, file searching, web fetching, web
searching, and decision tools today. MCP tools are eligible unless
daemon.tool_flow.mcp_tools_deny denies them; each deny entry is a
shell-style glob such as mcp__github__*. Shell, planning, subagent, todo,
and facet tools are never callable from a flow, and a flow cannot call
tool_flow itself. Polytoken validates the whole tools list before running
the script and rejects the flow call if the list contains a missing,
ineligible, or denied tool. These validation failures do not become errors
inside the script.
daemon.tool_flow.max_timeout_seconds caps a flow’s time budget.
The daemon.tool_flow.max_calls setting limits how many tool calls one flow
may make.
Background flows
Section titled “Background flows”Set background: true to run a flow in the background, or press Ctrl+B while
it runs in the foreground. Polytoken returns a job handle immediately, named
after your flow, and the flow keeps running while you continue the
conversation. Use the standard job controls to inspect, retrieve, or cancel the
flow, like any other background job.