Sprout — a self-growing multi-agent task tree
An open-source framework, designed solo: every Agent decides for itself whether to split, the tree topology has no depth limit, and recursion is the real thing.
Problem
Multi-agent orchestration with preset roles — a fixed researcher / writer / reviewer — can't fit the true shape of a task; a single Agent, meanwhile, is choked by the token and attention bottleneck of one LLM call. The division of labor needs to grow out of the task itself.
Approach
A recursive tree architecture (Python + asyncio for concurrent execution, litellm for multi-provider compatibility): (1) a two-phase Worker — analyze() makes a lightweight call to first decide "should this split?", then execute() does the actual work; separating analysis from execution makes the split decision sharper; (2) Approach injection — when a parent splits, it generates a methodology and focus for each subtask and injects them into the child Agent's system prompt, so roles emerge from the task rather than being preset; (3) straggler handling — if a branch takes markedly longer than its siblings (say 2.5×), it's canceled and re-split; nodes die once done, and results bubble up; (4) four ceilings — max_depth / max_children / max_total_nodes / max_total_tokens — to keep the tree from exploding.
Results
Under a fixed token budget: single Agent scores 25 vs. Sprout's 100
Head-to-head
Breaks past the token and attention bottleneck of a single LLM call
Core value
24 unit tests covering the core modules · MIT open-source
Engineering quality
AI's role in this project
The framework itself is multi-agent engineering: split decisions, straggler detection, result aggregation, and safety boundaries are all designed solo — a first-hand experiment in answering "what does multi-agent actually solve?"
Why I built it
Mainstream multi-agent orchestration runs on "preset roles": pin down researcher / writer / reviewer up front, then feed the task in. But the true shape of a task varies wildly — and a preset structure often doesn't fit. Sprout flips it around: don't preset the structure; let each Agent take its task and decide for itself whether to split, and how, so the task tree grows recursively, with no depth limit.
Four core designs
1. Two-phase Worker. analyze() makes a lightweight call to first decide "should this split?", then execute() does the actual work. Separating analysis from execution makes the split decision sharper — and saves tokens.
2. Approach injection. When a parent splits, it generates a methodology and focus for each subtask and injects them into the child Agent's system prompt — so the child Agent's "role" emerges from the task rather than being hand-assigned.
3. Straggler handling. If a branch takes markedly longer than its siblings (say 2.5×), it's canceled and re-split. Nodes die once done, and results bubble up to the parent.
4. Safety boundaries. Four ceilings — max_depth · max_children · max_total_nodes · max_total_tokens — keep the tree from exploding; 24 unit tests cover the core modules.
Head-to-head
Same task, fixed token budget: single Agent scores 25, Sprout scores 100. The takeaway: Sprout's core value isn't parallel speedup — it's breaking past the token and attention bottleneck of a single LLM call. Every node gets a full context budget to do its own small piece of the work.
Links
- Source: github.com/hlbbbbbbb/sprout (MIT)