Skip to content

Tools

The @tool decorator and tool primitives. For the conceptual model and the LLM-tool-loop interaction see concepts/behaviors, and for tools inside a pack see the authoring packs guide.

Decorator + base

Register a function as a Tool.

The decorated function's signature is (args: input_schema, ctx: ToolContext) -> output_schema. The runtime validates args against input_schema before invocation and validates the return value against output_schema after.

Keyword-only on purpose — too many fields for safe positional binding.

Metadata plus the callable for a runtime-invokable tool.

fn runs as fn(args, ctx): args is validated against input_schema before invocation and the return value against output_schema after (both Pydantic models). cost_per_call feeds the budget's cost dimension; deterministic declares whether replay may re-invoke (CONTRACT v0.7 #7 — False means replay must serve the recorded fixture or fail loud). Instances come from @tool; the runtime owns invocation and the tool.requested / tool.responded event pair.

to_definition()

Provider-facing tool definition.

Sent in the tools= parameter to LLMProvider.complete(). Anthropic and OpenAI both accept a similar shape; the provider translates if needed.

What a tool function body sees. CONTRACT v0.7 #5.

Deliberately narrow: the triggering behavior and event id, the active frame, an idempotency_key to forward to external APIs (the runtime never uses it for dedupe — caching is the cache's job), the decorator's timeout_seconds (advisory; the runtime does not preempt), and a per-tool logger. No graph reference — tools that need graph state close over it explicitly at registration (see make_graph_query_tool). external_io_mode defaults to "forbid"; runtime dispatch supplies "runtime_recorded" and an intentional replay bypass must say "live_unrecorded".

Registry helpers

Return a copy of the global @tool registry, in registration order.

This is the list a new Runtime snapshots when tools=[...] is not passed. It is a copy: mutating the returned list neither registers nor unregisters anything — use the @tool decorator to add and :func:clear_tool_registry to reset.

Empty the global @tool registry. Test-isolation helper.

Decoration pushes into a module-level list that persists for the life of the process, so tests that register tools clear it between cases (mirroring the @behavior registry's isolation pattern). Runtimes constructed before the clear keep working — the registry is snapshotted at runtime construction, not read per-dispatch.