Agent-to-Agent (A2A) Delegation
Ontheia supports collaboration between specialized Agents through delegation. This enables the construction of complex workflows where a “Master Agent” (Planner) delegates tasks to specialized “Sub-Agents” (Workers).
There are two primary mechanisms for delegation:
- Declarative Delegation (via Chain Steps)
- Autonomous Delegation (via the
delegate-to-agenttool)
1. Declarative Delegation (Chain Steps)
Section titled “1. Declarative Delegation (Chain Steps)”This form of delegation is fixed within a Chain specification. It is ideal for structured, recurring processes where the sequence of Agent calls is known in advance.
How it Works
Section titled “How it Works”A step of type agent is used within a Chain. The engine (ChainRunner) interrupts the execution of the Master Run, executes the Sub-Agent, and returns its result to the Chain.
Example Specification
Section titled “Example Specification”{ "id": "research_step", "type": "agent", "agent_id": "d2306d91-29fd-4ae3-8828-1189a9b41a7f", "task_id": "search_contacts", "input": "Search for contacts with the name 'Hans'", "params": { "silent": false }}Characteristics for LLMs
Section titled “Characteristics for LLMs”- Deterministic: The call always occurs when the step is reached.
- Context Isolation: The Sub-Agent receives a fresh instance but retains the conversation history if it is passed.
- Data Transfer: Results can be used in subsequent steps via
${steps.research_step.output}.
2. Autonomous Delegation (delegate-to-agent)
Section titled “2. Autonomous Delegation (delegate-to-agent)”This is the more dynamic form of delegation. Here, an LLM independently decides during runtime whether and to whom it wants to delegate a task.
The Tool: delegate-to-agent
Section titled “The Tool: delegate-to-agent”The tool is part of the internal delegation server and is available to an Agent only when explicitly assigned — the delegation server must be selected in the Agent’s MCP servers (plus the tool itself if a restricted tool selection is configured). This applies to all internal servers (memory, delegation, scheduler): unassigned tools do not appear in the prompt and incur no token cost.
Note for Sub-Agents: A pure worker Agent does not need delegation tools — it receives its task from the master and its result flows back automatically as the tool result. Only orchestrating Agents need delegation. Self-delegation is blocked (by UUID and label), and the maximum delegation depth is 5.
Tool Definition (for AI Models)
Section titled “Tool Definition (for AI Models)”- Server:
delegation - Tool:
delegate-to-agent - Parameters:
agent(String, Required): The UUID or name of the target Agent.input(String, Required): The specific task or message to the Sub-Agent.task(String, Optional): UUID or name of a specific Task context.chain(String, Optional): UUID or name of a specific Chain to be executed.
Precedence: An explicit, matching
taskbeats every chain — the agent’s default chain as well as a namedchain. Without a matching task, the namedchainruns (if bound to the agent), otherwise the default chain, otherwise an LLM call. A named-but-not-found task falls back to the chain and is logged in the trace. Details in Agent-to-Chain Binding & Delegation.
Security Mechanisms & Control
Section titled “Security Mechanisms & Control”1. Tool Approval in Sub-Run (Blocking)
Section titled “1. Tool Approval in Sub-Run (Blocking)”If the tool_approval: "prompt" mode is active for a Run, this also applies to all delegated tasks.
- Interactive Approval: If a Sub-Agent reaches a tool call, the entire chain (including the Master Agent) pauses.
- User Feedback: The user sees the Sub-Agent’s request in the Composer and must explicitly approve it before delegation continues.
- Transparency: All pending requests are listed in the sidebar (TOOL APPROVAL), including information on which Sub-Agent wants to call the tool.
2. Recursion Guard
Section titled “2. Recursion Guard”The ChainRunner engine tracks the depth of the delegation.
- Limit: A maximum of 5 levels of depth is allowed.
- If exceeded, the Run is aborted with an error message to prevent infinite loops between Agents.
3. Self-Delegation Lock (Self-Call Prevention)
Section titled “3. Self-Delegation Lock (Self-Call Prevention)”An Agent cannot delegate tasks to itself. This prevents “circular thinking” and unnecessary API costs through endless identity loops. The delegation plugin blocks such calls at the tool level.
4. Identity Injection
Section titled “4. Identity Injection”Sub-Agents automatically receive an extended system instruction informing them of their own role and identity within the system. This encourages the use of their own specialized tools rather than re-delegating.
5. The Sub-Agent’s Instructions (Task Context)
Section titled “5. The Sub-Agent’s Instructions (Task Context)”A sub-agent builds its system prompt itself — it does not inherit one from the master:
- Task context: The behavioural rules (
context_prompt) defined in the sub-agent’s own task are set as the primarysystemmessage. The master’s task context stays out of it. - User context: Information about the requesting user (ID, name, role) is resolved into the template variables.
- Time/Date: Current timestamps are injected automatically — into the volatile suffix, not the system prompt.
What the sub-agent does take from the master is the conversation history (point 6), not its instructions. The full delineation is in How Memory and Context Work.
6. History Continuity (History Flow)
Section titled “6. History Continuity (History Flow)”With every delegation, the relevant conversation history is passed to the Sub-Agent. This ensures that the Sub-Agent understands the context of the entire conversation.
7. Memory Context for Sub-Agents
Section titled “7. Memory Context for Sub-Agents”If readNamespaces are configured in a sub-agent’s memory policy, the system automatically loads the matching memory context before execution — identical to the behavior for the master agent.
- Namespace templates are resolved using the current user context.
- A security filter ensures only
vector.global.*namespaces and namespaces carrying the user’s own UUID are accessible. - Retrieved entries appear as a
memory_contextstep in the Trace Panel.
Best Practices for Developers
Section titled “Best Practices for Developers”- Clear Inputs: The
inputfor a delegation should be formulated as if it were a new user request. - Separate Responsibilities: It is better to create many small, specialized Agents than one large “all-rounder.”
- Use Labels: The system prompt for the Planner should include the names/labels of the Agents to facilitate selection by the LLM.