How DeerFlow Sub-Agents Orchestrate Parallel Task Execution
Purpose
I’ve struggled with a fundamental limitation in AI agents: they can only do one thing at a time. When I need to research multiple angles of a problem, analyze code while generating tests, or explore different solutions in parallel, a single agent becomes a bottleneck.
DeerFlow solves this with sub-agents. The lead agent can spawn specialized child agents that run in parallel, each with its own isolated context. This post explains how the sub-agent system works and when to use it.
The Problem: Single-Agent Limitations
Complex tasks often require multiple perspectives. Here’s what happens when I ask a single agent to handle a complex research task:
User: "Analyze the competitor landscape for our product" | vAgent: "Let me research competitor A..." [5 minutes]Agent: "Now competitor B..." [5 minutes]Agent: "Now competitor C..." [5 minutes]Agent: "Let me synthesize..." [2 minutes] | vTotal: 17+ minutes, sequentialThe problem compounds when tasks are independent:
- Linear context window: The agent can only think about one thing at a time
- Sequential execution: No parallelism, even when tasks don’t depend on each other
- Context pollution: Previous task outputs can bias later tasks
How DeerFlow Sub-Agents Work
DeerFlow introduces a hierarchical agent architecture:
┌─────────────────┐ │ Lead Agent │ │ (Orchestrator) │ └────────┬────────┘ │ task() tool ┌──────────────┼──────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │Sub-Agent │ │Sub-Agent │ │Sub-Agent │ │ #1 │ │ #2 │ │ #3 │ │(Research)│ │ (Code) │ │(Analysis)│ └──────────┘ └──────────┘ └──────────┘ │ │ │ └──────────────┴──────────────┘ │ ▼ Synthesized ResultThe lead agent has a task tool for delegation. When invoked, it creates a child agent that runs independently.
Exploring the Task Tool
I examined the task tool implementation:
@tooldef task( description: str, prompt: str, subagent_type: str = "general-purpose", max_turns: int = 5) -> str: """ Delegate a task to a sub-agent.
Args: description: Brief task description prompt: Detailed instructions for sub-agent subagent_type: Type of agent (general-purpose, bash) max_turns: Maximum turns for sub-agent
Returns: Result from sub-agent execution """The key parameters:
- description: What the task is about (shown in logs)
- prompt: Detailed instructions for the sub-agent
- subagent_type: Which built-in agent to use
- max_turns: How many conversation turns the sub-agent can take
Built-in Agent Types
DeerFlow ships with two built-in sub-agent types:
BUILTIN_AGENTS = { "general-purpose": AgentConfig( name="general-purpose", tools="all_except_task", # Cannot spawn more sub-agents system_prompt="You are a specialized agent..." ), "bash": AgentConfig( name="bash", tools=["bash", "read_file", "write_file"], system_prompt="You are a bash specialist..." )}The general-purpose agent has access to most tools but cannot spawn its own sub-agents (preventing infinite recursion). The bash agent is specialized for command execution.
Testing Parallel Execution
I wanted to see sub-agents in action. Here’s a test script:
from deerflow.client import DeerFlowClientimport time
client = DeerFlowClient()
# Request that benefits from parallel researchstart = time.time()response = client.chat( "Research the following in parallel:\n" "1. Latest React 19 features\n" "2. Vue 3.4 improvements\n" "3. Svelte 5 runes\n" "Then synthesize a comparison.", thread_id="parallel-test", context={"subagent_enabled": True})elapsed = time.time() - start
print(f"Total time: {elapsed:.1f}s")print(response)I watched the logs to confirm parallel execution:
[lead-agent] Analyzing request...[lead-agent] Spawning 3 sub-agents via task tool[subagent-1] Started: Research React 19 features[subagent-2] Started: Research Vue 3.4 improvements[subagent-3] Started: Research Svelte 5 runes[subagent-1] Completed in 12.3s[subagent-2] Completed in 14.1s[subagent-3] Completed in 11.8s[lead-agent] Synthesizing results...[lead-agent] Response completeAll three research tasks ran in parallel. The total time was ~14 seconds (the longest task), not 38 seconds (the sum).
How Concurrency is Enforced
I was curious about how DeerFlow prevents resource exhaustion. Here’s what I found:
Concurrency Limits
SubagentLimitMiddleware enforces a hard limit:
- Max 3 concurrent sub-agents per turn- 15-minute timeout per sub-agent- Excess task calls are truncated from model responseThis prevents the lead agent from spawning hundreds of sub-agents.
Thread Pool Architecture
DeerFlow uses dual thread pools:
_scheduler_pool = ThreadPoolExecutor(max_workers=3) # For scheduling_execution_pool = ThreadPoolExecutor(max_workers=3) # For executionThe separation ensures scheduling doesn’t block execution.
Monitoring Sub-Agent Events
Sub-agent execution emits SSE events for real-time monitoring:
from deerflow.client import DeerFlowClient
client = DeerFlowClient()
for event in client.stream("Research AI trends"): if event.type == "task_started": print(f"Sub-agent started: {event.data['task_id']}") print(f" Description: {event.data['description']}")
elif event.type == "task_running": print(f"Sub-agent running: {event.data['status']}")
elif event.type == "task_completed": print(f"Sub-agent completed: {event.data['task_id']}") print(f" Result length: {len(event.data['result'])} chars")
elif event.type == "task_failed": print(f"Sub-agent failed: {event.data['error']}")
elif event.type == "task_timed_out": print(f"Sub-agent timed out after 15 minutes")This produces output like:
Sub-agent started: subagent-a1b2c3 Description: Research AI trendsSub-agent running: searching webSub-agent running: analyzing resultsSub-agent completed: subagent-a1b2c3 Result length: 4521 charsSub-Agent Context Isolation
One of the most important aspects of sub-agents is context isolation:
Lead Agent Context: - Full conversation history - All user messages - Previous sub-agent results
Sub-Agent Context: - Only the prompt passed to it - Cannot see lead agent's conversation - Cannot see other sub-agents' contextsThis isolation prevents:
- Context contamination: Sub-agent doesn’t get biased by lead agent’s thinking
- Information leakage: Sub-agent can’t access unrelated context
- Token waste: Sub-agent only sees what’s relevant to its task
When to Use Sub-Agents
Based on my testing, sub-agents excel at:
Good Use Cases
Multi-angle research
client.chat( "Analyze our competitor from three angles:\n" "1. Technical: API design, architecture\n" "2. Business: Pricing, market position\n" "3. UX: User reviews, feature requests", context={"subagent_enabled": True})Parallel code generation
client.chat( "Generate tests for all services in src/services/:\n" "- auth.service.ts\n" "- user.service.ts\n" "- payment.service.ts", context={"subagent_enabled": True})Breaking down complex workflows
client.chat( "Implement the new dashboard feature:\n" "1. Research best practices (sub-agent)\n" "2. Design the data model (sub-agent)\n" "3. Create API endpoints (sub-agent)\n" "4. Build frontend components (sub-agent)\n" "5. Write integration tests (sub-agent)", context={"subagent_enabled": True})Not Recommended For
Simple single-step queries
User: "What's 2 + 2?"# Sub-agent overhead is wastefulTasks requiring shared context
User: "Refactor the function you just wrote"# Sub-agent wouldn't have the context of what was writtenQuick follow-up questions
User: "Can you elaborate on point 3?"# Direct response is fasterConfiguration
Enable sub-agents via the context parameter:
{ "message": "Research competitor pricing", "thread_id": "research-123", "context": { "thinking_enabled": true, "is_plan_mode": false, "subagent_enabled": true }}The subagent_enabled flag must be explicitly set to true.
Issues I Encountered
During testing, I ran into a few issues:
Issue 1: Sub-Agent Timeout
When a sub-agent took too long:
Error: Sub-agent timed out after 15 minutesTask ID: subagent-xyz789Description: Research enterprise AI solutionsThe fix was to reduce task scope:
# WRONG: Too broadclient.chat("Research all AI frameworks")
# CORRECT: Focused scopeclient.chat("Research Python AI frameworks for web apps")Issue 2: Context Not Shared
I expected sub-agents to see the lead agent’s context:
Lead Agent: "I mentioned React earlier"Sub-Agent: "I don't know what React is"This is by design. Sub-agents only receive the prompt you give them:
client.chat( "Task 1: Research React 19 features\n" "Context: React is a JavaScript UI library by Meta\n" "Focus on the new compiler and server components.")Issue 3: Concurrency Limit Hit
When I tried to spawn 5 sub-agents:
[lead-agent] Warning: Only 3 sub-agents allowed per turn[lead-agent] Tasks 4 and 5 were truncatedThe middleware silently drops excess tasks. The fix is to batch:
# First batchclient.chat("Research frameworks A, B, and C")
# Second batch (in new turn)client.chat("Now research frameworks D and E")Performance Comparison
I ran benchmarks comparing single-agent vs sub-agent execution:
Task: Research 3 topics and synthesize
Single Agent: - Sequential execution - Total time: 47.3 seconds - Context used: ~12,000 tokens
Sub-Agents (3 parallel): - Parallel execution - Total time: 18.7 seconds (longest task) - Context per sub-agent: ~4,000 tokens - Lead agent context: ~2,000 tokens - Total tokens: ~14,000 (some overhead)The speedup was 2.5x for parallelizable tasks. Token usage was similar due to coordination overhead.
Why This Matters
| Aspect | Single Agent | DeerFlow Sub-Agents |
|---|---|---|
| Parallelism | None | Up to 3 concurrent |
| Context isolation | Shared | Per-agent isolation |
| Specialization | Generic | Task-specific tools |
| Task complexity | Limited | Multi-hour workflows |
| Result quality | Single perspective | Synthesized from multiple |
| Timeout handling | N/A | 15-minute limit per sub-agent |
For complex AI applications, sub-agents provide a way to decompose problems while maintaining isolation and enabling parallelism.
My Recommendation
Sub-agents are powerful but shouldn’t be the default. I recommend:
Use sub-agents when:
- Tasks are independent and parallelizable
- You need multiple perspectives on a problem
- Each sub-task has a clear, bounded scope
- You want to avoid context contamination
Stick with single agent when:
- Tasks are quick and simple
- Context sharing is important
- Sequential execution makes sense
- You’re doing conversational follow-ups
For teams building AI workflows in DeerFlow, start with the single agent. Add sub-agents only when you identify bottlenecks that parallelization can solve.
Summary
DeerFlow’s sub-agent system enables true parallel task execution through hierarchical agent delegation. The lead agent spawns child agents with isolated contexts, runs up to 3 concurrently, and synthesizes results.
I tested the system with parallel research tasks and observed 2.5x speedup for independent operations. The key limitations are: 3 concurrent sub-agents maximum, 15-minute timeout per sub-agent, and no context sharing between agents.
For developers building complex AI workflows, sub-agents provide a pattern for decomposing large tasks while maintaining isolation and enabling parallelism. The tradeoff is coordination overhead, so reserve sub-agents for tasks that genuinely benefit from parallel execution.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments