Multi-Agent Workflows
Use Agent.asTool() to delegate work from one agent to specialist agents.
Use multiple agents when one coordinator should break a task into specialist work. In Anvia, the simplest pattern is to turn specialist agents into tools with agent.asTool(...), then attach those tools to a coordinator agent.
Build Specialist Agents
import { AgentBuilder } from "@anvia/core";
const supportAgent = new AgentBuilder("support", model)
.name("Support Specialist")
.description("Analyze customer impact and support next steps.")
.instructions("Return concise support triage notes using only the provided facts.")
.build();
const engineeringAgent = new AgentBuilder("engineering", model)
.name("Engineering Specialist")
.description("Analyze technical causes, diagnostics, and engineering next steps.")
.instructions("Return concrete diagnostics and avoid unverified root-cause claims.")
.build();Specialist agents should have narrow instructions. Give each one a clear role and output shape.
Expose Agents as Tools
const coordinator = new AgentBuilder("coordinator", model)
.name("Incident Coordinator")
.instructions(
[
"Coordinate specialist agents through tools.",
"Give each specialist a short task based only on the user request.",
"Combine their findings into one concise incident brief.",
].join("\n"),
)
.tools([
supportAgent.asTool({ name: "ask_support_agent" }),
engineeringAgent.asTool({ name: "ask_engineering_agent" }),
])
.defaultMaxTurns(4)
.build();asTool(...) creates a tool with one input field:
{ prompt: string }When the coordinator calls the tool, Anvia prompts the specialist agent and returns the specialist's final text as the tool result.
By default, a specialist exposed with asTool(...) is opaque while it runs. The parent stream shows the parent tool_call and final tool_result, but not the child agent's intermediate turns.
Enable nested streaming when your UI should show specialist progress:
const coordinator = new AgentBuilder("coordinator", model)
.tools([
supportAgent.asTool({ name: "ask_support_agent", stream: true }),
engineeringAgent.asTool({ name: "ask_engineering_agent", stream: true }),
])
.build();When the parent runs with .stream(), child agent events arrive as agent_tool_event values. The parent model still receives only the final specialist output as the normal tool result.
Nested progress is best-effort: the parent agent and child agent models must both support streaming. If nested streaming is unavailable, the agent-tool still behaves like a normal opaque asTool(...) call and returns the specialist's final output.
Add an event store when you need to replay or inspect nested child-agent progress after the run.
For memory boundaries in coordinator/specialist systems, see Multi-Agent Memory.
Run With Tool Concurrency
const response = await coordinator
.prompt("Prepare an incident brief for a webhook retry failure.")
.withToolConcurrency(2)
.send();
console.log(response.output);Use .withToolConcurrency(...) when independent specialist tools can run at the same time.
When to Use This Pattern
| Pattern | Use it when |
|---|---|
agent.asTool(...) | A coordinator should decide which specialists to call during a prompt run and child progress can remain hidden |
agent.asTool({ stream: true }) | A coordinator should decide which specialists to call and the caller should see child progress during streaming |
| Parallel pipelines | You already know every branch should run |
| Studio multiple agents | You want several agents available in one local UI |
For runnable examples, see examples/cookbook/07_multi_agent/01-agent-as-tool.ts, examples/cookbook/07_multi_agent/03-streaming-agent-tools.ts, and examples/cookbook/07_multi_agent/04-agent-event-store.ts.
