QueryMT Agent - Delegation System
The delegation system enables multi-agent workflows where a planner agent can delegate tasks to specialized delegate agents. This allows for division of labor and specialized expertise.
Overview
Delegation allows agents to: - Delegate tasks to specialized agents - Coordinate work across multiple agents - Verify results from delegates - Run in parallel multiple delegations - Route to remote agents via mesh networking
Architecture
flowchart TD
P["Planner Agent<br/>(Analyzes task, decides which delegate to use)"]
O["Delegation Orchestrator<br/>(Manages delegation lifecycle)"]
D1["Delegate 1<br/>(Coder)"]
D2["Delegate 2<br/>(Tester)"]
P -->|"Delegation Request"| O
O --> D1 & D2
Configuration
Enabling Delegation
Delegation is enabled in the quorum configuration:
Defining Delegates
Planner Configuration
Session-Scoped Delegate Models (ACP)
A delegate's profile configuration supplies its default model. A parent session can explicitly override that model for future delegations, without changing the profile, another parent session, or a child that is already running. The override is read during child setup, before its first prompt; a change racing with setup is not guaranteed to affect that already-starting child.
Read assignments
Check querymt/capabilities for querymt/session/delegateModels and
querymt/session/setDelegateModel. Call:
An illustrative result is:
modelis the stored override, ornullto inherit. It is returned even if the model has disappeared from the current catalog or its node is offline.sourceisoverrideorprofile_default. A failed read is unknown, not proof of inheritance. Do not substitute a recent/default catalog entry.configured_default_model_idis the local delegate's configured provider/model, also included byquerymt/profile/agents. It may benullfor a remote delegate. It is not a resolved Mesh route, a runtime availability guarantee, or the model that generated an existing child's messages.reasoning_effort_supportedis true when the additive setter/readback field is available. Clients must hide reasoning controls when an older backend omits it.reasoning_effortisnullto inherit the parent session at delegation time, orauto,low,medium,high, ormaxfor an explicit role override.orphaned_overridescontains{agent_id, model, reasoning_effort}entries for removed profile roles. Model can benullfor reasoning-only overrides. They remain visible and can be explicitly cleared; reads never delete them.editableis false for delegated child sessions. User-created forks can own independent assignments. The session must have a valid persisted profile binding; no prior actor load is required.
Reads do not set models, replay client preferences, or create session actors.
Change one assignment
The response includes version, session_id, agent_id, confirmed model,
reasoning_effort, revision, and durable. Every write must include model_id;
omitting it is InvalidParams. Omit node_id (or use null) for a local model.
Reset the model with an explicit model_id: null and no node. The optional
reasoning_effort field preserves the existing setting when omitted, clears it back
to parent-session inheritance when null, and accepts auto, low, medium, high,
or max. Snake-case request fields also accept their camelCase aliases. An empty
node string is rejected rather than silently selecting local execution.
Use the revision from readback to avoid lost updates. A stale write fails without
changing anything. The ACP error code is -32020, not InvalidParams
(-32602), with this error data:
Refresh and let the user review a conflict; do not blindly retry. Writes to an unchanged value keep the revision. The revision covers all roles in that parent session; a changed role increments it once. Multiple setter calls are not an atomic bulk operation: retain per-role confirmations and handle partial failure before sending a new session's first prompt.
Older clients may omit expected_revision; their writes are unconditional but
atomically preserve other roles and any omitted reasoning setting. SQLite stores one
revision row per parent session and one relational override row per configured role;
there are no JSON assignment blobs. Deleting a parent cascades to its assignments. A
user fork copies assignments independently with revision zero; delegated children do
not inherit that assignment map.
Notifications and recovery
On changes, stdio and WebSocket event streams send the advertised
querymt/session/delegateModelsChanged invalidation hint:
Notifications use existing session event routing/ownership rules. They are not a cross-process database watcher or a guaranteed event for every commit: the write and event publication are separate. Always read back on reconnect and refresh on focus when other processes may write. The returned state, not an event history scan, is authoritative.
Delegation updates and load snapshots also expose selectedModelId and
selectedProviderNodeId once a child has been configured. These optional fields
come from that child's confirmed control state immediately before the fork event
and first prompt. Older fork events omit them. Use them for historical execution
provenance; do not rewrite them from today's parent assignment settings.
Custom SessionStore implementations that do not implement durable assignments
retain the legacy in-memory path. They report durable: false and revision: null,
and reject an expected_revision. Do not promise persistence or compare-and-swap
for those backends. Legacy in-memory overrides are not automatically migrated;
clients must explicitly apply any desired saved setup.
Testing and database isolation
Profile tests must inject temporary or in-memory storage into AgentInfra; the
profile manager and its runtimes must use the same isolated storage. storage: None
means use the normal user database, not an in-memory test database.
As defense in depth, run tests with a fresh QMT_SESSIONS_DB, QMT_HOME, and
HOME, and use a filesystem sandbox that hides the real home and other worktrees.
Never launch development builds against a live sessions database to test migrations.
The delegate-assignment migration is 0017_delegate_assignments, after the event
source identity and remote sync progress migrations already present on main.
Delegation Lifecycle
1. Delegation Request
The planner decides to delegate and creates a delegation request.
If hooks are enabled, pre_delegation runs before the delegation is recorded. It can block the delegation entirely or rewrite fields such as target_agent_id, objective, context, constraints, and expected_output.
The planner-side tool result is updated when a delegation is blocked, so the model sees Delegation blocked by hook: ... instead of a misleading queued message.
The delegation request shape is:
2. Session Creation
The orchestrator creates a new session for the delegate:
3. Context Injection
The planner's context is injected into the delegate session.
If hooks are enabled, delegation_start runs just before the delegate begins work. This hook is observe-only: it cannot block execution, but its additional_context is appended to the child session planning context.
The planner's context is injected into the delegate session:
4. Task Execution
The delegate receives the task and begins execution:
5. Result Collection
The delegate's work is collected.
If hooks are enabled, post_delegation runs after the delegate summary is extracted. This hook is observe-only and can append context to the summary that gets injected back into the planner session.
The delegate's work is collected:
6. Verification (Optional)
If verification is enabled, the result is verified:
7. Result Injection
The result is injected back into the planner session.
If a delegation fails, delegation_failure runs before the failure message is injected back into the planner. This hook is also observe-only and can append remediation context to the planner-visible failure message.
The result is injected back into the planner session:
Delegation Hooks Summary
| Hook | Matcher | Behavior |
|---|---|---|
pre_delegation |
target agent regex | Block or rewrite the delegation before it is recorded |
delegation_start |
target agent regex | Observe start and append planning context for the child session |
post_delegation |
target agent regex | Observe completion and append context to the injected summary |
delegation_failure |
target agent regex | Observe failure and append context to the injected failure message |
See the Hooks Guide for JSON payloads, schemas, and output examples.
Delegation Status
| Status | Description |
|---|---|
Pending |
Delegation requested, waiting to start |
Running |
Delegate is working on the task |
Complete |
Delegate finished successfully |
Failed |
Delegate encountered an error |
Cancelled |
Delegation was cancelled |
Verification
Verification Types
Example Verification
Delegation Parameters
Wait Policy
Controls how the planner waits for delegate results:
- any: Continue when first delegate completes
- all: Wait for all delegates to complete
Parallel Delegations
Maximum concurrent delegations.
Grace Period
Time to wait for graceful cancellation before force abort.
Remote Delegation
Delegates can run on remote mesh nodes:
When peer is specified:
- LLM calls are routed to the remote node
- Tool execution happens locally
- Enables "remote model, local session" pattern
Delegation Events
Agents emit events during delegation:
Programmatic Delegation
Creating a Delegation
Subscribing to Delegation Events
Error Handling
Common Errors
| Error | Cause | Resolution |
|---|---|---|
AgentNotFound |
Delegate not registered | Register delegate with correct ID |
SessionCreationFailed |
Cannot create delegate session | Check delegate configuration |
VerificationFailed |
Verification check failed | Fix the issue or adjust verification |
Timeout |
Delegation took too long | Increase timeout or optimize task |
Cancelled |
Delegation was cancelled | Retry or handle cancellation |
Error Classification
The system classifies delegation errors:
Best Practices
When to Delegate
Good candidates for delegation: - Well-defined, isolated tasks - Tasks requiring specific expertise - Parallelizable work - Tasks with clear success criteria
Poor candidates for delegation: - Highly ambiguous requirements - Tasks requiring deep context - Interactive, multi-turn tasks - Tasks needing human judgment
Writing Good Delegation Requests
- Clear objective: Be specific about what needs to be done
- Relevant context: Include necessary background information
- Explicit constraints: List any requirements or restrictions
- Expected output: Describe what success looks like
- Verification criteria: If applicable, specify how to verify
Planning for Delegation
- Break down tasks: Split complex tasks into smaller delegations
- Order dependencies: Plan delegation sequence
- Set expectations: Clearly communicate goals to delegates
- Review results: Always review delegate output before integrating
Examples
Simple Delegation
User: "Add a new API endpoint" Planner: Delegates to coder with task details Coder: Implements the endpoint Planner: Reviews and integrates the changes
Parallel Delegation
User: "Implement feature X" Planner: Delegates frontend to frontend-coder, backend to backend-coder Both delegates work in parallel Planner: Integrates both results
Verification Example
Troubleshooting
Delegation Not Starting
- Check delegate is registered:
agent.agent_registry().list_agents() - Verify delegate configuration is valid
- Check for middleware errors
- Review logs for delegation events
Delegate Not Completing
- Check delegate has necessary tools
- Verify delegate can access required files
- Check for infinite loops in delegate logic
- Review timeout settings
Verification Failing
- Check verification command is correct
- Verify delegate made expected changes
- Adjust verification criteria if too strict
- Review delegate output for issues
Related Documentation
- Configuration Guide - Delegation configuration
- Mesh Networking - Remote delegation
- API Reference - Delegation types
- Agent Modes - Mode-aware delegation