@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
182 lines (141 loc) • 6.81 kB
Markdown
# Agent networks
> **Deprecated — Use supervisor agents:** Agent networks are deprecated and will be removed in a future major release. [Supervisor agents](https://mastra.ai/docs/agents/supervisor-agents) using `agent.stream()` or `agent.generate()` are now the recommended approach. It provides the same multi-agent coordination with better control, a simpler API, and easier debugging.
>
> See the [migration guide](https://mastra.ai/guides/migrations/network-to-supervisor) to upgrade.
A **routing agent** uses an LLM to interpret a request and decide which primitives (subagents, workflows, or tools) to call, in what order, and with what data.
## Create an agent network
Configure a routing agent with `agents`, `workflows`, and `tools`. Memory is required as `.network()` uses it to store task history and determine when a task is complete.
Each primitive needs a clear `description` so the routing agent can decide which to use. For workflows and tools, `inputSchema` and `outputSchema` also help the router determine the right inputs.
```typescript
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
import { LibSQLStore } from '@mastra/libsql'
import { researchAgent } from './research-agent'
import { writingAgent } from './writing-agent'
import { cityWorkflow } from '../workflows/city-workflow'
import { weatherTool } from '../tools/weather-tool'
export const routingAgent = new Agent({
id: 'routing-agent',
name: 'Routing Agent',
instructions: `
You are a network of writers and researchers. The user will ask you to research a topic. Always respond with a complete report—no bullet points. Write in full paragraphs, like a blog post. Do not answer with incomplete or uncertain information.`,
model: 'openai/gpt-5.4',
agents: {
researchAgent,
writingAgent,
},
workflows: {
cityWorkflow,
},
tools: {
weatherTool,
},
memory: new Memory({
storage: new LibSQLStore({
id: 'mastra-storage',
url: 'file:../mastra.db',
}),
}),
})
```
> **Note:** Subagents need a `description` on the `Agent` instance. Workflows and tools need a `description` plus `inputSchema` and `outputSchema` on `createWorkflow()` or `createTool()`.
## Call the network
Call `.network()` with a user message. The method returns a stream of events you can iterate over.
```typescript
const result = await routingAgent.network('Tell me three cool ways to use Mastra')
for await (const chunk of result) {
console.log(chunk.type)
if (chunk.type === 'network-execution-event-step-finish') {
console.log(chunk.payload.result)
}
}
```
## Structured output
Pass `structuredOutput` to get typed, validated results. Use `objectStream` for partial objects as they generate.
```typescript
import { z } from 'zod'
const resultSchema = z.object({
summary: z.string().describe('A brief summary of the findings'),
recommendations: z.array(z.string()).describe('List of recommendations'),
confidence: z.number().min(0).max(1).describe('Confidence score'),
})
const stream = await routingAgent.network('Research AI trends', {
structuredOutput: { schema: resultSchema },
})
for await (const partial of stream.objectStream) {
console.log('Building result:', partial)
}
const final = await stream.object
console.log(final?.summary)
```
## Approve and decline tool calls
When a primitive requires approval, the stream emits an `agent-execution-approval` or `tool-execution-approval` chunk. Use `approveNetworkToolCall()` or `declineNetworkToolCall()` to respond.
Network approval uses snapshots to capture execution state. Ensure a [storage provider](https://mastra.ai/docs/memory/storage) is enabled in your Mastra instance.
```typescript
const stream = await routingAgent.network('Perform some sensitive action', {
memory: {
thread: 'user-123',
resource: 'my-app',
},
})
for await (const chunk of stream) {
if (chunk.type === 'agent-execution-approval' || chunk.type === 'tool-execution-approval') {
// Approve
const approvedStream = await routingAgent.approveNetworkToolCall(chunk.payload.toolCallId, {
runId: stream.runId,
memory: { thread: 'user-123', resource: 'my-app' },
})
for await (const c of approvedStream) {
if (c.type === 'network-execution-event-step-finish') {
console.log(c.payload.result)
}
}
}
}
```
To decline instead, call `declineNetworkToolCall()` with the same arguments.
## Suspend and resume
When a primitive calls `suspend()`, the stream emits a suspension chunk (e.g., `tool-execution-suspended`). Use `resumeNetwork()` to provide the requested data and continue execution.
```typescript
const stream = await routingAgent.network('Delete the old records', {
memory: { thread: 'user-123', resource: 'my-app' },
})
for await (const chunk of stream) {
if (chunk.type === 'workflow-execution-suspended') {
console.log(chunk.payload.suspendPayload)
}
}
// Resume with user confirmation
const resumedStream = await routingAgent.resumeNetwork(
{ confirmed: true },
{
runId: stream.runId,
memory: { thread: 'user-123', resource: 'my-app' },
},
)
for await (const chunk of resumedStream) {
if (chunk.type === 'network-execution-event-step-finish') {
console.log(chunk.payload.result)
}
}
```
### Automatic resumption
Set `autoResumeSuspendedTools` to `true` so the network resumes suspended primitives based on the user's next message. This creates a conversational flow where users provide the required information naturally.
```typescript
const stream = await routingAgent.network('Delete the old records', {
autoResumeSuspendedTools: true,
memory: { thread: 'user-123', resource: 'my-app' },
})
```
Requirements for automatic resumption:
- **Memory configured**: The agent needs memory to track suspended tools across messages.
- **Same thread**: The follow-up message must use the same `thread` and `resource` identifiers.
- **`resumeSchema` defined**: The tool must define a `resumeSchema` so the network can extract data from the user's message.
| | Manual (`resumeNetwork`) | Automatic (`autoResumeSuspendedTools`) |
| -------- | ---------------------------------------------- | ----------------------------------------- |
| Best for | Custom UIs with approval buttons | Chat-style interfaces |
| Control | Full control over resume timing and data | Network extracts data from user's message |
| Setup | Handle suspension chunks, call `resumeNetwork` | Set flag, define `resumeSchema` on tools |
## Related
- [Supervisor agents](https://mastra.ai/docs/agents/supervisor-agents)
- [Migration: `.network()` to supervisor agents](https://mastra.ai/guides/migrations/network-to-supervisor)