tool_call step. Policy
applies to it, it replays on resume, and it shows up in the audit trail.
defineTool
name, description, inputSchema,
idempotency, and execute, so frameworks that introspect a tool object bind it
unchanged. Hand tools to a framework as a plain array:
resources names the external resources the tool may change.
Defaults to none.
wrapTool accepts the same option. See Resources.
Idempotency
idempotency controls whether a tool may run again when a dispatch replays.
safe_to_retry(default) is for reads and anything else fine to execute again. On resume the recorded result replays, and a step that never completed runs again.at_most_onceis for destructive operations such as sending an email or charging a card. If a resumed dispatch finds the step already executing, the kernel fails it with reasonindeterminateand the SDK throwsToolError, so your handler decides how to reconcile. A step recorded but never started is still safe, so it runs.
Denied calls
A tool denied by policy does not throw.defineTool and wrapTool catch the
PolicyError and return a string instead:
step() throws PolicyError
normally, since nothing reads its result as a tool response.
Subagents
subagent() runs another agent as a subagent of the
calling tool. Return its result from the tool body:
output, and a failed or cancelled
subagent throws ToolError. Other tool calls keep running while it waits. Once
every call in flight waits, the execution suspends and releases its worker. The
handler reruns after they settle and replays their outcomes, so concurrent tool
calls can each start a subagent.
Pass { session } to continue a conversation with a subagent. Subagents started
with the same session run one at a time, and each continues from the last one
that completed. The session must differ from the parent’s. Derive it from the
parent’s session or ID so other parents cannot reuse it:
Client, which needs a
key with the executions:write scope. Pass { client }, or set REBUNO_URL
and REBUNO_API_KEY. Calling subagent() outside a tool body throws an
Error.
Blocking work
Calling context
A tool records against the current execution. Calling one outside an active dispatch throws anError. Active means inside a handler running under
agent.serve() or agent.fetch, or inside a test context.
wrapTool
defineTool fits functions you own. wrapTool builds a Rebuno-routed tool from
a name plus an invoke(args) seam. Use it for tools that aren’t plain
callables, like framework tool objects or schema-only tools:
nameis the tool id the LLM sees and the kernel sees, so put any namespace prefix directly in it.inputSchemais passed through to the returned tool for frameworks that read it.toResultmaps the raw return before it’s recorded. Defaults to identity.transformArgsmaps the argument object before it’s recorded and passed toinvoke, for something like null-stripping. Defaults to a shallow copy.
MCP tools
wrapMcpTool and wrapMcpTools wrap
Model Context Protocol tool descriptors, so
MCP tools get the same treatment as native ones.
- Descriptors carry
name,description, andinputSchema, the spec field names. prefixnamespaces the tool id. The LLM and the kernel see`${prefix}_${name}`, while the MCP server (viacall) sees the barename. An empty prefix uses the name as-is.- The result is flattened from a standard MCP
CallToolResultby default, preferring structured content and otherwise joining text blocks. Override it withtoResult. - Null arguments are stripped by default, since LLMs often fill optional fields
with
nulland typed MCP parameters reject it.
wrapMcpTool does one descriptor; wrapMcpTools maps over a list.