Skip to content

Manager-Worker: One Agent Assigns, Others Execute

As travel planning grows, one agent has to do too much: budget, routing, food, writing, safety checks. A manager can split the task and send narrow work to workers.

Manager-Worker is not "more agents are better". It is about clear responsibility: the manager assigns and synthesizes; workers do narrow tasks.

One Sentence

Manager-Worker turns one overloaded agent into manager decomposes, workers execute, manager synthesizes, so complex tasks are easier to divide and trace.

What Breaks Without It

Problem What it looks like Risk
One agent owns everything Simple Context and responsibilities mix
No subtask owner Flexible Failures have no clear owner
No synthesis owner Everyone says something Final answer conflicts

What This Pattern Changes

Who Owns
Manager Decomposes, chooses workers, writes final answer
Worker Executes narrow task
Python Validates assignments, runs workers, collects results, traces

The final answer usually belongs to the manager. Workers do not directly own the user response.

Walk Through One Trace

Stage Content
Manager assigns math computes 2+2, writer explains
Workers execute math returns 4, writer returns explanation
Manager synthesizes 2+2=4. It is the sum of two and two.

For travel, workers can handle budget, route, food, and writing.

Flow

flowchart TD
  T["Task"] --> M["Manager decomposes"]
  M --> W1["Worker: budget"]
  M --> W2["Worker: route"]
  M --> W3["Worker: writing"]
  W1 --> R["Collected results"]
  W2 --> R
  W3 --> R
  R --> M2["Manager writes final answer"]

Code Walk

The manager first returns assignments:

manager = MockLLM(
    [
        '{"assignments":[{"worker":"math","task":"Compute 2+2"},{"worker":"writer","task":"Explain the result in one sentence"}]}',
        "2+2=4. It is the sum of two and two.",
    ]
)

A worker has a name, description, and model:

Worker(name="math", description="Fast arithmetic and exact calculations.", model=MockLLM(["4"]))

Full example:

from __future__ import annotations

from pathlib import Path

from agent_patterns_lab.patterns.manager_worker import Worker, run_manager_worker
from agent_patterns_lab.runtime import MockLLM, Tracer


def main() -> None:
    tracer = Tracer()

    manager = MockLLM(
        [
            '{"assignments":[{"worker":"math","task":"Compute 2+2"},{"worker":"writer","task":"Explain the result in one sentence"}]}',
            "2+2=4. It is the sum of two and two.",
        ]
    )

    workers = [
        Worker(
            name="math",
            description="Fast arithmetic and exact calculations.",
            model=MockLLM(["4"]),
        ),
        Worker(
            name="writer",
            description="Clear, concise explanations.",
            model=MockLLM(["Because adding 2 and 2 yields 4."]),
        ),
    ]

    out = run_manager_worker(manager, workers, task="What is 2+2? Explain briefly.", tracer=tracer)
    print(out)

    trace_path = tracer.export_jsonl(Path(".traces") / "60_manager_worker.jsonl")
    print(f"[trace] {trace_path}")


if __name__ == "__main__":
    main()

Run:

UV_CACHE_DIR=.uv_cache PYTHONPATH=src uv run --no-sync python examples/60_manager_worker.py

Nearby Patterns

Pattern Final answer owner Use when
Manager-Worker Manager Work splits across workers
Agents-as-Tools Controller agent Experts are callable tools
Handoff Specialist Current agent transfers ownership
Group Chat Moderator or final writer Debate/discussion matters

When To Use It

  • Subtasks can be separated.
  • Worker responsibilities are clear.
  • Manager can synthesize results.
  • You need per-worker trace.

When Not To Use It

  • A normal function is enough.
  • Workers overlap heavily.
  • Final-answer ownership is unclear.
  • Shared context is too important to split.

Costs And Common Failures

Failure Symptom Fix
Over-decomposition Many worker calls, little value Merge small tasks
Bad worker contract Manager cannot consume output Use structured worker output
Synthesis loses info Worker result omitted List all worker results in manager input
High cost Many models/calls Route only complex tasks here

Manager-Worker fits explicit delegation.

If the controller calls experts as tools, read Agents-as-Tools. If a specialist should take over, read Handoff.

References