@mastra/mcp-docs-server 1.2.13 → 1.2.14-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.docs/docs/agents/a2a.md +1 -1
- package/.docs/docs/agents/acp.md +1 -1
- package/.docs/docs/agents/agent-approval.md +1 -1
- package/.docs/docs/agents/networks.md +2 -2
- package/.docs/docs/agents/overview.md +2 -2
- package/.docs/docs/agents/using-tools.md +2 -2
- package/.docs/docs/capabilities/channels/overview.md +1 -1
- package/.docs/docs/{agents/supervisor-agents.md → capabilities/subagents.md} +58 -58
- package/.docs/docs/deployment/sandbox.md +95 -1
- package/.docs/docs/getting-started/develop.md +2 -0
- package/.docs/docs/harness/agent-controller.md +370 -0
- package/.docs/docs/long-running-agents/background-tasks.md +1 -1
- package/.docs/docs/long-running-agents/goals.md +3 -3
- package/.docs/docs/mcp/overview.md +222 -281
- package/.docs/docs/memory/overview.md +2 -2
- package/.docs/docs/observability/integrations/exporters/confident-ai.md +140 -0
- package/.docs/docs/observability/integrations/overview.md +1 -1
- package/.docs/docs/observability/overview.md +122 -8
- package/.docs/docs/observability/tracing/overview.md +2 -2
- package/.docs/docs/server/mastra-client.md +1 -1
- package/.docs/docs/server/server-adapters.md +2 -0
- package/.docs/docs/storage/overview.md +2 -2
- package/.docs/guides/build-your-ui/copilotkit/channels.md +49 -39
- package/.docs/guides/concepts/multi-agent-systems.md +7 -7
- package/.docs/guides/guide/coding-agent.md +2 -2
- package/.docs/guides/guide/research-coordinator.md +1 -1
- package/.docs/guides/migrations/network-to-supervisor.md +1 -1
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/cortecs.md +2 -1
- package/.docs/models/providers/digitalocean.md +9 -9
- package/.docs/models/providers/kilo.md +1 -1
- package/.docs/models/providers/llmgateway.md +1 -1
- package/.docs/models/providers/opencode.md +2 -1
- package/.docs/reference/acp/acp-agent.md +1 -1
- package/.docs/reference/agent-controller/agent-controller-class.md +195 -506
- package/.docs/reference/agent-controller/session.md +274 -111
- package/.docs/reference/agents/network.md +1 -1
- package/.docs/reference/ai-sdk/handle-network-stream.md +1 -1
- package/.docs/reference/ai-sdk/network-route.md +1 -1
- package/.docs/reference/cli/create-mastra.md +1 -1
- package/.docs/reference/editor/versioning.md +1 -1
- package/.docs/reference/evals/rubric.md +1 -1
- package/.docs/reference/file-based-agents/observability.md +2 -2
- package/.docs/reference/file-based-agents/storage.md +1 -1
- package/.docs/reference/file-based-agents/subagents.md +1 -1
- package/.docs/reference/file-based-agents/tools.md +1 -1
- package/.docs/reference/observability/tracing/configuration.md +1 -1
- package/.docs/reference/observability/tracing/exporters/confident-ai.md +138 -0
- package/.docs/reference/observability/tracing/interfaces.md +29 -0
- package/.docs/reference/signals/signal-provider.md +2 -0
- package/.docs/reference/tools/mcp-server.md +1 -1
- package/.docs/reference/tools/submit-plan-tool.md +1 -1
- package/.docs/reference/workspace/railway-sandbox.md +5 -5
- package/CHANGELOG.md +14 -0
- package/package.json +3 -3
- package/.docs/docs/agent-controller/channels.md +0 -111
- package/.docs/docs/agent-controller/modes.md +0 -147
- package/.docs/docs/agent-controller/overview.md +0 -136
- package/.docs/docs/agent-controller/session.md +0 -161
- package/.docs/docs/agent-controller/subagents.md +0 -110
- package/.docs/docs/agent-controller/threads-and-state.md +0 -148
- package/.docs/docs/agent-controller/tool-approvals.md +0 -147
- package/.docs/docs/mcp/mcp-apps.md +0 -306
- package/.docs/docs/observability/config.md +0 -140
- package/.docs/docs/observability/storage.md +0 -81
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
-
|
|
3
|
-
# Modes
|
|
4
|
-
|
|
5
|
-
Modes define the different behaviors an AgentController can run. Each mode layers its own instructions and tool overrides on top of a shared backing agent, so the same agent can act as a planner in one mode and an executor in another. The AgentController keeps exactly one mode active at a time and carries the thread and state across switches, plus handles the transition between them.
|
|
6
|
-
|
|
7
|
-
Every AgentController needs at least one mode, the `modes` array is required, and the AgentController throws at construction if it's empty. A single-purpose AgentController still defines one mode. Multiple modes are how you give a session more than one behavior to switch between.
|
|
8
|
-
|
|
9
|
-
A mode supplies three things that change how the agent behaves:
|
|
10
|
-
|
|
11
|
-
- **Instructions**: layered on top of the backing agent's own instructions while the mode is active.
|
|
12
|
-
- **Tools**: either replacing or adding to the backing agent's tools (see [Mode tool overrides](#mode-tool-overrides)).
|
|
13
|
-
- **Model**: an optional `defaultModelId` to bootstrap model selection when the session enters the mode.
|
|
14
|
-
|
|
15
|
-
Because every mode shares the same backing agent, thread, and state, switching modes changes how the agent behaves without losing conversation context.
|
|
16
|
-
|
|
17
|
-
## Quickstart
|
|
18
|
-
|
|
19
|
-
Import the `AgentController` class and create a new instance with your agent and modes:
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
import { AgentController } from '@mastra/core/agent-controller'
|
|
23
|
-
import { myAgent } from './agents'
|
|
24
|
-
|
|
25
|
-
const agentController = new AgentController({
|
|
26
|
-
id: 'multi-mode',
|
|
27
|
-
agent: myAgent,
|
|
28
|
-
modes: [
|
|
29
|
-
{
|
|
30
|
-
id: 'plan',
|
|
31
|
-
name: 'Plan',
|
|
32
|
-
metadata: { default: true },
|
|
33
|
-
instructions: 'Reason about the task before making changes.',
|
|
34
|
-
},
|
|
35
|
-
{ id: 'build', name: 'Build', instructions: 'Implement the approved plan.' },
|
|
36
|
-
],
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
await agentController.init()
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Defining modes
|
|
43
|
-
|
|
44
|
-
Each mode requires an `id`. When a top-level `agent` is provided, modes layer instructions and tool overrides on the shared agent. Each mode can also specify a `defaultModelId` to bootstrap model selection:
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
import { AgentController } from '@mastra/core/agent-controller'
|
|
48
|
-
|
|
49
|
-
const agentController = new AgentController({
|
|
50
|
-
id: 'multi-mode',
|
|
51
|
-
agent: myAgent,
|
|
52
|
-
modes: [
|
|
53
|
-
{
|
|
54
|
-
id: 'plan',
|
|
55
|
-
name: 'Plan',
|
|
56
|
-
metadata: { default: true },
|
|
57
|
-
defaultModelId: 'anthropic/claude-sonnet-4-6',
|
|
58
|
-
instructions: 'Reason about the task before making changes.',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
id: 'build',
|
|
62
|
-
name: 'Build',
|
|
63
|
-
defaultModelId: 'anthropic/claude-sonnet-4-6',
|
|
64
|
-
instructions: 'Implement the approved plan.',
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
})
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Mode tool overrides
|
|
71
|
-
|
|
72
|
-
Modes support two strategies for tool configuration. Use `tools` to replace the backing agent's tools entirely, or `additionalTools` to layer extra tools on top:
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
// Replace — agent sees only these tools in plan mode
|
|
76
|
-
const planMode = { id: 'plan', tools: { planTool } }
|
|
77
|
-
|
|
78
|
-
// Augment — agent keeps its own tools plus these
|
|
79
|
-
const buildMode = { id: 'build', additionalTools: { deployTool } }
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
You can't set both `tools` and `additionalTools` on the same mode.
|
|
83
|
-
|
|
84
|
-
### Restricting tool visibility
|
|
85
|
-
|
|
86
|
-
`tools` and `additionalTools` control which tools are **added** to a mode's run, they don't hide the backing agent's own tools. To restrict which of those tools the model can actually see and call, set `availableTools`:
|
|
87
|
-
|
|
88
|
-
```typescript
|
|
89
|
-
const reviewMode = {
|
|
90
|
-
id: 'review',
|
|
91
|
-
name: 'Review',
|
|
92
|
-
// Only these tools are visible to the model in this mode.
|
|
93
|
-
availableTools: ['view', 'find_files', 'search_content'],
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
`availableTools` is a per-mode visibility allowlist that matches each tool by its final exposed name:
|
|
98
|
-
|
|
99
|
-
- **`undefined`** (default): no mode-level restriction: every tool is visible.
|
|
100
|
-
- **`[]`**: no tools are available for this mode.
|
|
101
|
-
- A denied tool stays hidden even when the list includes it. Per-tool and per-category `deny` rules in your permission config always take precedence.
|
|
102
|
-
|
|
103
|
-
Workspace tools use the same list as every other tool, reference them by their exposed names (`view`, `write_file`, `find_files`, etc.). Visibility is enforced at LLM-call time, so the model never sees, and can't attempt to call, a tool outside the allowlist.
|
|
104
|
-
|
|
105
|
-
### Mode transitions
|
|
106
|
-
|
|
107
|
-
A mode can declare a `transitionsTo` target. When the `submit_plan` built-in tool runs in that mode, the AgentController transitions to the target mode on approval:
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
const planMode = {
|
|
111
|
-
id: 'plan',
|
|
112
|
-
name: 'Plan',
|
|
113
|
-
transitionsTo: 'build',
|
|
114
|
-
instructions: 'Reason about the task and submit a plan.',
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
On plan approval, the AgentController automatically switches to `build` mode. On rejection, the agent remains in `plan` mode to revise.
|
|
119
|
-
|
|
120
|
-
## Switching modes
|
|
121
|
-
|
|
122
|
-
The active mode lives on the Session, so call `agentController.session.mode.switch()` to change it. The switch aborts any in-progress generation and saves the current model to the outgoing mode, plus emits a `mode_changed` event. It then resolves the incoming mode's model and, when one resolves, applies it and emits a `model_changed` event:
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
await agentController.session.mode.switch({ modeId: 'build' })
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Querying modes
|
|
129
|
-
|
|
130
|
-
The AgentController exposes the full mode catalog, while the Session tracks which mode is active. Use `agentController.listModes()` to read every configured mode, `agentController.session.mode.get()` for the active mode ID, and `agentController.session.mode.resolve()` for the active mode's full definition:
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
// List all configured modes
|
|
134
|
-
const modes = agentController.listModes()
|
|
135
|
-
|
|
136
|
-
// Get the current mode ID
|
|
137
|
-
const modeId = agentController.session.mode.get()
|
|
138
|
-
|
|
139
|
-
// Get the full mode object
|
|
140
|
-
const mode = agentController.session.mode.resolve()
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
## Related
|
|
144
|
-
|
|
145
|
-
- [AgentController overview](https://mastra.ai/docs/agent-controller/overview)
|
|
146
|
-
- [Threads and state](https://mastra.ai/docs/agent-controller/threads-and-state)
|
|
147
|
-
- [API reference](https://mastra.ai/reference/agent-controller/agent-controller-class)
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
-
|
|
3
|
-
# AgentController overview
|
|
4
|
-
|
|
5
|
-
> **Beta:** The `AgentController` feature is in beta stage and subject to breaking changes in minor versions until it graduates from its beta status.
|
|
6
|
-
|
|
7
|
-
The AgentController is a session controller for building interactive agent applications.
|
|
8
|
-
|
|
9
|
-
It handles the runtime concerns between your UI and the agent loop. These include conversation threads, mode switches, and persistent state. It also gates tool execution with approvals and coordinates subagents. You can focus on what your agent does rather than how to wire it together.
|
|
10
|
-
|
|
11
|
-
An AgentController exposes a [`Session`](https://mastra.ai/docs/agent-controller/session), the per-conversation runtime state that tracks the active mode, model, thread binding, permission grants, follow-up queue, and token usage. The AgentController is the shared host. The Session is the conversation running inside it. In a multi-user host, the same AgentController can back many Sessions at once.
|
|
12
|
-
|
|
13
|
-
[Mastra Code](https://code.mastra.ai/) is the flagship AgentController implementation. It's a terminal-based coding agent with multi-model support, persistent conversations, and plan-then-execute workflows.
|
|
14
|
-
|
|
15
|
-
## What you can build
|
|
16
|
-
|
|
17
|
-
The AgentController gives you the runtime pieces to release interactive agent applications. Each outcome below maps to a capability you can use today:
|
|
18
|
-
|
|
19
|
-
- **Resume a conversation exactly where the user left off.** Persistent [threads and state](https://mastra.ai/docs/agent-controller/threads-and-state) reload the active mode, model, and progress across restarts, so a coding agent or assistant picks up mid-task instead of starting over.
|
|
20
|
-
- **Gate destructive actions behind human approval.** [Tool approvals and permission policies](https://mastra.ai/docs/agent-controller/tool-approvals) let you require confirmation for risky operations like file writes or deployments, while trusted tools run automatically.
|
|
21
|
-
- **Move a task through distinct phases without losing context.** [Modes](https://mastra.ai/docs/agent-controller/modes) switch the agent's instructions, tools, and model on the same thread, so you can build a plan-then-execute coding agent or a research-then-draft assistant.
|
|
22
|
-
- **Let users pick the right model for each step.** Per-mode [model management](https://mastra.ai/reference/agent-controller/agent-controller-class) switches models at runtime and tracks usage, which powers copilot UIs where users trade speed for capability.
|
|
23
|
-
- **Delegate focused work to child agents.** [Subagents](https://mastra.ai/docs/agent-controller/subagents) run subtasks with constrained tools and can fork the parent conversation, so a research mode can spin off web search or code review without polluting the main thread.
|
|
24
|
-
- **Drive a live UI from agent activity.** The [event system](https://mastra.ai/docs/agent-controller/session) emits typed events and coalesced display snapshots, so your TUI or web app reflects message updates, mode changes, and pending approvals in real time.
|
|
25
|
-
- **Run long-lived autonomous agents.** Structured task lists, interval handlers, and observational memory keep background task runners on track and let them learn across threads.
|
|
26
|
-
|
|
27
|
-
## When to use the AgentController
|
|
28
|
-
|
|
29
|
-
Use the AgentController when your application needs:
|
|
30
|
-
|
|
31
|
-
- Multiple agent modes that share one conversation thread (e.g., plan → build → review)
|
|
32
|
-
- A control layer between your UI and the agent loop (model switching, state persistence, thread management)
|
|
33
|
-
- Tool approval flows and permission policies for human-in-the-loop gating
|
|
34
|
-
- Subagent orchestration to delegate focused subtasks with constrained tools
|
|
35
|
-
- Session continuity with persistent threads, state, and observational memory across restarts
|
|
36
|
-
|
|
37
|
-
You could assemble all of this yourself on top of the [Agent class](https://mastra.ai/docs/agents/overview), which exposes the full agent loop, tools, and memory. The AgentController provides opinionated defaults for an ongoing session where the agent acts as a collaborator rather than a one-shot endpoint. Reach for the Agent class directly when you want full control or a request-response call. Reach for the AgentController when you want the collaborative-session model without building the runtime around it.
|
|
38
|
-
|
|
39
|
-
## Key capabilities
|
|
40
|
-
|
|
41
|
-
- **Session**: Per-conversation state: active thread, mode, model, grants, follow-ups, token usage, and the display snapshot: accessed through `agentController.session`. See [Session](https://mastra.ai/docs/agent-controller/session).
|
|
42
|
-
- **Modes**: Define distinct agent personalities (instructions, tools, model) and switch between them without losing conversation context. See [Modes](https://mastra.ai/docs/agent-controller/modes).
|
|
43
|
-
- **Threads and state**: Persist conversations and structured state across sessions, users, and mode switches. See [Threads and state](https://mastra.ai/docs/agent-controller/threads-and-state).
|
|
44
|
-
- **Subagents**: Spawn focused child agents with constrained tools for subtasks, optionally forking the parent conversation. See [Subagents](https://mastra.ai/docs/agent-controller/subagents).
|
|
45
|
-
- **Tool approvals and permissions**: Configure which tools require user confirmation and grant session-wide exceptions, plus handle interactive tool suspension. See [Tool approvals](https://mastra.ai/docs/agent-controller/tool-approvals).
|
|
46
|
-
- **Model management**: Switch models per-mode at runtime, track usage, and resolve gateway-backed models through Mastra's [model router](https://mastra.ai/models).
|
|
47
|
-
- **Follow-ups and steering**: Queue messages while the agent is running, or inject mid-stream instructions to redirect the agent. Built on [signals](https://mastra.ai/docs/long-running-agents/signals).
|
|
48
|
-
- **Event system**: Subscribe to typed events (message updates, mode changes, tool approvals) or coalesced `AgentControllerDisplayState` snapshots to drive your UI. See [Events](https://mastra.ai/reference/agent-controller/agent-controller-class).
|
|
49
|
-
- **Observational memory**: Automatic summarization and reflection across threads for long-running agent sessions. See [Observational memory](https://mastra.ai/docs/memory/observational-memory).
|
|
50
|
-
|
|
51
|
-
## Quickstart
|
|
52
|
-
|
|
53
|
-
Import the `AgentController` class and create a new instance with an agent, storage backend, and modes:
|
|
54
|
-
|
|
55
|
-
```typescript
|
|
56
|
-
import { Agent } from '@mastra/core/agent'
|
|
57
|
-
import { AgentController } from '@mastra/core/agent-controller'
|
|
58
|
-
import { LibSQLStore } from '@mastra/libsql'
|
|
59
|
-
|
|
60
|
-
const agent = new Agent({
|
|
61
|
-
id: 'assistant',
|
|
62
|
-
name: 'assistant',
|
|
63
|
-
instructions: 'Help the user plan and complete tasks.',
|
|
64
|
-
model: 'openai/gpt-5.6-sol',
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
const agentController = new AgentController({
|
|
68
|
-
id: 'my-agent',
|
|
69
|
-
agent,
|
|
70
|
-
storage: new LibSQLStore({ id: 'agent-storage', url: 'file:./data.db' }),
|
|
71
|
-
modes: [
|
|
72
|
-
{
|
|
73
|
-
id: 'plan',
|
|
74
|
-
name: 'Plan',
|
|
75
|
-
metadata: { default: true },
|
|
76
|
-
instructions: 'Reason about changes before making them.',
|
|
77
|
-
},
|
|
78
|
-
{ id: 'build', name: 'Build', instructions: 'Implement the approved plan.' },
|
|
79
|
-
],
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
agentController.subscribe(event => {
|
|
83
|
-
if (event.type === 'message_update') {
|
|
84
|
-
console.log(event.message)
|
|
85
|
-
}
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
await agentController.init()
|
|
89
|
-
await agentController.selectOrCreateThread()
|
|
90
|
-
await agentController.sendMessage({ content: 'Hello!' })
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Visit the [AgentController reference](https://mastra.ai/reference/agent-controller/agent-controller-class) for the full constructor parameters and method signatures.
|
|
94
|
-
|
|
95
|
-
## Architecture
|
|
96
|
-
|
|
97
|
-
The AgentController sits between your application layer and the underlying agent loop:
|
|
98
|
-
|
|
99
|
-
```text
|
|
100
|
-
┌───────────────────────────────────────┐
|
|
101
|
-
│ Your App (TUI/Web/API) │
|
|
102
|
-
└───────────────────────────────────────┘
|
|
103
|
-
│ commands ▲ events
|
|
104
|
-
▼ │
|
|
105
|
-
┌───────────────────────────────────────┐
|
|
106
|
-
│ AgentController │
|
|
107
|
-
│ Config · storage · threads │
|
|
108
|
-
│ permissions · subagents · events │
|
|
109
|
-
│ │
|
|
110
|
-
│ ┌─────────────────────────────────┐ │
|
|
111
|
-
│ │ agentController.session │ │
|
|
112
|
-
│ │ identity · thread · mode │ │
|
|
113
|
-
│ │ model · run · grants │ │
|
|
114
|
-
│ │ display state │ │
|
|
115
|
-
│ └─────────────────────────────────┘ │
|
|
116
|
-
└───────────────────────────────────────┘
|
|
117
|
-
│
|
|
118
|
-
▼
|
|
119
|
-
┌───────────────────────────────────────┐
|
|
120
|
-
│ Agent + Memory + Tools │
|
|
121
|
-
└───────────────────────────────────────┘
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Your app sends commands, send a message, switch mode, approve a tool call, and receives typed events such as `message_update` and `tool_approval_required`.
|
|
125
|
-
|
|
126
|
-
The AgentController manages the lifecycle internally. It persists threads and routes requests to the correct mode agent. It also enforces permissions and emits events as state changes.
|
|
127
|
-
|
|
128
|
-
## Next steps
|
|
129
|
-
|
|
130
|
-
- [Session](https://mastra.ai/docs/agent-controller/session): The per-conversation state on an AgentController
|
|
131
|
-
- [Modes](https://mastra.ai/docs/agent-controller/modes): Define and switch between agent personalities
|
|
132
|
-
- [Threads and state](https://mastra.ai/docs/agent-controller/threads-and-state): Manage persistent conversations
|
|
133
|
-
- [Subagents](https://mastra.ai/docs/agent-controller/subagents): Delegate focused subtasks
|
|
134
|
-
- [Tool approvals and permissions](https://mastra.ai/docs/agent-controller/tool-approvals): Human-in-the-loop gating
|
|
135
|
-
- [API reference](https://mastra.ai/reference/agent-controller/agent-controller-class): Full constructor and method docs
|
|
136
|
-
- 📹 [Mastra AgentController harness workshop](https://www.youtube.com/watch?v=tV1pSleP-LM)
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
-
|
|
3
|
-
# Session
|
|
4
|
-
|
|
5
|
-
A [`Session`](https://mastra.ai/reference/agent-controller/session) holds the live state of an AgentController. It identifies the user and active thread, along with the selected mode and model. It also stores permission grants, queued follow-ups, token usage, application state, and the display snapshot.
|
|
6
|
-
|
|
7
|
-
You reach it through `agentController.session`.
|
|
8
|
-
|
|
9
|
-
## What the Session tracks
|
|
10
|
-
|
|
11
|
-
The Session is the live state of a single user's interaction with the AgentController.
|
|
12
|
-
|
|
13
|
-
It answers who owns the session and which thread is bound. It also identifies the selected mode and model while tracking approvals, queued or running work, application state, and the snapshot to render.
|
|
14
|
-
|
|
15
|
-
A session has one active thread at a time but can list, switch between, and clone many threads over its lifetime. Anything that describes the current state lives here. The AgentController owns the shared infrastructure every session runs on.
|
|
16
|
-
|
|
17
|
-
Each session has its own identity and state. One AgentController can therefore serve many users at once, with a separate `resourceId` and Session preventing mode, grant, or active-thread data from leaking between users.
|
|
18
|
-
|
|
19
|
-
Calling `createSession` with the same `resourceId` returns the existing session (get-or-create), so a resource always resumes its own session.
|
|
20
|
-
|
|
21
|
-
The rest of this page walks through the Session's state. Each part is a focused sub-object on `agentController.session`:
|
|
22
|
-
|
|
23
|
-
- **Who and where**: [Identity](#identity) sets the stable session `id`, `ownerId`, and resource the session belongs to, and [Thread](#thread) tracks the currently bound thread.
|
|
24
|
-
- **How the agent behaves**: [Mode and model](#mode-and-model) controls which agent profile and model are active, and [Permission grants](#permission-grants) records what the user has approved to run without prompting.
|
|
25
|
-
- **What's happening right now**: [Run state](#run-state) reflects the in-flight generation, and [Follow-ups](#follow-ups) holds messages queued to send when it finishes.
|
|
26
|
-
- **What you store and render**: [State](#state) holds your application's structured data, and [Display state](#display-state) is the single snapshot your UI renders from.
|
|
27
|
-
|
|
28
|
-
The AgentController performs actions that change this state, switching threads, modes, or models, because those operations coordinate shared infrastructure and emit events. The Session is where you read the result. The sections below note this split where it matters.
|
|
29
|
-
|
|
30
|
-
## Identity
|
|
31
|
-
|
|
32
|
-
`session.identity` holds three stable identifiers for the conversation: a session `id`, an `ownerId`, and the resource ID. Threads are scoped to a resource ID, so this is what groups a conversation's threads together:
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
const sessionId = agentController.session.identity.getId()
|
|
36
|
-
const ownerId = agentController.session.identity.getOwnerId()
|
|
37
|
-
const resourceId = agentController.session.identity.getResourceId()
|
|
38
|
-
const threadId = agentController.session.thread.getId()
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
The session `id` and `ownerId` are stable for the life of the session, they don't change when the resource ID is switched. They mirror the `id` and `ownerId` fields on `SessionRecord` in storage, so storage layers can key sessions by a stable identifier rather than the mutable resource ID.
|
|
42
|
-
|
|
43
|
-
The resource ID is set when creating a session via [`agentController.createSession()`](https://mastra.ai/reference/agent-controller/agent-controller-class) and defaults to the agentController `id`. See [Resource IDs](https://mastra.ai/docs/agent-controller/threads-and-state) for how it scopes threads.
|
|
44
|
-
|
|
45
|
-
## Thread
|
|
46
|
-
|
|
47
|
-
`session.thread` owns the active thread binding and read access to threads and messages. The AgentController performs lifecycle transitions; the Session reads the result:
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// Lifecycle transitions live on the AgentController
|
|
51
|
-
await agentController.switchThread({ threadId: 'thread-abc123' })
|
|
52
|
-
|
|
53
|
-
// Reads live on the Session
|
|
54
|
-
const threads = await agentController.session.thread.list()
|
|
55
|
-
const messages = await agentController.session.thread.listActiveMessages()
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
See [Threads and state](https://mastra.ai/docs/agent-controller/threads-and-state) for the full lifecycle.
|
|
59
|
-
|
|
60
|
-
## Mode and model
|
|
61
|
-
|
|
62
|
-
The AgentController defines the available modes in `config.modes`. The Session tracks which mode and model are _currently_ selected:
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
// Switch mode (aborts the run, emits events)
|
|
66
|
-
await agentController.session.mode.switch({ modeId: 'build' })
|
|
67
|
-
|
|
68
|
-
// Read the current selection (Session state)
|
|
69
|
-
const modeId = agentController.session.mode.get()
|
|
70
|
-
const mode = agentController.session.mode.resolve()
|
|
71
|
-
const modelId = agentController.session.model.get()
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
See [Modes](https://mastra.ai/docs/agent-controller/modes) for how modes carry their own model.
|
|
75
|
-
|
|
76
|
-
## Permission grants
|
|
77
|
-
|
|
78
|
-
The AgentController owns permission _policy_, which categories or tools require approval. The Session owns the _grants_ a user makes during the conversation. A grant lets a tool run for the rest of the session without prompting again:
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
// Grant a category or tool for the rest of the session
|
|
82
|
-
agentController.session.grantCategory('edit')
|
|
83
|
-
agentController.session.grantTool('mastra_workspace_execute_command')
|
|
84
|
-
|
|
85
|
-
// Inspect current grants
|
|
86
|
-
const grants = agentController.session.getGrants()
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Grants are intentionally in-memory and reset when the session restarts. See [Tool approvals](https://mastra.ai/docs/agent-controller/tool-approvals) for the approval flow.
|
|
90
|
-
|
|
91
|
-
## Run state
|
|
92
|
-
|
|
93
|
-
`session.run` tracks the in-flight generation: whether a run is active, its run and trace IDs, and the abort signal. Use it to reflect run status in your UI:
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
if (agentController.session.run.isRunning()) {
|
|
97
|
-
// show a stop button
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Abort the active run (AgentController orchestration clears related state)
|
|
101
|
-
agentController.abort()
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Follow-ups
|
|
105
|
-
|
|
106
|
-
A user may want to add to the conversation while the agent is still working. Instead of dropping or interrupting those messages, the Session queues them on `session.followUps` and sends them when the current run finishes:
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
const queued = agentController.session.followUps.count()
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Queue a follow-up with `agentController.followUp({ content })`. To redirect the agent mid-run instead of waiting, use `agentController.steer({ content })`. Both build on [signals](https://mastra.ai/docs/long-running-agents/signals).
|
|
113
|
-
|
|
114
|
-
## State
|
|
115
|
-
|
|
116
|
-
`session.state` holds the conversation's application state, structured values that agents and the UI share, such as model preferences, feature flags, or progress.
|
|
117
|
-
|
|
118
|
-
The AgentController defines the shape with a `stateSchema`. The Session owns the live snapshot and validates updates against that schema. Every write emits `state_changed`:
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
const state = agentController.session.state.get()
|
|
122
|
-
await agentController.session.state.set({ theme: 'light' })
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
See [Threads and state](https://mastra.ai/docs/agent-controller/threads-and-state) for defining a schema.
|
|
126
|
-
|
|
127
|
-
## Display state
|
|
128
|
-
|
|
129
|
-
A conversation emits fine-grained events for streamed tokens and tool activity. Other events cover pending approvals, task updates, and token usage.
|
|
130
|
-
|
|
131
|
-
Subscribing to each event type and reassembling the current picture yourself is tedious and error-prone.
|
|
132
|
-
|
|
133
|
-
`session.displayState` does that work for you.
|
|
134
|
-
|
|
135
|
-
It's a reducer-maintained snapshot.
|
|
136
|
-
|
|
137
|
-
The Session keeps one `AgentControllerDisplayState` object and folds every agentController event into it as it happens, so the snapshot always reflects the latest state.
|
|
138
|
-
|
|
139
|
-
It captures everything a UI needs to render. The snapshot shows whether the agent is running, what it's streaming, and which tools or subagents are active. It also includes pending approvals, the current task list, token usage, and queued follow-ups.
|
|
140
|
-
|
|
141
|
-
Because it's a single object, you can drive an entire UI from one place: read the current snapshot with `get()`, and re-render whenever the AgentController emits `display_state_changed` (fired after every other event):
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
const snapshot = agentController.session.displayState.get()
|
|
145
|
-
|
|
146
|
-
// Re-render from the snapshot on every change
|
|
147
|
-
agentController.subscribe(event => {
|
|
148
|
-
if (event.type === 'display_state_changed') {
|
|
149
|
-
render(agentController.session.displayState.get())
|
|
150
|
-
}
|
|
151
|
-
})
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
This is the recommended pattern for most UIs. Subscribe to individual typed events only when you need to react to a specific transition rather than re-render the whole view. Visit the [Session reference](https://mastra.ai/reference/agent-controller/session) for the full list of sub-objects and method signatures.
|
|
155
|
-
|
|
156
|
-
## Related
|
|
157
|
-
|
|
158
|
-
- [AgentController overview](https://mastra.ai/docs/agent-controller/overview)
|
|
159
|
-
- [Threads and state](https://mastra.ai/docs/agent-controller/threads-and-state)
|
|
160
|
-
- [Tool approvals](https://mastra.ai/docs/agent-controller/tool-approvals)
|
|
161
|
-
- [Session reference](https://mastra.ai/reference/agent-controller/session)
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
-
|
|
3
|
-
# Subagents
|
|
4
|
-
|
|
5
|
-
Subagents let a parent agent delegate focused tasks to child agents with constrained tools and instructions. The AgentController auto-generates a `subagent` built-in tool that the parent model can call to spawn any configured subagent type. Reach for a subagent when a task needs a different toolset or instruction set than the parent agent, when you want to isolate a subtask's messages from the parent thread, or when the parent should delegate to a cheaper or faster model for specific work.
|
|
6
|
-
|
|
7
|
-
## Quickstart
|
|
8
|
-
|
|
9
|
-
Define subagent types in the AgentController constructor:
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { Agent } from '@mastra/core/agent'
|
|
13
|
-
import { AgentController } from '@mastra/core/agent-controller'
|
|
14
|
-
|
|
15
|
-
const agent = new Agent({
|
|
16
|
-
id: 'assistant',
|
|
17
|
-
name: 'assistant',
|
|
18
|
-
instructions: 'Use subagents when a focused task needs a narrower toolset.',
|
|
19
|
-
model: 'openai/gpt-5.6-sol',
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
const agentController = new AgentController({
|
|
23
|
-
id: 'with-subagents',
|
|
24
|
-
agent,
|
|
25
|
-
modes: [{ id: 'default', name: 'Default', metadata: { default: true } }],
|
|
26
|
-
subagents: [
|
|
27
|
-
{
|
|
28
|
-
id: 'explore',
|
|
29
|
-
name: 'Explore',
|
|
30
|
-
description: 'Reads files and gathers context without making changes.',
|
|
31
|
-
instructions: 'You are a read-only exploration agent.',
|
|
32
|
-
allowedWorkspaceTools: ['read_file', 'list_directory', 'grep_search'],
|
|
33
|
-
defaultModelId: 'anthropic/claude-haiku-4-5',
|
|
34
|
-
maxSteps: 30,
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
id: 'execute',
|
|
38
|
-
name: 'Execute',
|
|
39
|
-
description: 'Makes changes to files and runs commands.',
|
|
40
|
-
instructions: 'You are an execution agent.',
|
|
41
|
-
allowedWorkspaceTools: ['read_file', 'write_file', 'execute_command'],
|
|
42
|
-
defaultModelId: 'anthropic/claude-sonnet-4-6',
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
})
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
The parent agent can then call the auto-generated `subagent` tool with a `task` description and optional `agentType`.
|
|
49
|
-
|
|
50
|
-
When you define a subagent, give its `description` and `instructions` a clear, narrow scope. The `description` is what the parent model reads to decide _when_ to delegate, so state the single job the subagent is for and, by implication, what it's not for, "Reads files and gathers context without making changes" tells the parent to reach for it during exploration and to handle edits elsewhere. The `instructions` then keep the child agent inside that job. A subagent scoped to one task with a focused toolset stays predictable and is easier for the parent to route to. A broadly described subagent invites the parent to over-delegate and blurs the boundary between types. Pair the narrow scope with `allowedWorkspaceTools` so the subagent can only do what its description promises.
|
|
51
|
-
|
|
52
|
-
For the full list of subagent configuration options, see [`AgentController` reference](https://mastra.ai/reference/agent-controller/agent-controller-class).
|
|
53
|
-
|
|
54
|
-
## Forked subagents
|
|
55
|
-
|
|
56
|
-
A default subagent starts with a fresh context: it can't see the parent conversation, so you pass everything it needs in the `task` description. That's the right model for self-contained work, but it has two costs. The subagent has no access to what's already happened, and it builds a brand-new request prefix, a different system prompt and tool schemas, so it can't reuse the parent's prompt cache.
|
|
57
|
-
|
|
58
|
-
**Forked subagents** solve both. Instead of a fresh agent, a fork clones the parent thread and runs the parent agent itself, so it sees the full conversation history and keeps the same system prompt and tool schemas as the parent. The identical prefix means the model's prompt cache still hits, which makes context-heavy delegation cheaper and faster.
|
|
59
|
-
|
|
60
|
-
Use a fork when the subtask depends on the conversation so far, prior messages, earlier tool results, or the parent's tool environment, and you want to run it without paying to rebuild that context. Use a default subagent when the task is self-contained and benefits from a narrower toolset or a tighter system prompt, or alternatively a cheaper model.
|
|
61
|
-
|
|
62
|
-
Enable forked mode per-type:
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
const collaborator = {
|
|
66
|
-
id: 'collaborator',
|
|
67
|
-
name: 'Collaborator',
|
|
68
|
-
description: 'Continues the conversation in a fork.',
|
|
69
|
-
forked: true,
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Or per-invocation via the `subagent` tool's `forked` input parameter, which overrides the type's default.
|
|
74
|
-
|
|
75
|
-
### Forked mode semantics
|
|
76
|
-
|
|
77
|
-
Because a fork reuses the parent agent to keep the prompt prefix stable, the subagent's own definition is mostly set aside:
|
|
78
|
-
|
|
79
|
-
- Memory must be configured on the AgentController, since forking clones the parent thread.
|
|
80
|
-
|
|
81
|
-
Without it, the fork call returns an error.
|
|
82
|
-
|
|
83
|
-
- The fork runs with the parent agent's instructions, tools, and model. The subagent definition's own `instructions`, `tools`, and `defaultModelId` are ignored, and a per-invocation `modelId` is ignored too.
|
|
84
|
-
- Only the subagent definition's `description` still matters: it's what the parent model reads to decide when to delegate.
|
|
85
|
-
- Fork threads are tagged with `metadata.forkedSubagent === true` and hidden from `session.thread.list()` by default.
|
|
86
|
-
- Recursive forks are blocked at runtime: the inherited `subagent` tool is disabled inside a fork to prevent infinite nesting.
|
|
87
|
-
|
|
88
|
-
## Subagent model management
|
|
89
|
-
|
|
90
|
-
Set a global or per-type subagent model at runtime:
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
// Global subagent model
|
|
94
|
-
await agentController.session.subagents.model.set({ modelId: 'anthropic/claude-sonnet-4-6' })
|
|
95
|
-
|
|
96
|
-
// Per-type override
|
|
97
|
-
await agentController.session.subagents.model.set({
|
|
98
|
-
modelId: 'anthropic/claude-haiku-4-5',
|
|
99
|
-
agentType: 'explore',
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
// Read current model
|
|
103
|
-
const modelId = agentController.session.subagents.model.get({ agentType: 'explore' })
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## Related
|
|
107
|
-
|
|
108
|
-
- [AgentController overview](https://mastra.ai/docs/agent-controller/overview)
|
|
109
|
-
- [Tool approvals and permissions](https://mastra.ai/docs/agent-controller/tool-approvals)
|
|
110
|
-
- [API reference](https://mastra.ai/reference/agent-controller/agent-controller-class)
|