tool_call step. Policy
applies to it, it replays on resume, and it shows up in the audit trail.
@tool
Decorate an async function:
functools.wraps), so frameworks
that introspect your function bind it unchanged. Hand tools to a framework as a
plain list:
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 raisesToolError, 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 raise.@tool and wrap_tool catch the
PolicyError and return a string instead:
rebuno.step() raises PolicyError
normally, since nothing reads its result as a tool response.
Blocking work
Offload blocking or CPU-bound work to a thread:Calling context
A tool records against the current execution. Calling one outside an active dispatch raisesRuntimeError. Active means inside a handler running under
agent.run(), or inside a test context.
wrap_tool
@tool fits plain functions. wrap_tool builds a Rebuno-routed callable 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 (via__name__) and the kernel sees, so put any namespace prefix directly in it.args_schema’spropertiesandrequiredbuild a keyword-only signature that frameworks introspect. The schema itself is exposed on__input_schema__. The wrapper still accepts**kwargs, so an argument outside the schema is passed through.to_resultmaps the raw return before it’s recorded. Defaults to identity.transform_argsmaps the argument dict before it’s recorded and passed toinvoke, for something like null-stripping. Defaults to identity.
MCP tools
rebuno.mcp wraps Model Context Protocol
tool descriptors, so MCP tools get the same treatment as native ones.
- Descriptors can be attribute-style (the official
mcpSDK’sTool, a fastmcp tool) or plain dicts. Both work. prefixnamespaces the tool id. The LLM and the kernel seef"{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 withto_result. - Null arguments are stripped by default, since LLMs often fill optional fields
with
nulland typed MCP parameters reject it.
wrap_mcp_tool does one descriptor; wrap_mcp_tools maps over a list.