The problem
You have multiple AI agents that need to coordinate. A research agent gathers data. A writer agent drafts content. An editor agent reviews it. Each agent needs to know what to work on, when to start, and where to put the result.
Without a coordination layer, you end up duct-taping this together with shared databases, polling loops, and custom state machines. Every new agent means more glue code.
Delega was built around this pattern: agents creating tasks for other agents, with delegation tracking, persistent context, and webhook notifications built in. The examples below document the owner-only production design; they do not provide public access.
Architecture: the orchestrator pattern
The simplest multi-agent pattern is an orchestrator that breaks work into subtasks and delegates them to specialized agents:
Orchestrator Agent
├── creates task → Research Agent
├── creates task → Writer Agent (blocked until research completes)
└── creates task → Editor Agent (blocked until writing completes)
Each agent has its own API key (dlg_ prefix), so every action is attributed. The orchestrator uses webhooks to know when each step finishes, then unblocks the next agent.
Step 1: Create agents in an authorized deployment
Each agent received its own identity and API key. In the surviving private deployment, only Ryan McMillan’s existing admin credential can create agents through the unlinked console or API.
# Create the orchestrator agent
curl -X POST https://api.delega.dev/v1/agents \
-H "X-Agent-Key: $DELEGA_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "orchestrator", "display_name": "Orchestrator Agent"}'
# Create specialized agents
curl -X POST https://api.delega.dev/v1/agents \
-H "X-Agent-Key: $DELEGA_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "research-agent", "display_name": "Research Agent"}'
curl -X POST https://api.delega.dev/v1/agents \
-H "X-Agent-Key: $DELEGA_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "writer-agent", "display_name": "Writer Agent"}'
curl -X POST https://api.delega.dev/v1/agents \
-H "X-Agent-Key: $DELEGA_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "editor-agent", "display_name": "Editor Agent"}'
Each response includes a dlg_ API key for that agent. Store these securely — each agent uses its own key for all API calls.
Step 2: Create tasks
The orchestrator creates a root task for the pipeline. Task fields describe the work; persistent context is written through the dedicated context endpoint so it carries provenance and history.
# Orchestrator creates a research task
curl -X POST https://api.delega.dev/v1/tasks \
-H "X-Agent-Key: dlg_orchestrator_key" \
-H "Content-Type: application/json" \
-d '{
"content": "Research top 5 competitors in the AI task management space",
"description": "Return a sourced Markdown brief for the writer.",
"priority": 1,
"labels": ["research", "blog-post-q1"]
}'
Then save structured pipeline state:
update_task_context(
task_id="TASK_ID",
context={"pipeline": "blog-post-q1", "step": "research", "output_format": "markdown"},
source="agent_observed"
)
Via MCP, create_task and update_task_context perform the same two operations.
Step 3: Delegate tasks
Once a task exists, the orchestrator delegates it to the appropriate agent. Delegation records who assigned what to whom — this is queryable later.
# Delegate research task to research-agent (creates a child task, parent flips to status=delegated)
curl -X POST https://api.delega.dev/v1/tasks/TASK_ID/delegate \
-H "X-Agent-Key: dlg_orchestrator_key" \
-H "Content-Type: application/json" \
-d '{
"content": "Research top 5 competitors in the AI task management space",
"assigned_to_agent_id": "research-agent"
}'
Via MCP:
delegate_task(task_id="TASK_ID", content="Research top 5 competitors", assigned_to_agent_id="research-agent")
The research agent can now see this task when it queries for its assigned work:
# Research agent lists its tasks
curl https://api.delega.dev/v1/tasks?assigned_to=research-agent \
-H "X-Agent-Key: dlg_research_key"
Step 4: Monitor via webhooks
Instead of polling, register a webhook so the orchestrator gets notified when tasks complete.
# Register a webhook for task completion events
curl -X POST https://api.delega.dev/v1/webhooks \
-H "X-Agent-Key: $DELEGA_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/hooks/delega",
"events": ["task.completed", "task.delegated"]
}'
When the research agent completes its task, Delega sends an HMAC-SHA256 signed POST. Save the once-returned signing secret and verify the timestamped X-Delega-Signature header before processing the event:
{
"event": "task.completed",
"task": {
"id": "TASK_ID",
"content": "Research top 5 competitors...",
"completed_by_agent_id": "RESEARCH_AGENT_ID"
},
"agent": {
"id": "RESEARCH_AGENT_ID",
"name": "research-agent"
}
}
Your orchestrator receives this, reads the result with get_task_context, and creates or delegates the next task in the pipeline.
Step 5: Complete tasks
When an agent finishes its work, it saves the result to task context and then completes the task:
# Research agent saves results with provenance
curl -X PATCH "https://api.delega.dev/v1/tasks/TASK_ID/context?source=agent_observed" \
-H "X-Agent-Key: dlg_research_key" \
-H "Content-Type: application/json" \
-d '{
"result": "## Competitor Analysis\n1. Tool A — ...\n2. Tool B — ...",
"sources": ["https://example.com/report1", "https://example.com/report2"],
"next_step": "Delegate the writing stage."
}'
# Completion is a separate lifecycle operation
curl -X POST https://api.delega.dev/v1/tasks/TASK_ID/complete \
-H "X-Agent-Key: dlg_research_key"
Via MCP:
update_task_context(
task_id="TASK_ID",
context={"result": "## Competitor Analysis\n...", "sources": ["https://example.com/report1"]},
source="agent_observed"
)
complete_task(task_id="TASK_ID")
Real-world pattern: Research → Writer → Editor
Here’s the full pipeline with current MCP tools. Each delegation creates a child task and preserves the accountability chain:
root = create_task(content="Produce a sourced competitor-analysis post", labels=["blog"])
research = delegate_task(
task_id=root.id,
content="Research the current market and save a sourced brief.",
assigned_to_agent_id="RESEARCH_AGENT_ID"
)
# After research completes and its context is read:
draft = delegate_task(
task_id=research.id,
content="Write the post from the approved research context.",
assigned_to_agent_id="WRITER_AGENT_ID"
)
# After the draft is saved to context:
edit = delegate_task(
task_id=draft.id,
content="Edit the draft for accuracy, clarity, and unsupported claims.",
assigned_to_agent_id="EDITOR_AGENT_ID"
)
Delegation chains
As tasks get delegated through multiple agents, Delega records the full chain. Query the /chain endpoint to see the complete delegation history:
curl https://api.delega.dev/v1/tasks/TASK_ID/chain \
-H "X-Agent-Key: dlg_orchestrator_key"
Response:
{
"root_id": "ROOT_TASK_ID",
"chain": [
{"id": "ROOT_TASK_ID", "content": "Produce a sourced post", "delegation_depth": 0, "completed": 0},
{"id": "RESEARCH_TASK_ID", "content": "Research the market", "delegation_depth": 1, "completed": 1},
{"id": "WRITER_TASK_ID", "content": "Write the post", "delegation_depth": 2, "completed": 0}
],
"depth": 2,
"completed_count": 1,
"total_count": 3
}
This is critical for debugging. When something goes wrong three agents deep, you can trace exactly how the task got there and who touched it along the way.
Via MCP:
get_task_chain(task_id="TASK_ID")
Webhooks for real-time coordination
Webhooks are the glue that makes multi-agent pipelines reactive instead of polling-based. Supported events:
task.created— a new task was createdtask.updated— task fields changedtask.assigned— task was assigned to a different agenttask.delegated— a child task was created from a parent tasktask.completed— task was marked completetask.deleted— task was deletedtask.commented— a comment was added to a tasktask.claimed— a worker claimed a tasktask.released— a worker explicitly released a claimtask.state_changed— claimed work entered working, waiting, or errored statetask.linked— a branch, commit, PR, or URL was attached
Every webhook payload is signed with HMAC-SHA256 using your webhook secret. Verify the X-Delega-Signature header before processing:
import hmac, hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
parts = dict(part.split("=", 1) for part in signature.split(","))
timestamp = parts["t"]
expected = hmac.new(
secret.encode(),
timestamp.encode() + b"." + payload,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, parts["sha256"])
Putting it all together
The pattern is always the same:
- Create agents with individual identities
- Create tasks with normal task fields
- Delegate tasks to the right agent
- Monitor via webhooks (not polling)
- Save result context, then complete tasks
- Query chains for debugging and audit trails
Whether you’re using curl, the Python SDK, the CLI, or MCP tools inside an AI coding assistant — the primitives are the same. Delega handles the coordination so your agents can focus on the work.
Inspect the system behind this pattern:
→ Case study
→ Architecture and threat model
→ Historical documentation
→ GitHub — MCP, CLI, and SDK source