Multi-Agent Orchestration / Sub-Agents
Sub-agent delegation uses the
agents()middleware frompackage:genkit_middleware/agents.dart. Read agents.md first.
A common pattern is an orchestrator agent that delegates tasks to
specialized sub-agents (e.g. a researcher and a coder). The agents()
middleware injects one delegation tool per sub-agent (delegate_to_<name>),
appends a <sub-agents> block to the orchestrator's system prompt, and — when
the model calls a delegation tool — runs the sub-agent and returns its response
as the tool result.
To make the middleware available, register AgentsPlugin() on the Genkit
instance:
import 'package:genkit_middleware/agents.dart';
final ai = Genkit(plugins: [googleAI(), AgentsPlugin(), RetryPlugin()]);
1. Define the sub-agents
Give each sub-agent a description — it's auto-discovered from registry metadata
and shown to the orchestrator so the model knows when to delegate.
import 'genkit.dart';
final researcher = ai.defineAgent(
name: 'researcher',
description:
'A thorough research assistant that provides well-sourced answers.',
system: 'You are a thorough research assistant. When asked a question, '
'provide a clear, well-structured, and well-sourced answer.',
maxTurns: 10,
);
final coder = ai.defineAgent(
name: 'coder',
description: 'Writes, debugs, and explains code. Use for any programming tasks.',
system: 'You are an expert programmer. Provide clean, well-commented code '
'with explanations. Use Dart by default unless asked otherwise.',
maxTurns: 10,
);
2. Wire up the orchestrator
Add agents() to the orchestrator's use: [...]. Pass the sub-agent names;
their descriptions are auto-discovered from the registry.
import 'package:genkit/genkit.dart';
import 'package:genkit_middleware/agents.dart';
import 'genkit.dart';
final orchestratorAgent = ai.defineAgent(
name: 'orchestratorAgent',
system: '''
You are a helpful project assistant.
Analyze the user's request and delegate to the appropriate sub-agent.
If the request requires both research AND code, call them sequentially.
After receiving sub-agent responses, synthesize a final answer for the user.''',
use: [
agents(
agents: ['researcher', 'coder'],
maxDelegations: 5, // guard rail against runaway delegation loops
historyLength: 4, // forward the last N user/model messages as context
),
],
store: InMemorySessionStore(),
);
Run it like any other agent:
final chat = orchestratorAgent.chat();
final turn = chat.sendStream(
text: 'Research the best sorting algorithms, then write a Dart quicksort.',
);
await for (final chunk in turn.stream) {
stdout.write(chunk.text);
}
final res = await turn.response;
agents() options
agents(required):List<String>of sub-agent names. Each description is auto-discovered from the registry.toolPrefix: prefix for generated tool names. Defaults todelegate_to→delegate_to_<agent>.maxDelegations: max delegations pergeneratecall. Prevents runaway loops.historyLength: number of recent user/model messages forwarded to sub-agents as context.0/omitted sends only the task description.artifactStrategy:'inline'(default) or'session'— see below.
Sharing artifacts between agents
Sub-agents can produce artifacts. artifactStrategy
controls how they reach the orchestrator:
'inline'(default): artifact content is included in the delegation tool result (so the model sees it directly) and merged into the parent session.'session': artifacts are merged into the parent session only; the tool result lists artifact names, not content. Merged artifacts are namespaced by an invocation id (<invocationId>/<name>).
Other middleware
package:genkit_middleware also exports filesystem, skills, and
toolApproval; retry ships in core package:genkit. They attach the same way
via use: [...] on an agent (or on ai.generate) — see
using middleware. retry() is commonly paired with
delegation.
Note: if a sub-agent triggers an interrupt, it is reported back to the orchestrator as a normal tool response (not propagated as a resumable interrupt). Delegate self-contained tasks.