Skip to content

Chapter 10 · Team Advanced: Shared State and Member Communication ​

Learning objectives: Master switching between the four collaboration modes, learn the correct posture for shared session state across members, and observe team-internal division of labor through streaming events.

10.1 Four Collaboration Modes Overview ​

Last chapter we used mode=TeamMode.coordinate to let the leader dispatch tasks. Agno explicitly exposes four collaboration styles (from agno.team.mode import TeamMode):

ModeConfigBehavior
Coordinate (default)Omit mode or set coordinateLeader picks members, rewrites tasks, synthesizes results
Routemode=TeamMode.routeLeader routes to one member, returns that member's reply directly
Broadcastmode=TeamMode.broadcastSame task sent to all members
Tasksmode=TeamMode.tasksLeader maintains a shared task list, looping until completion

On legacy parameters

Old versions' respond_directly=True and delegate_to_all_members=True remain compatible (mapping to route and broadcast respectively), but new code should always use mode= — when both appear, mode overrides the legacy flags.

10.2 Route Mode: Direct-to-Reply ​

Customer-service triage, language routing — scenarios where the leader doesn't need to process the result further. Route mode has the lowest latency:

python
import os
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.team import Team, TeamMode

model = OpenAIChat(
    id="deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1",
)

billing_agent = Agent(name="Billing Agent", role="Handle billing and refund issues", model=model)
tech_agent = Agent(name="Tech Agent", role="Handle technical fault issues", model=model)

router_team = Team(
    name="Customer Router",
    model=model,
    mode=TeamMode.route,
    members=[billing_agent, tech_agent],
    # Key switch: pass user's original input verbatim to members; don't let the leader rewrite
    determine_input_for_members=False,
    instructions=["Route the request to the most suitable member; answer yourself if unsure."],
)

router_team.print_response("My order was charged twice", stream=True)

determine_input_for_members=False is an important detail in route mode: without it, the leader still "polishes" the task description by default, which introduces distortion in scenarios requiring passthrough.

10.3 Broadcast and Tasks Modes ​

Broadcast suits "multi-perspective parallel review"; task loops suit goal-driven long flows:

python
from agno.team import Team, TeamMode

# Broadcast: three reviewers each receive the same draft
review_team = Team(
    name="Review Panel",
    model=model,
    mode=TeamMode.broadcast,   # Same task to each member
    members=[
        Agent(name="Legal Reviewer", role="Review from compliance perspective", model=model),
        Agent(name="UX Reviewer", role="Review from user-experience perspective", model=model),
        Agent(name="SEO Reviewer", role="Review from search-optimization perspective", model=model),
    ],
    instructions="Synthesize all member opinions into a single merged revision checklist.",
)

# Task loop: leader decomposes a task list and advances item by item
ops_team = Team(
    name="Ops Team",
    model=model,
    mode=TeamMode.tasks,
    max_iterations=6,          # Cap the task loop iterations to prevent runaway token burn
    members=[tech_agent, billing_agent],
)

Always set max_iterations in Tasks mode: the task list is generated and checked off by the model; an uncapped loop is equivalent to handing your budget to the model.

10.4 Shared Session State Across Members ​

To let multiple members collaborate around the same mutable state (e.g., jointly maintaining a shopping list), the core is three things: declare session_state on the team, enable add_session_state_to_context, and share the same database between team and members:

python
import os
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIChat
from agno.team import Team

db = SqliteDb(db_file="tmp/team.db")
model = OpenAIChat(
    id="deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1",
)

shopping_agent = Agent(
    id="shopping-agent",
    name="Shopping List Agent",
    role="Manage the shopping list",
    model=model,
    db=db,                                    # Must share the same db as the team to share sessions
    add_session_state_to_context=True,        # Let members see session state
    enable_agentic_state=True,                # Allow members to autonomously modify state in conversation
)

team = Team(
    name="Household Team",
    members=[shopping_agent],
    session_state={"shopping_list": []},      # Initial shared state
    db=db,
    add_session_state_to_context=True,
    enable_agentic_state=True,
    description="You are a team that manages shopping lists and household tasks",
    show_members_responses=True,
)

team.print_response("Add milk, eggs, and bread to the shopping list")
team.print_response("I already bought eggs; what's still on the list?")

print(f"Final state: {team.get_session_state()}")

Another lightweight trick is template injection — state variables can be written directly into instructions and are auto-replaced at runtime:

python
team = Team(
    members=[],
    session_state={"user_name": "Xiaoming"},
    instructions="The user's name is {user_name}; address them by name.",
    markdown=True,
)

10.5 Observing the Division of Labor: Streaming Events and Member Responses ​

The key to debugging a team is seeing "who is doing what." Three techniques work together:

python
team = Team(
    name="Research Team",
    model=model,
    members=[news_agent, finance_agent],
    markdown=True,
    show_members_responses=True,   # Attach each member's raw reply in the final output
)

# With stream=True you can observe the full leader-dispatch → member-execute → leader-synthesize process
for event in team.run("What are the recent AI company moves and NVDA stock performance?", stream=True):
    print(event)   # Member start, tool calls, content increments all have corresponding events

Three supporting best practices:

  1. Set explicit ids on members: dispatch selection and run tracking both use member id — more stable than relying on name;
  2. Model inheritance: when a member doesn't set model, it automatically inherits the team's model — letting you "members use small models, leader uses a large model" with a single omission;
  3. Callable factories: members= can accept functions that dynamically decide the lineup based on session_state at each run (remember to set cache_callables=False).

10.6 Chapter Summary ​

  • New code统一用 mode=TeamMode.coordinate/route/broadcast/tasks; legacy flag respond_directly is superseded by the override mechanism;
  • Route mode with determine_input_for_members=False passthroughs user input verbatim;
  • Full conditions for shared state: team and members share db + both have add_session_state_to_context=True + enable_agentic_state=True when autonomous modification is needed;
  • Instructions support {var} template injection from session state;
  • show_members_responses + streaming events + explicit member ids are the three-pronged approach to observing team division of labor.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. In Agno, to have "the leader only pick a member and return that member's reply directly", the recommended写法 is?

2. In route mode, to pass the user's original input through to members without rewriting, you should?

3. The minimal config to let members read and autonomously modify the team session state is?

4. Regarding Tasks mode, which statement is correct?

🛠️ Hands-On Exercises ​

  1. Use route mode to build a "Chinese/English/code question" three-way router; compare member input with and without the determine_input_for_members switch.
  2. Add a "cooking suggestion" member to the shopping list team from 10.4; verify both members can read entries written by the other.
  3. Enable show_members_responses=True and run a coordinate-mode team with stream=True; record the event sequence (leader dispatch → member → synthesis) and write it as an observation note.

Next chapter brings "determinism" back: when the flow should not be improvised by the model on the fly, Workflow is the better orchestration tool.