Skip to main content

A multi-agent teams implementation using LangGraph (Blackboard & Mailbox architecture)

Project description

๐Ÿค LangGraph Agent Teams

A Python library for building agent teams with LangGraph, inspired by the Claude Code Agent Teams feature. One agent acts as the team lead โ€” coordinating work, assigning tasks, and synthesizing results โ€” while teammates work independently, each in its own context window, claiming tasks from a shared task list and messaging each other through mailboxes.

Unlike supervisor/subagent patterns where workers only report back to a caller, agent teams coordinate through two shared primitives:

  • Task board โ€” a shared list of work items with dependencies (blocks / blocked_by). The lead creates tasks; teammates claim and complete them. Claiming uses file locking, so concurrent teammates never grab the same task.
  • Mailbox โ€” asynchronous, direct agent-to-agent messaging. Any member can message any other member by name โ€” teammate-to-teammate debate is a first-class capability, not just teammate-to-lead reporting. Idle notifications flow to the lead automatically, and the team shuts down gracefully via a shutdown request/response protocol.

As in Claude Code, the coordination tools (SendMessage plus the task tools) are always available to every team member โ€” define members with TeamMemberSpec and the package attaches them automatically.

All coordination state (task board, mailboxes, roster) is persisted as JSON files on disk โ€” you can cat a mailbox or ls the task list at any time while the team is running, and state survives crashes.

Features

  • ๐Ÿ‘‘ Lead / teammate architecture โ€” a coordinator agent delegates to independent worker agents
  • ๐Ÿ“‹ Shared task board โ€” dependency-aware tasks with atomic, lock-protected claiming
  • ๐Ÿ“ฌ Inter-agent mailboxes โ€” every member can message every other member (or broadcast), with idle notifications and graceful shutdown
  • ๐Ÿงฐ Coordination tools always on โ€” TeamMemberSpec members automatically get SendMessage + task tools, like Claude Code teammates
  • โšก True parallelism โ€” teammates run concurrently as async LangGraph nodes
  • ๐Ÿ—‚๏ธ File-system-as-a-bus โ€” inspect and debug the team's state live on disk
  • ๐Ÿ› ๏ธ LangChain tools included โ€” SendMessage, TaskCreate, TaskUpdate, TaskList, TaskGet

When to Use Agent Teams

Agent teams shine when parallel exploration adds real value:

  • Research and review โ€” teammates investigate different aspects of a problem simultaneously
  • New modules or features โ€” each teammate owns a separate piece without stepping on the others
  • Competing hypotheses โ€” teammates test different theories in parallel and converge faster
  • Cross-layer work โ€” frontend, backend, and tests each owned by a different teammate

For sequential tasks or work with many dependencies, a single agent or a supervisor/subagent pattern is more effective โ€” teams add coordination overhead and use more tokens.

Installation

pip install langgraph-agent-teams

Quickstart

pip install langgraph-agent-teams langchain-openai

export OPENAI_API_KEY=<your_api_key>
import asyncio

from langgraph_agent_teams import TeamMemberSpec, create_agent_team

# Every member automatically gets the coordination tools:
# SendMessage, TaskCreate, TaskUpdate, TaskList, TaskGet
lead = TeamMemberSpec(
    name="team-lead",
    model="openai:gpt-5.5",
    system_prompt="You are a team lead. Delegate work to your teammates.",
)
researcher = TeamMemberSpec(
    name="researcher",
    model="openai:gpt-5.5",
    system_prompt="You are a thorough researcher.",
    agent_type="researcher",
)
critic = TeamMemberSpec(
    name="critic",
    model="openai:gpt-5.5",
    system_prompt="You are a devil's advocate who challenges findings.",
    agent_type="critic",
)

app = create_agent_team(
    lead, [researcher, critic], team_name="research-team"
).compile()

result = asyncio.run(
    app.ainvoke(
        {
            "messages": [
                {
                    "role": "user",
                    "content": "Evaluate whether we should migrate from REST to GraphQL. "
                    "Have one teammate research the benefits and another challenge them.",
                }
            ]
        }
    )
)
print(result["messages"][-1].content)

[!IMPORTANT] Agent teams rely on asyncio concurrency โ€” the lead and all teammates run at the same time. Always invoke the compiled graph with await app.ainvoke(...) (or asyncio.run(...)); synchronous invoke is not supported.

