In AutoGen's Swarm team, how does one agent actually hand control to another agent?
answer
- the speaker names the successor
- handoffs become transfer tools
- a message carries the target
- the user is just another target
basics
~20 sYou configure an agent with handoffs=["other_agent"], which gives its model a transfer_to_other_agent tool. Calling that tool makes the agent emit a HandoffMessage whose target names the next speaker, and the Swarm team makes that agent speak next.
solid answer
~40 s`Swarm` in `autogen_agentchat.teams` has no central selector: the current speaker decides who goes next. You wire that by passing `handoffs=["reviewer", "billing"]` when constructing an `AssistantAgent`; AutoGen turns each entry into a tool named `transfer_to_<target>` that the model can call. When the model calls it, the agent emits a `HandoffMessage` carrying a `target` and a content string, and the Swarm switches the speaker to that target for the next turn. The first participant in the list speaks first. Messages are broadcast, so the receiving agent sees the shared thread rather than only the handoff payload. To involve a human, give an agent a handoff to `"user"` and stop the run with `HandoffTermination(target="user")`; you resume by calling `team.run()` with a `HandoffMessage(source="user", target="<agent>", content=...)`.
go deeper
Know that in Swarm the current agent chooses the next one, that you declare this with handoffs= on the agent, and that the transfer travels as a HandoffMessage.
Explain the chain: handoffs become transfer_to_<target> tools, the model calls one, a HandoffMessage names the target, and the team switches speaker. Mention that the first participant starts.
Show the operational side: bounding ping-pong with turn caps, keeping handoff menus narrow, and using a handoff to "user" plus HandoffTermination for approval gates and resumption.
Argue about where routing knowledge should live — local to the specialist versus in a central planner — and what that choice costs in debuggability, context growth and failure containment across a fleet of conversations.
## The shape of a Swarm run `Swarm(participants, termination_condition=..., max_turns=...)` is AutoGen AgentChat's decentralised team type. Unlike a selector team, no manager reasons about who should speak; the speaker at each step is whoever the previous speaker named. The first agent in `participants` is the initial speaker, and control moves only when a handoff is emitted. If an agent produces an ordinary text message without handing off, it simply stays the speaker for the next turn. ## Wiring a handoff Handoffs are declared on the agent, not the team: ``` agent = AssistantAgent( "triage", model_client=model_client, handoffs=["refunds", "user"], system_message="Route the customer. Hand off to refunds for money questions.", ) ``` Each string becomes a `Handoff` whose generated tool is named `transfer_to_<target>`. The model sees those tools alongside any real tools the agent has, so "who should handle this" becomes an ordinary tool-calling decision made by the model, guided by your system message. For finer control you can pass `Handoff` objects instead of strings to customise the tool description and the message the handoff carries. ## What crosses the boundary Calling the tool produces a `HandoffMessage` with `source` (the handing-off agent), `target` (the named next speaker), and `content` (a short brief, typically "transferring to refunds"). The Swarm reads `target` and installs that participant as the speaker. A point candidates often get wrong: the receiving agent does not start from a blank slate holding only the handoff content. Swarm broadcasts messages to participants, so the receiver has the shared conversation available. The handoff content is a hint about intent, not the entire information transfer. That is convenient — the new agent has the customer's original words — and it is the reason Swarm runs get expensive as the thread grows, since every participant re-reads the accumulated history. ## Bringing a human in The canonical human-in-the-loop pattern uses a handoff target of `"user"` plus `HandoffTermination(target="user")` from `autogen_agentchat.conditions`. When an agent decides it needs a person, it hands off to `"user"`; the condition fires and `run()` returns with a `stop_reason` about the handoff. Your application collects the human input and resumes by calling `run()` again with a `HandoffMessage(source="user", target="triage", content="...")`, which names the agent that should pick the conversation back up. Because a team keeps its message thread across runs, the conversation continues rather than restarting. ## Failure modes to expect **Ping-pong.** Two agents that each believe the other owns the request hand back and forth. Nothing in Swarm detects this; the run ends only when your `max_turns` or a message cap fires. Bound the run, and write system messages that say when an agent must answer rather than transfer. **Handoff to a non-participant.** The target must name an actual participant. A model that invents a target, or an agent configured with a handoff to an agent you forgot to include in the participants list, breaks the run rather than degrading gracefully. **Over-broad handoff menus.** Giving every agent a handoff to every other agent turns speaker selection into a large tool-choice problem and raises the ping-pong rate. Model the intended flow and declare only the transfers that flow requires. **Silent stalls.** An agent that neither answers nor hands off keeps the turn. Repeated turns from the same source in your message log is the signature; a message cap turns it from a hang into a visible failure. ## When Swarm is the right team Swarm fits when routing knowledge is local — the specialist that has the conversation knows better than any central planner who should take it next — and when you want the human to be just another handoff target rather than a special case. It fits badly when you need a global view to allocate work, or when the flow is a fixed pipeline that a simpler team expresses without any tool calls at all.
- Does the receiving agent in a Swarm see only the handoff message content?No. Swarm broadcasts the conversation to participants, so the receiver has the shared thread, not just the handoff payload. The `content` on the `HandoffMessage` is a short statement of intent. That is why handoffs feel seamless to users, and also why long Swarm conversations get costly — every participant re-reads a growing history on its turn.
- How do you pause a Swarm for human input and then resume it?Give the relevant agent a handoff target of `"user"` and pass `HandoffTermination(target="user")` as the team's termination condition. The run returns when that handoff is emitted; you gather the person's reply and call `run()` again with `HandoffMessage(source="user", target="<agent name>", content=...)`. The team's retained thread means the conversation continues rather than restarting.
- Two Swarm agents keep transferring the request back and forth. What in the configuration do you change?Swarm itself will not notice, so first make the failure bounded with `max_turns` or a message-count termination so it surfaces as a stop_reason instead of a hang. Then narrow the handoff menus so each agent can transfer only along the intended flow, and tighten system messages to state explicitly when the agent must answer rather than transfer.
saying these in an interview costs you the question
- Thinks a central manager chooses the next Swarm speaker
- Believes the receiving agent only sees the handoff content
- Assumes Swarm detects and breaks handoff loops itself
- Forgets to include a handoff target in the participants list
- Thinks handoffs are configured on the team rather than the agent