docs(graph): timeout: 0 disables the wall-clock bound
Documents the new zero-means-unbounded rule on all five timeout fields (settings.timeout, agent, script, llm, rag), the validator warning that flags an explicit 0, how bounds compose outward-in across nested graph agents, and what interrupts an unbounded step.
1 file changed
+28
-8
+28
-8
@@ -95,7 +95,7 @@ settings:
|
|||||||
max_loop_iterations: 100 # PER-NODE visit cap; default 100 (see below)
|
max_loop_iterations: 100 # PER-NODE visit cap; default 100 (see below)
|
||||||
log_state_snapshots: true # log state JSON before each node executes
|
log_state_snapshots: true # log state JSON before each node executes
|
||||||
validate_before_run: true # run the graph validator on startup
|
validate_before_run: true # run the graph validator on startup
|
||||||
timeout: 600 # optional overall timeout in seconds
|
timeout: 600 # optional overall timeout in seconds; 0 = no bound
|
||||||
max_concurrency: 8 # cap on simultaneously running parallel branches; default 8
|
max_concurrency: 8 # cap on simultaneously running parallel branches; default 8
|
||||||
|
|
||||||
reducers: # optional; declares how parallel branches merge writes
|
reducers: # optional; declares how parallel branches merge writes
|
||||||
@@ -159,7 +159,21 @@ nodes:
|
|||||||
`fallback`s, so any cleanup/reporting nodes are skipped. Prefer per-node
|
`fallback`s, so any cleanup/reporting nodes are skipped. Prefer per-node
|
||||||
`timeout`s on `llm` nodes (which *do* route via `fallback`) as the
|
`timeout`s on `llm` nodes (which *do* route via `fallback`) as the
|
||||||
operative bound, and treat the graph-level `timeout` as a generous
|
operative bound, and treat the graph-level `timeout` as a generous
|
||||||
backstop.
|
backstop. `0` disables the bound entirely (equivalent to unset;
|
||||||
|
`--validate` flags the explicit `0` as an intentional choice) — for graphs
|
||||||
|
that must run until they complete, e.g. an end-to-end implementation run;
|
||||||
|
pair it with a sane `max_loop_iterations`. **Bounds compose outward-in:**
|
||||||
|
if this graph is run by another graph's `agent` node, that node's
|
||||||
|
`timeout` (default 300) still applies and will drop this graph regardless
|
||||||
|
of its own settings — set `timeout: 0` there too. Conversely a parent's
|
||||||
|
`timeout: 0` does not lift a child's non-zero `settings.timeout`; the
|
||||||
|
child's own executor enforces it. A root graph run directly is bounded
|
||||||
|
only by its own `settings.timeout`. An unbounded run ends only on
|
||||||
|
completion, error, or an enclosing bound; Ctrl-C is observed between
|
||||||
|
super-steps, and an in-flight agent step only stops when its own loop
|
||||||
|
observes the interrupt (a script step is killed only when its future is
|
||||||
|
dropped). The 300s agent default was a de-facto safety net for a wedged
|
||||||
|
child — `timeout: 0` is the explicit opt-out of that net.
|
||||||
- **`initial_state`:** A JSON-compatible object. Values are seeded into
|
- **`initial_state`:** A JSON-compatible object. Values are seeded into
|
||||||
state before any node runs and are referenced from any node via `{{key}}`
|
state before any node runs and are referenced from any node via `{{key}}`
|
||||||
templates.
|
templates.
|
||||||
@@ -243,7 +257,7 @@ research_topic:
|
|||||||
type: agent
|
type: agent
|
||||||
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, seconds; default 300, 0 = no bound
|
||||||
inputs: # optional; only when the child is a GRAPH agent
|
inputs: # optional; only when the child is a GRAPH agent
|
||||||
max_parallel: "{{inner_width}}" # seeds the child's initial_state (see below)
|
max_parallel: "{{inner_width}}" # seeds the child's initial_state (see below)
|
||||||
teammates: false # optional; peer messaging with concurrent siblings (see below)
|
teammates: false # optional; peer messaging with concurrent siblings (see below)
|
||||||
@@ -258,7 +272,10 @@ research_topic:
|
|||||||
- **`prompt`:** The user message sent to the child agent. Templated against
|
- **`prompt`:** The user message sent to the child agent. Templated against
|
||||||
the current graph state.
|
the current graph state.
|
||||||
- **`timeout`:** Hard wall-clock cap. If the child agent exceeds it, the
|
- **`timeout`:** Hard wall-clock cap. If the child agent exceeds it, the
|
||||||
whole graph fails (no built-in fallback path on agent nodes).
|
whole graph fails (no built-in fallback path on agent nodes). `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.
|
||||||
- **`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}}`.
|
||||||
- **`inputs`:** Map of `child_state_key: "{{template}}"`. Each value is
|
- **`inputs`:** Map of `child_state_key: "{{template}}"`. Each value is
|
||||||
@@ -396,7 +413,7 @@ route_after_parse:
|
|||||||
id: route_after_parse
|
id: route_after_parse
|
||||||
type: script
|
type: script
|
||||||
script: scripts/route_after_parse.py
|
script: scripts/route_after_parse.py
|
||||||
timeout: 30 # seconds, default 30
|
timeout: 30 # seconds; default 30, 0 = no bound
|
||||||
fallback: handle_error # optional: where to route on script failure
|
fallback: handle_error # optional: where to route on script failure
|
||||||
state_updates: # applied after stdout merge
|
state_updates: # applied after stdout merge
|
||||||
last_run: "{{some_value}}"
|
last_run: "{{some_value}}"
|
||||||
@@ -571,7 +588,7 @@ grade_research:
|
|||||||
state_updates:
|
state_updates:
|
||||||
grade: "{{output}}"
|
grade: "{{output}}"
|
||||||
output_schema: { ... } # optional, see "Structured Output" below
|
output_schema: { ... } # optional, see "Structured Output" below
|
||||||
timeout: 120 # optional; node wall-clock cap in seconds (unset = no timeout)
|
timeout: 120 # optional; node wall-clock cap in seconds (unset or 0 = no timeout)
|
||||||
next: synthesize
|
next: synthesize
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -639,6 +656,7 @@ A node-level `timeout` counts as a failure like any other: it routes via
|
|||||||
per-node `timeout`s the preferred way to bound long-running `llm` nodes.
|
per-node `timeout`s the preferred way to bound long-running `llm` nodes.
|
||||||
Unlike the graph-level `settings.timeout`, a node timeout still gives the
|
Unlike the graph-level `settings.timeout`, a node timeout still gives the
|
||||||
graph a chance to recover or report through its `fallback` route.
|
graph a chance to recover or report through its `fallback` route.
|
||||||
|
`timeout: 0` (or unset) disables the bound.
|
||||||
|
|
||||||
### Retries (`max_attempts`)
|
### Retries (`max_attempts`)
|
||||||
|
|
||||||
@@ -712,7 +730,7 @@ research_context:
|
|||||||
- https://example.com/spec
|
- https://example.com/spec
|
||||||
query: "{{initial_prompt}}" # templated; defaults to "{{initial_prompt}}"
|
query: "{{initial_prompt}}" # templated; defaults to "{{initial_prompt}}"
|
||||||
top_k: 5 # optional; default = the knowledge base's own top_k
|
top_k: 5 # optional; default = the knowledge base's own top_k
|
||||||
timeout: 120 # optional; retrieval timeout in seconds (default 120)
|
timeout: 120 # optional; retrieval timeout in seconds (default 120; 0 = no bound)
|
||||||
state_updates: # required in practice (see below)
|
state_updates: # required in practice (see below)
|
||||||
rag_context: "{{output.context}}"
|
rag_context: "{{output.context}}"
|
||||||
rag_sources: "{{output.sources}}"
|
rag_sources: "{{output.sources}}"
|
||||||
@@ -735,7 +753,7 @@ answer:
|
|||||||
query an upstream `llm` node produced.
|
query an upstream `llm` node produced.
|
||||||
- **`top_k`:** Number of chunks to retrieve. Defaults to the knowledge
|
- **`top_k`:** Number of chunks to retrieve. Defaults to the knowledge
|
||||||
base's own configured `top_k`.
|
base's own configured `top_k`.
|
||||||
- **`timeout`:** Retrieval timeout in seconds. Default 120.
|
- **`timeout`:** Retrieval timeout in seconds. Default 120; `0` = no bound.
|
||||||
- **`state_updates`:** Where the result goes. A `rag` node with no
|
- **`state_updates`:** Where the result goes. A `rag` node with no
|
||||||
`state_updates` discards its result (the validator warns).
|
`state_updates` discards its result (the validator warns).
|
||||||
|
|
||||||
@@ -1060,6 +1078,8 @@ script node upstream.
|
|||||||
failed item). One failing item fails the map.
|
failed item). One failing item fails the map.
|
||||||
- **Per-item timeouts.** `settings.timeout` applies to the whole
|
- **Per-item timeouts.** `settings.timeout` applies to the whole
|
||||||
super-step; node-level `timeout`s (llm/agent/script) apply per step.
|
super-step; node-level `timeout`s (llm/agent/script) apply per step.
|
||||||
|
`timeout: 0` on a branch's `agent`/`script` nodes is the explicit opt-out
|
||||||
|
for long-running chains; the item then runs until its terminal node.
|
||||||
- **Shared state between items mid-run.** Items communicate via
|
- **Shared state between items mid-run.** Items communicate via
|
||||||
[teammate messaging](#teammate-messaging-in-fan-outs); results merge at
|
[teammate messaging](#teammate-messaging-in-fan-outs); results merge at
|
||||||
collect.
|
collect.
|
||||||
|
|||||||
Reference in new issue
Block a user