AgentManager
Category: Agent
Source: agent_manager.dart
Classes
SubagentUpdate
An update from a running subagent, forwarded to the UI.
Constructor
SubagentUpdate({
required this.task,
this.index,
this.total,
required this.event,
})SubagentUpdate(task: task, index: index, total: total, event: event)Properties
| Property | Type | Description |
|---|---|---|
task | String | Short description of the subagent's task. |
index | int? | Index within a parallel batch (null for single subagent). |
total | int? | Total number of parallel subagents (null for single). |
event | AgentEvent | The underlying agent event. |
tools | Map<String, Tool> | |
llmFactory | LlmClientFactory | |
config | GlueConfig | |
systemPrompt | String | |
allowedSubagentTools | Set<String> | |
obs | Observability? | |
onPersistEvent | SubagentEventSink? | Optional sink for persisting subagent activity onto the parent session log. Surfaces wire this to SessionManager.logEvent so subagent transcripts survive resume and feed /share. When null, subagent activity remains live-only (the legacy behavior). |
subagentStats | UsageStats | Cumulative usage across every subagent this manager has spawned. Surfaces (CLI status bar, ACP usage endpoint) read this to attribute subagent cost separately from the parent agent's own LLM calls. |
updates | Stream<SubagentUpdate> get | Stream of updates from running subagents. |
updates | Stream<SubagentUpdate> get | Stream of updates from running subagents. |
Methods
void Function(UsageStats)
Optional callback invoked when a subagent finishes, with that subagent's [UsageStats]. Surfaces wire this to SessionManager.recordUsage(stats, role: 'subagent') so the rollup is also persisted.
`Future<String> spawnSubagent({
required String task,
ModelRef? modelOverride,
int currentDepth = 0,
int? index,
int? total,
String? parentSubagentId,
})`
Spawns a single subagent to complete a [task].
Optionally override [modelOverride] to switch model for this subagent. [currentDepth] tracks recursion to prevent infinite nesting. [index] and [total] are set when spawned as part of a parallel batch. [parentSubagentId] is the id of the subagent that initiated this spawn (null when spawned by the top-level agent). Persisted on the subagent_spawned row so transcript reconstruction can attach the new group to the correct parent even when sibling subagents run in parallel and emit interleaved events.
AgentManager
Orchestrates subagent spawning using the manager pattern.
Creates independent [AgentCore] instances with their own conversation history but shared tool registry. Subagents run headlessly via [AgentRunner] with an allowlist-based approval policy (read-only tools by default).
Constructor
AgentManager({
required this.tools,
required this.llmFactory,
required this.config,
required this.systemPrompt,
Set<String>? allowedSubagentTools,
this.obs,
this.onPersistEvent,
})Properties
| Property | Type | Description |
|---|---|---|
tools | Map<String, Tool> | |
llmFactory | LlmClientFactory | |
config | GlueConfig | |
systemPrompt | String | |
allowedSubagentTools | Set<String> | |
obs | Observability? | |
onPersistEvent | SubagentEventSink? | Optional sink for persisting subagent activity onto the parent session log. Surfaces wire this to SessionManager.logEvent so subagent transcripts survive resume and feed /share. When null, subagent activity remains live-only (the legacy behavior). |
subagentStats | UsageStats | Cumulative usage across every subagent this manager has spawned. Surfaces (CLI status bar, ACP usage endpoint) read this to attribute subagent cost separately from the parent agent's own LLM calls. |
updates | Stream<SubagentUpdate> get | Stream of updates from running subagents. |
updates | Stream<SubagentUpdate> get | Stream of updates from running subagents. |
Methods
void Function(UsageStats)
Optional callback invoked when a subagent finishes, with that subagent's [UsageStats]. Surfaces wire this to SessionManager.recordUsage(stats, role: 'subagent') so the rollup is also persisted.
`Future<String> spawnSubagent({
required String task,
ModelRef? modelOverride,
int currentDepth = 0,
int? index,
int? total,
String? parentSubagentId,
})`
Spawns a single subagent to complete a [task].
Optionally override [modelOverride] to switch model for this subagent. [currentDepth] tracks recursion to prevent infinite nesting. [index] and [total] are set when spawned as part of a parallel batch. [parentSubagentId] is the id of the subagent that initiated this spawn (null when spawned by the top-level agent). Persisted on the subagent_spawned row so transcript reconstruction can attach the new group to the correct parent even when sibling subagents run in parallel and emit interleaved events.
`Future<List<String>> spawnParallel({
required List<String> tasks,
ModelRef? modelOverride,
int currentDepth = 0,
String? parentSubagentId,
})`
Spawns [tasks] in parallel, each as independent subagents.
All subagents run concurrently and results are returned in order.
Note: Parallel subagents share the same file system. Avoid tasks that write to the same files concurrently, as this can cause race conditions.
return switch (event)
Functions
Map<String, dynamic> serializeAgentEvent(AgentEvent event)
Serialises an [AgentEvent] into a JSON-compatible map for persistence in the parent session log under subagent_event.inner. The shape mirrors the top-level conversation event types where they overlap (tool_call, tool_result, assistant_message) so the same normaliser can recurse into either.