How It Works

              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   user โ”€โ”€โ”€โ”€โ–บ โ”‚  team lead  โ”‚ โ—„โ”€โ”€โ”€โ”€ idle notifications, reports, replies
              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        TaskCreate / โ”‚ SendMessage
         TaskUpdate  โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚      shared task board        โ”‚   {base_dir}/tasks/{team}/
   โ”‚  1.json  2.json  .lock  ...   โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ”‚ claim (locked)  โ”‚ claim (locked)
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚ teammate A  โ”‚   โ”‚ teammate B  โ”‚   each with its own context window
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ–ฒ                 โ–ฒ
          โ””โ”€โ”€โ”€โ”€โ”€ mailboxes โ”€โ”˜           {base_dir}/teams/{team}/inboxes/
  1. A setup node resets the team's on-disk state and registers every member in the roster.
  2. The lead node runs the lead agent with a coordination briefing. The lead breaks the request into tasks (TaskCreate), optionally assigns them (TaskUpdate with owner), and messages teammates (SendMessage).
  3. Each teammate node runs a poll loop: read unread mail โ†’ claim the next available task โ†’ run its own agent turn โ†’ mark the task complete โ†’ report the result and an idle notification back to the lead.
  4. Teammate messages are delivered to the lead automatically; the lead responds, reassigns, or creates follow-up work.
  5. When every task is complete and all teammates are idle, the lead broadcasts a shutdown request; each teammate acknowledges with a shutdown response and exits. The lead's final message synthesizes the team's results.

Task dependencies

Tasks can depend on each other. A pending task with unresolved dependencies cannot be claimed until those dependencies are completed โ€” blocked tasks unblock automatically:

# Inside the lead's reasoning, via the TaskCreate / TaskUpdate tools:
#   TaskCreate(subject="Research API options", description="...")            -> task 1
#   TaskCreate(subject="Write recommendation", description="...", blocked_by=["1"])  -> task 2

Lead-assigned vs. self-claimed tasks

  • Lead assigns: the lead sets owner on a task with TaskUpdate โ€” only that teammate can claim it.
  • Self-claim: unassigned tasks are claimed by idle teammates in ID order.

Teammate-to-teammate communication

Every TeamMemberSpec member can message any other member by name with SendMessage โ€” the classic "teammates debate each other" pattern from the Claude Code docs works out of the box:

result = await app.ainvoke({"messages": [{
    "role": "user",
    "content": "Investigate why the app disconnects after one message. "
    "Have teammates pursue different hypotheses and message each other "
    "to try to disprove each other's theories, like a scientific debate.",
}]})

Communication is agent-driven with a harness fallback: if a teammate finishes a turn without calling SendMessage, its final reply is forwarded automatically โ€” task reports go to the lead, message replies go back to the sender โ€” so no work is silently lost even with models that under-use tools. Fallback replies are marked internally and never trigger another automatic reply, so two teammates can't ping-pong forever.

Using prebuilt agents (advanced)

You can also pass prebuilt agents (e.g. from langchain.agents.create_agent) instead of specs โ€” useful when you need middleware or custom agent construction. In that case, attach the coordination tools yourself so the agent can communicate:

from langchain.agents import create_agent
from langgraph_agent_teams import create_team_tools

coder = create_agent(
    model="openai:gpt-5.5",
    tools=[*my_tools, *create_team_tools("coder", team_name="research-team")],
    name="coder",
)

Prebuilt agents without team tools still work โ€” the harness claims tasks, completes them, and forwards their replies for them.

Inspecting a Running Team

Team state lives under ~/.langgraph-agent-teams by default (override with base_dir):

~/.langgraph-agent-teams/
โ”œโ”€โ”€ teams/{team_name}/
โ”‚   โ”œโ”€โ”€ config.json          # Roster: members, roles, live status
โ”‚   โ””โ”€โ”€ inboxes/
โ”‚       โ”œโ”€โ”€ team-lead.json   # The lead's mailbox
โ”‚       โ””โ”€โ”€ researcher.json  # A teammate's mailbox
โ””โ”€โ”€ tasks/{team_name}/
    โ”œโ”€โ”€ .lock                # Claim lock
    โ”œโ”€โ”€ .highwatermark       # Highest task ID ever created
    โ””โ”€โ”€ 1.json               # Task #1
# Watch the task board while the team works
watch -n1 'cat ~/.langgraph-agent-teams/tasks/research-team/*.json | jq -r "\(.id) [\(.status)] \(.owner // \"unassigned\") โ€” \(.subject)"'

You can also use the store classes directly:

from langgraph_agent_teams import get_team_resources

