docs: document agent fallback and max_attempts field for parity with LLM nodes

Dark-Alex-17 committed 2026-09-12 12:40:33 -06:00
1 parent a09d21a1c6
commit 7df7d27a6f
1 file changed
+39 -9
+39 -9
@@ -314,6 +314,8 @@ research_topic:
agent: deep-researcher # name of an existing Coyote agent
prompt: "Research {{topic}}" # interpolated against state
timeout: 600 # optional, seconds; default 300, 0 = no bound
max_attempts: 2 # optional; retry transient child failures (default 1)
fallback: report_unavailable # optional; route here when the child ultimately fails
inputs: # optional; only when the child is a GRAPH agent
max_parallel: "{{inner_width}}" # seeds the child's initial_state (see below)
teammates: false # optional; peer messaging with concurrent siblings (see below)
@@ -327,11 +329,30 @@ research_topic:
`<coyote-config-dir>/agents/`.
- **`prompt`:** The user message sent to the child agent. Templated against
the current graph state.
- **`timeout`:** Hard wall-clock cap. If the child agent exceeds it, the
whole graph fails (no built-in fallback path on agent nodes). `0`
- **`timeout`:** Hard wall-clock cap per attempt. A timeout counts as a
transient failure: remaining `max_attempts` retries run, each with a fresh
budget; the final failure routes via `fallback` when declared, otherwise
the whole graph fails at this node. `0`
disables the bound; the child runs until it returns. Required on the
calling node to let a child graph's own `timeout: 0` take effect; the
child's non-zero `settings.timeout` still applies.
- **`max_attempts`:** Transient-error retries with the same matcher and
semantics as `llm` nodes (see [Retries](#retries-max_attempts)). Each retry
re-spawns the child agent from scratch with the same prompt and a fresh
`timeout` budget; a concurrent-teammate identity (inbox + roster) is
preserved across attempts. Default `1` (no retries). Only set this on
children that are safe to re-run from scratch; e.g. read-only reviewers,
researchers, report writers. Leave it at `1` for side-effectful children
(agents that write code or deploy things); a child that authors files
(e.g. a probe lane writing test artifacts) is mildly side-effectful,
meaning a failed first attempt may leave partial artifacts behind.
- **`fallback`:** Failure route with the same contract as `llm` nodes: on the
final failure (retries exhausted, hard error, or structured-output
extraction failure) the node writes `Agent node failed: <error>` as
`{{output}}`, applies `state_updates`, and routes to `fallback` instead of
failing the graph. Without `fallback` the error propagates and the graph
fails at this node. Inside a map branch the fallback target must be
branch-local.
- **`state_updates`:** Map of `state_key: "{{template}}"`. The child agent's
final text is available inside this map as `{{output}}`.
- **`inputs`:** Map of `child_state_key: "{{template}}"`. Each value is
@@ -720,10 +741,19 @@ graph a chance to recover or report through its `fallback` route.
`max_attempts` retries the LLM call **only on transient errors**. The
failure message containing one of: `timed out`, `rate limit`, `429`,
`Connection reset`, `Connection refused`, or `produced no output`. Any
`Connection reset`, `Connection refused`, `produced no output`,
`broken pipe`, `connection error`, or `error sending request`. Any
other error fails immediately without consuming further attempts. The
default is `1` (no retries).
`agent` nodes support the same key with the same transient matcher: the
child agent is re-spawned **from scratch** on a transient failure, each
attempt with a fresh `timeout` budget (a per-attempt timeout counts as
transient). A retried teammate keeps the same identity, inbox, and roster
across attempts. See [agent](#agent) for when re-running a child is safe;
structured-output extraction failures are never retried on either node
type (they route via `fallback` instead).
### Turn cap (`max_iterations`)
`max_iterations` caps the number of model-call turns in one execution of the
@@ -1191,7 +1221,7 @@ Rules for the loop:
- Item errors are fail-fast and carry the chain position:
`map node 'review_each_file': sub-branch [2] failed at node 'check_review' (step 2): ...`.
- A `script` step that fails consults its `fallback:` (a branch-local node)
before failing the item, exactly like a main-flow script. An `llm` step's
before failing the item, exactly like a main-flow script. An `llm` or `agent` step's
`max_attempts` and `fallback:` work per item the same way.
### Empty `over`
@@ -1318,7 +1348,7 @@ Nodes route via three mechanisms in priority order:
| Node type | Needs `next`? | Supports fan-out (`next: [...]`)? |
|-------------|---------------------------------------------------------------------------------------------------|-----------------------------------|
| `agent` | **Yes** - `next` is required (unless the agent node is unreachable). Error at runtime if missing. | Yes |
| `agent` | **Yes** - `next` is required (unless the agent node is unreachable). Error at runtime if missing. Failures without `fallback` halt the graph. | Yes (success path; failure with `fallback` routes to single target) |
| `script` | Either `_next` from script output OR static `next` (or `fallback` on failure). Error if neither. | Yes (when `_next` is not emitted) |
| `approval` | No - routing is via `routes` and `on_other`. `next` is ignored. | No - forbidden by validator |
| `input` | **Yes** - `next` is the success route. | No - forbidden by validator |
@@ -1336,14 +1366,14 @@ an error. Fan-out is never allowed inside a branch. See
| Node type | Success | Failure with `fallback` | Failure without `fallback` |
|----------------------------|-----------------------------|-------------------------|-----------------------------------------------------------|
| `llm` | Routes via `next` | Routes via `fallback` | **Graph fails at this node** (use `fallback:` to recover) |
| `llm` / `agent` | Routes via `next` | Routes via `fallback` | **Graph fails at this node** (use `fallback:` to recover) |
| `script` | Routes via `next` | Routes via `fallback` | Routes via `next`; `{{output}}` holds the error |
| `agent` / `input` | Routes via `next` | n/a (no `fallback`) | Graph fails at this node |
| `input` | Routes via `next` | n/a (no `fallback`) | Graph fails at this node |
| `rag` / `map` / `approval` | Routes via configured edges | n/a | Graph fails at this node |
**Note:** LLM node failures halt the graph with
**Note:** LLM and agent node failures without a `fallback` halt the graph with
a clear error message. This prevents downstream nodes from running against
garbage state when an upstream LLM call fails (HTTP 4xx/5xx, timeout,
garbage state when an upstream call fails (HTTP 4xx/5xx, timeout,
structured-extraction error, etc.).
---