docs: Updated the docs to mention the new support for the teammate pattern in graph agents
2 files changed
+75
-3
No files matched your search
+5
@@ -729,6 +729,11 @@ their siblings. For a working example of the teammate pattern, see the built-in
|
||||
[code-reviewer](https://github.com/Dark-Alex-17/coyote/blob/main/assets/agents/code-reviewer) agent, which spawns file-specific reviewers that share
|
||||
cross-cutting findings with each other.
|
||||
|
||||
Sub-agents run by [graph agent nodes](Graph-Agents#agent) can also form per-fan-out teams: set `teammates: true` on the
|
||||
agent node and concurrent siblings (map branches or same-super-step flagged nodes) get pre-provisioned inboxes, a roster
|
||||
block in their prompts, and a `peers` section in `agent__list_running`. See
|
||||
[Teammate messaging in fan-outs](Graph-Agents#teammate-messaging-in-fan-outs).
|
||||
|
||||
## Runaway Safeguards
|
||||
|
||||
The spawning system includes built-in safeguards to prevent runaway agent chains:
|
||||
|
||||
+70
-3
@@ -67,6 +67,10 @@ top_p: null # default sampling top-p
|
||||
reasoning_effort: null # default reasoning effort for llm nodes (model-dependent; e.g. low, medium, high)
|
||||
max_concurrent_jobs: null # optional; graph-wide [background job](Background-Jobs) budget shared by all llm nodes
|
||||
# (jobs themselves are node-local); overrides the global setting, 0 disables
|
||||
can_spawn_agents: null # optional; whether llm nodes may spawn dynamic sub-agents via the agent__* tools;
|
||||
# defaults to true iff the graph contains at least one agent node
|
||||
max_concurrent_agents: null # optional; cap on dynamically spawned sub-agents running at once (default 4)
|
||||
max_agent_depth: null # optional; max agent nesting depth, i.e. agents spawning agents (default 3)
|
||||
global_tools: # global tools available to nodes
|
||||
- web_search_coyote.sh
|
||||
mcp_servers: # MCP servers available to nodes
|
||||
@@ -132,9 +136,17 @@ nodes:
|
||||
see a variable inside prompts, seed its value into state (typically via
|
||||
a setup script that reads the env var and writes it into state) so
|
||||
`{{name}}` resolves.
|
||||
- **`can_spawn_agents` is derived, not declared.** A graph agent can spawn
|
||||
child agents iff its graph contains at least one `agent` node. You don't
|
||||
set a flag. The `agent` node's presence *is* the declaration.
|
||||
- **`can_spawn_agents` is declared, or derived when omitted.** When the key
|
||||
is absent, a graph agent can spawn dynamic child agents iff its graph
|
||||
contains at least one `agent` node; an explicit value overrides that
|
||||
derivation. Set `can_spawn_agents: true` on a graph with only `llm` nodes
|
||||
to build an **orchestrator graph**: its `llm` nodes get the full
|
||||
`agent__*` toolset (spawn/collect/messaging/task queue) and can drive
|
||||
dynamic sub-agent teams. Setting it `false` on a graph that *does* have
|
||||
`agent` nodes still runs those nodes; only dynamic spawning from `llm`
|
||||
nodes is disabled (the agent-recursion depth guard stays active either
|
||||
way). `max_concurrent_agents` (default 4) and `max_agent_depth`
|
||||
(default 3) cap dynamic spawning; the validator warns on zero values.
|
||||
- **`max_loop_iterations`:** This is a **per-node visit cap**, not a total
|
||||
graph-step cap. If the same node id is entered more than this many times,
|
||||
execution aborts with `Node 'X' visited N times (max_loop_iterations=...)`.
|
||||
@@ -230,6 +242,7 @@ research_topic:
|
||||
agent: deep-researcher # name of an existing Coyote agent
|
||||
prompt: "Research {{topic}}" # interpolated against state
|
||||
timeout: 600 # optional, in seconds (default 300)
|
||||
teammates: false # optional; peer messaging with concurrent siblings (see below)
|
||||
state_updates:
|
||||
findings: "{{output}}"
|
||||
output_schema: { ... } # optional, see "Structured Output" below
|
||||
@@ -244,6 +257,11 @@ research_topic:
|
||||
whole graph fails (no built-in fallback path on agent nodes).
|
||||
- **`state_updates`:** Map of `state_key: "{{template}}"`. The child agent's
|
||||
final text is available inside this map as `{{output}}`.
|
||||
- **`teammates`:** Opt-in peer messaging. When `true` and this node runs
|
||||
concurrently with other flagged agent nodes (as branches of one `map`
|
||||
fan-out, or alongside other `teammates: true` agent nodes in the same
|
||||
super-step), the sibling sub-agents can message each other during the
|
||||
run. See [Teammate messaging in fan-outs](#teammate-messaging-in-fan-outs).
|
||||
|
||||
---
|
||||
|
||||
@@ -999,6 +1017,55 @@ invoking `research_subject` with `{{subject}}` bound to the item.
|
||||
Outputs are collected into `research_results` **in input order**
|
||||
regardless of which sub-branch finished first.
|
||||
|
||||
## Teammate messaging in fan-outs
|
||||
|
||||
By default, concurrent sub-agents in a fan-out are mutually invisible:
|
||||
each reports only through its own branch output. Setting `teammates: true`
|
||||
on an `agent` node turns the concurrent siblings into a communicating
|
||||
team:
|
||||
|
||||
```yaml
|
||||
review_file:
|
||||
id: review_file
|
||||
type: agent
|
||||
agent: file-reviewer
|
||||
prompt: "Review {{file}}"
|
||||
teammates: true
|
||||
```
|
||||
|
||||
Mechanics:
|
||||
|
||||
- **Scope = one fan-out.** A team forms per `map` node (its branches) or
|
||||
per super-step (the `teammates: true` agent nodes in that frontier), and
|
||||
requires at least two members. Each fan-out gets its *own* registry: a
|
||||
flagged map fan-out and a flagged agent node in the same super-step form
|
||||
two separate teams and cannot message each other.
|
||||
- **Pre-provisioned inboxes.** Every member's `(id, inbox)` pair is created
|
||||
before any branch starts, so a fast sibling can message one that has not
|
||||
started yet -- the message simply waits in its inbox.
|
||||
- **Roster injection.** Each member's prompt gains a roster block naming
|
||||
its teammates (collision-safe `graph_agent_*` ids plus human labels:
|
||||
`branch[idx]` for map branches, the node id for super-step nodes).
|
||||
Members can also rediscover peers at runtime via `agent__list_running`,
|
||||
which lists them in a dedicated `peers` section.
|
||||
- **Messaging only.** The team registry carries no lifecycle semantics:
|
||||
peers are not collectible, do not count against `max_concurrent_agents`,
|
||||
and outputs still flow exclusively through `collect_into` / state
|
||||
reducers. Once a member finishes, sending to it returns an error -- its
|
||||
results travel through the graph's collected outputs, not its inbox.
|
||||
- **The registry dies with the fan-out.** If the node is done, so is the
|
||||
team.
|
||||
|
||||
Upward fan-in needs no flag: every branch already shares the graph agent's
|
||||
own inbox, so children can `agent__send_message --id parent` at any time
|
||||
and a downstream `llm` node can drain those findings with
|
||||
`agent__check_inbox`.
|
||||
|
||||
**When to use it:** research or implementation lanes where one branch's
|
||||
discovery should redirect a sibling's work mid-flight. Leave it off for
|
||||
independent-verdict lanes (e.g. parallel reviewers), where cross-talk
|
||||
invites anchoring bias.
|
||||
|
||||
## Reducers
|
||||
|
||||
When two or more parallel branches write to the same state key in the
|
||||
|
||||
Reference in new issue
Block a user