LlmClient. AgentRegistry lets you register named agents and invoke them from code or from inside another agent’s tool loop. Sub-agents run entirely in-process — there are no HTTP round-trips, no additional servers, and no separate orchestration framework to learn.
AgentRegistry
Import AgentRegistry from anvil/agent:
registry.register(name, config)
Register a named agent with its RunAgentOptions (the same options runAgent accepts, minus messages):
register returns this, so you can chain calls.
registry.call(name, input, overrides?)
Invoke a registered agent by name. Pass a string for a single user message, or a full ModelMessage[] conversation. Returns AgentRunResult.
overrides to adjust config for a specific call without modifying the registration:
The final text response from the sub-agent.
The full conversation, including all tool calls and results.
The number of model turns that ran.
Accumulated token counts across all turns.
Accumulated USD cost.
true if the loop stopped because it hit maxIterations rather than finishing naturally.registry.has(name) and registry.names()
Check membership and list registered names:
agentAsTool
Wrap a registered agent as an AgentTool so an orchestrator agent can delegate to it during its own tool loop. The sub-agent’s final text becomes the tool result:
The registry that contains the target agent.
The name of the registered agent to wrap.
The tool name advertised to the parent model. Defaults to
call_<name>.The tool description. Defaults to a generic delegation prompt that includes the agent name.
Config overrides applied every time the parent model delegates to this sub-agent.
message input schema — the parent model passes a plain string describing the subtask, which becomes the sub-agent’s first user message.
withAgents middleware and callAgent helper
Use withAgents to attach a registry to ctx.state.agents, then use callAgent anywhere in your handler tree:
callAgent(ctx, name, input) is sugar for getAgents(ctx).call(name, input). It throws a clear error if no registry is attached.
Full orchestration example
This example registers a researcher and a summarizer, then wires them together in a parent orchestrator agent that the client talks to:POST /report route now orchestrates the two sub-agents. The orchestrator model decides when to call research and summarize; each sub-agent runs to completion in-process and returns its text as the tool result.
Sub-agents run synchronously in the parent’s event loop via
runAgent — no network calls, no spawned processes. The parent agent’s maxIterations counts its own turns; sub-agent turns are independent.Sub-agent execution model
agentAsTool calls registry.call(name, message) inside execute, which calls runAgent directly. The entire sub-agent loop runs to completion before execute returns. This means:
- No HTTP round-trips — the sub-agent never makes an HTTP request to itself.
- No shared streaming — the parent stream does not include the sub-agent’s intermediate events; only its final text appears as a tool result.
- Nested cost tracking — each sub-agent call uses the client’s internal cost accumulator, so
client.totalCostUsdreflects the total across all agents sharing that client.