One call asks the lead to split the question into independent sub-questions, one per line, at
most MAX_WORKERS (3 by default). Code parses that text into a list, drops exact duplicates, and
caps it at MAX_WORKERS if the lead asked for more: the lead’s split is a proposal the code is
free to cut down, never a command code obeys blindly. Anthropic’s own research system names what a
good brief needs: “Each subagent needs an objective, an output format, guidance on the tools and
sources to use, and clear task boundaries”[2]; this example’s brief is just the
sub-question text, the simplest version of that, since every worker already shares one tool (the
corpus) and one output shape (a cited answer).
Each worker is examples.rag.run.run, imported and called unmodified: a level-2 single call, not
a loop, which is the cheap end of what a worker can be. A team that needed a
worker to search iteratively would hand it examples.agentic_rag.run.run instead; nothing else in
this file would change, since both share the same (question, model, embedder, tracer) -> Answer
signature.
examples/orchestrator_workers/run.py · lines 76–117
def run(
question: str,
model: Model,
embedder: Embedder,
tracer: Tracer,
*,
corpus_dir: Path = DEFAULT_CORPUS_DIR,
max_workers: int = MAX_WORKERS,
max_team_tokens: int = MAX_TEAM_TOKENS,
) -> Answer:
subquestions = _split(question, model, tracer)
if len(subquestions) > max_workers:
tracer.record(
kind="code",
decided_by="code",
title="Cap the team",
detail=f"lead asked for {len(subquestions)} workers, capped at {max_workers}",
)
subquestions = subquestions[:max_workers]
worker_answers: list[tuple[str, Answer]] = []
for i, subq in enumerate(subquestions, start=1):
team_tokens = tracer.tokens_in_total() + tracer.tokens_out_total()
if team_tokens >= max_team_tokens:
tracer.record(
kind="code",
decided_by="code",
title="Team token budget reached",
detail=f"stopping before worker {i} of {len(subquestions)}: {team_tokens} >= {max_team_tokens}",
)
break
tracer.record(kind="code", decided_by="code", title=f"Spawn worker {i}", detail=subq)
worker_answer = rag_worker(subq, model, embedder, tracer, corpus_dir=corpus_dir)
worker_answers.append((subq, worker_answer))
if not worker_answers:
return Answer(text="No worker returned an answer.", citations=[])
combined_text = _combine(question, worker_answers, model, tracer)
retrieved = sorted({c for _, a in worker_answers for c in a.retrieved_sources})
return Answer.from_text(combined_text, retrieved_sources=retrieved)
tracer.tokens_in_total() + tracer.tokens_out_total() is the whole team’s running spend, checked
before every worker spawns; once it passes MAX_TEAM_TOKENS (6,000 by default) the remaining
sub-questions are dropped and the run ends with whatever workers already answered, rather than
spawning one more. The split call is the only step in this file with decided_by: "model": the
lead’s output is what picks which sub-questions exist and how many workers run. Every worker’s own
steps stay decided_by: "code", the same as RAG’s page,
because retrieval inside a worker is still fixed. The diagram above draws that one call as two
dashed edges, because a reader has to see both assignments happen; its own note says so, and the
recorded trace counts the decision once.
Run it yourself:
examples/orchestrator_workers/README.md · lines 16–16
python -m examples.orchestrator_workers --model stub:scripted
CrewAI’s own README describes a similar split. It lists what Crews enable, and the first two
entries are “Natural, autonomous decision-making between agents” and “Dynamic task delegation and
collaboration”[4]; its optional hierarchical process “automatically assigns a manager
to the defined crew to properly coordinate the planning and execution of tasks through delegation
and validation of results”[4]. That manager checks the work as well as parceling it out,
which this example’s combine step does not. Microsoft’s AutoGen, also registered against this
technique, now carries a maintenance notice: “AutoGen is now in maintenance mode. It will not
receive new features or enhancements and is community managed going forward.” and “New users
should start with Microsoft Agent Framework.”[5] A framework named in a tutorial today
may not be the one to build on by the time you read this.