resources = get_team_resources("research-team")
for task in resources.task_board().list_tasks():
    print(task.id, task.status, task.owner, task.subject)
for message in resources.mailbox().read_all("team-lead"):
    print(message.from_agent, "->", message.summary or message.text[:80])

API Reference

TeamMemberSpec(name, model, system_prompt=None, tools=[], agent_type=None)

Declarative definition of one team member. The package builds the agent with langchain.agents.create_agent and automatically attaches the five coordination tools bound to the member's identity. tools adds extra domain tools on top; agent_type is a role label shown in the roster and briefings.

create_agent_team(lead, teammates, team_name, base_dir=None, *, poll_interval=0.5, shutdown_timeout=60.0, max_agent_turns=100)

Builds the team StateGraph. The lead and every teammate run as concurrent async nodes; compile and ainvoke it like any LangGraph graph.

Parameter Description
lead TeamMemberSpec (recommended) or a prebuilt agent equipped with create_team_tools.
teammates TeamMemberSpecs (recommended) or prebuilt agents, each with a unique name.
team_name Unique team name; also names the on-disk state directories.
base_dir Root directory for team state (default ~/.langgraph-agent-teams).
poll_interval Seconds between mailbox/task-board polls.
shutdown_timeout Max seconds the lead waits for shutdown acknowledgements.
max_agent_turns Safety cap on agent invocations per member per run.

create_team_tools(agent_name, team_name, base_dir=None)

Returns the five coordination tools bound to one agent's identity:

Tool Purpose
SendMessage DM another agent by name, or "*" to broadcast
TaskCreate Add a task to the shared board (optionally blocked_by)
TaskUpdate Change status/owner/description, add dependency edges
TaskList List every task with status, owner, and blockers
TaskGet Fetch one task's full details

Store classes

SwarmTaskBoard, AgentMailbox, and TeamRoster are exported for direct use โ€” every operation is atomic and protected by portalocker file locks, so they're safe across threads, asyncio tasks, and even separate processes.

Comparing Agent Teams with Other Multi-Agent Patterns

Pattern Coordination Communication Best for
Agent Teams Shared task list + lead Teammates message each other directly Parallel work requiring discussion and collaboration
Group Chat Centralized selector Broadcast (shared history) Moderated turn-taking discussions
Swarm Decentralized handoffs Control transfer via tools Fluid handoffs, direct user interaction
Subagents Main agent delegates Results report back to caller only Focused tasks where only the result matters

Use subagents when you need quick, focused workers that report back. Use agent teams when workers benefit from a shared work queue, independent context windows, and inter-agent communication.

Best Practices

  1. Give teammates enough context โ€” teammates don't see the lead's conversation history, so the lead's task descriptions must be self-contained (the built-in briefing tells it so)
  2. Size tasks appropriately โ€” self-contained units with a clear deliverable; 5โ€“6 tasks per teammate keeps everyone productive
  3. Start with 3โ€“5 teammates โ€” token costs scale linearly with team size, and coordination overhead grows with it
  4. Avoid file conflicts โ€” if teammates edit files, break work so each owns a different set
  5. Use dependencies for ordering โ€” blocked_by edges let the board sequence work without the lead micromanaging

Examples

See the examples/ directory:

  • software_team โ€” a lead coordinating researcher/coder/reviewer teammates

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License โ€” see LICENSE for details.

Acknowledgments

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langgraph_agent_teams-0.1.0.tar.gz (31.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langgraph_agent_teams-0.1.0-py3-none-any.whl (27.4 kB view details)

Uploaded Python 3

File details

Details for the file langgraph_agent_teams-0.1.0.tar.gz.

File metadata

  • Download URL: langgraph_agent_teams-0.1.0.tar.gz
  • Upload date:
  • Size: 31.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for langgraph_agent_teams-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f9cb9913e8ff2b7f15373c29dc0e220792cd09140f231097efab7d61330266a6
MD5 a7034014c1429c4748cf8ddea7848ee7
BLAKE2b-256 af02bf52f3fe1d3e3faf1e7ce1b83b450a9259c443fbe363e7d94975726592eb

See more details on using hashes here.

File details

Details for the file langgraph_agent_teams-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for langgraph_agent_teams-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a5c4a5d72af66599f1cdc9b88c88938dfd33c8a6096b38c67605db62ec5b71cf
MD5 baf2475aab510c5fcfad5cc7a4e6ba26
BLAKE2b-256 2b30c298902bb3d01ee93cfef0a8387be9e8a3d1432072b7ced74ac7e53c9e53

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page