← All projects

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.

PythonasynciolitellmMulti-AgentRecursive task decomposition

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