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
|
[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.
|
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
|
## Runaway Safeguards
|
||||||
|
|
||||||
The spawning system includes built-in safeguards to prevent runaway agent chains:
|
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)
|
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
|
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
|
# (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
|
global_tools: # global tools available to nodes
|
||||||
- web_search_coyote.sh
|
- web_search_coyote.sh
|
||||||
mcp_servers: # MCP servers available to nodes
|
mcp_servers: # MCP servers available to nodes
|
||||||
@@ -132,9 +136,17 @@ nodes:
|
|||||||
see a variable inside prompts, seed its value into state (typically via
|
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
|
a setup script that reads the env var and writes it into state) so
|
||||||
`{{name}}` resolves.
|
`{{name}}` resolves.
|
||||||
- **`can_spawn_agents` is derived, not declared.** A graph agent can spawn
|
- **`can_spawn_agents` is declared, or derived when omitted.** When the key
|
||||||
child agents iff its graph contains at least one `agent` node. You don't
|
is absent, a graph agent can spawn dynamic child agents iff its graph
|
||||||
set a flag. The `agent` node's presence *is* the declaration.
|
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
|
- **`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,
|
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=...)`.
|
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
|
agent: deep-researcher # name of an existing Coyote agent
|
||||||
prompt: "Research {{topic}}" # interpolated against state
|
prompt: "Research {{topic}}" # interpolated against state
|
||||||
timeout: 600 # optional, in seconds (default 300)
|
timeout: 600 # optional, in seconds (default 300)
|
||||||
|
teammates: false # optional; peer messaging with concurrent siblings (see below)
|
||||||
state_updates:
|
state_updates:
|
||||||
findings: "{{output}}"
|
findings: "{{output}}"
|
||||||
output_schema: { ... } # optional, see "Structured Output" below
|
output_schema: { ... } # optional, see "Structured Output" below
|
||||||
@@ -244,6 +257,11 @@ research_topic:
|
|||||||
whole graph fails (no built-in fallback path on agent nodes).
|
whole graph fails (no built-in fallback path on agent nodes).
|
||||||
- **`state_updates`:** Map of `state_key: "{{template}}"`. The child agent's
|
- **`state_updates`:** Map of `state_key: "{{template}}"`. The child agent's
|
||||||
final text is available inside this map as `{{output}}`.
|
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**
|
Outputs are collected into `research_results` **in input order**
|
||||||
regardless of which sub-branch finished first.
|
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
|
## Reducers
|
||||||
|
|
||||||
When two or more parallel branches write to the same state key in the
|
When two or more parallel branches write to the same state key in the
|
||||||
|
|||||||
Reference in new issue
Block a user