Skip to main content
GroupChat runs a turn-based, self-selecting conversation: there is no fixed speaking order and no speaker-selection function, but exactly one agent speaks per turn. Each turn, every agent privately “bids” — via a forced respond(score, message) tool call — on how much it wants the floor; the single highest (recency-adjusted) bidder above threshold speaks, and only that reply is posted. A recency_penalty discourages the same agent from speaking twice in a row, so the floor moves around the room even though there’s no explicit rotation.

When to Use

  • Debate and discussion: multiple perspectives on a complex topic
  • Collaborative problem-solving: agents build on each other through conversation
  • Brainstorming: emergent ideas from parallel contributions
  • Negotiation: back-and-forth between stakeholders
  • Peer review: evaluating work from several angles at once
This is a rewrite of the older speaker-function design. speaker_function, speaker_state, set_speaker_function, start_interactive_session, @mention routing, and the round-robin-speaker / random-speaker / priority-speaker selectors no longer exist. Use threshold / recency_penalty / max_loops to shape the conversation instead. See the GroupChat API reference.

How It Works

  1. Seed — the task is posted to the shared conversation as the first message; every agent sees it.
  2. Bid (in parallel) — each turn, every agent is asked concurrently (via a forced respond(score, message) tool call) how much it wants to speak, on a 0..1 scale, along with the reply it would give.
  3. Select one speaker — the single highest recency-adjusted bidder that clears threshold and has a non-empty reply takes the floor. Only that one reply is posted to the conversation for this turn.
  4. Recency penalty — an agent that spoke within the last recency_window turns has recency_penalty subtracted from its bid, so the floor tends to move around the room instead of one agent monologuing.
  5. Stop — the chat ends when max_loops total messages have been posted, or a turn arrives where no agent’s adjusted bid clears threshold (a conversational lull).
idle_timeout is accepted for backward compatibility but is currently unused — the chat stops on a bidding lull (step 5 above), not a wall-clock timeout.

Key Features

  • Turn-based self-selection: bids are collected in parallel, but exactly one agent speaks per turn (no fixed speaking order)
  • Self-selection: silence is the default; agents speak only when they add value
  • Forced respond(score, message) decision via RESPOND_TOOL
  • Threshold-based speaker selection with a recency penalty to rotate the floor
  • Auto-equips the respond tool into agents (auto_equip=True)
  • Conversation history tracking and flexible output formats

Basic Example

auto_equip=True (the default) injects the respond tool into each agent, so you do not need to add tools_list_dictionary=[RESPOND_TOOL] yourself.

Shaping the Conversation

There is no speaker function — you steer the room with three parameters.

Threshold

Recency penalty

Max loops (total messages)

max_loops caps the total number of messages posted (the seed task counts as the first), not turns per agent — it’s the primary cost control.

Key Parameters

str
default:"dynamic-groupchat"
Name for the group chat.
str
default:"Agents take turns; one speaker per turn."
Description of the group chat’s purpose.
List[Agent]
required
Participating agents. At least two are required — each message is broadcast to the other agents.
int
default:"20"
Hard cap on total messages posted, including the initial user task.
float
default:"0.5"
Minimum recency-adjusted decision score (0..1) required for an agent to take the floor for a turn.
float
default:"0.3"
Amount subtracted from an agent’s bid if it spoke within the last recency_window turns. Discourages one agent from monologuing; set to 0.0 to disable.
int
default:"1"
How many of the most recent speakers are subject to recency_penalty.
float
default:"8.0"
Accepted for backward compatibility but currently unused — the chat now stops on a bidding lull (no agent clears threshold) rather than a wall-clock timeout.
str
default:"str-all-except-first"
History format. Use "list" or "dict" to iterate individual messages.
bool
default:"True"
Auto-inject the respond tool into agents that lack it.
bool
default:"False"
Emit internal log messages (decision scores, broadcasts, stop events) and print each posted message as a styled panel.

Methods

run()

Run the group chat until no agent’s bid clears threshold (a lull) or max_loops is hit.
By default the result is a formatted string. For per-message iteration, set output_type="list" and read role / content:

run_batch()

Run several independent group chats sequentially, one per task.

The respond Tool

Every agent must carry RESPOND_TOOL so the chat can force a structured speaking decision. With auto_equip=True this is automatic; otherwise add it yourself:
The tool forces a call to respond(score, message): score (0..1) is how much the agent wants to speak, and message is the reply (empty string to stay silent). Each turn, only the single agent with the highest recency-adjusted score above threshold gets its message published.

Use Cases

Debate

Expert Panel

Best Practices

Tuning over speaker functions: shape participation with threshold (selectivity), recency_penalty (how aggressively the floor rotates), and max_loops (total length) — there is no speaker-selection function.
  1. Distinct roles: give each agent a specific perspective so its respond decision is meaningful.
  2. max_loops=1 + persistent_memory=False per agent: keep each speaking decision a clean single-shot call.
  3. Tune threshold to room size: lower (~0.4–0.5) for 2–3 agents, higher (~0.6–0.75) for 4+.
  4. Pick the right output_type: a transcript string by default, or "list"/"dict" to iterate messages.
Conversation length grows with agents and turns — use max_loops to bound total messages and watch context limits.

When NOT to Use