docs: proposal — loops and iteration in Open Agent Spec#93
Conversation
Adds docs/proposals/loops.md. Frames "add loops to OA" as three distinct features (tool-calling loop / bounded map / conditional-until-good) and draws the boundary by determinism of termination: - A. tool-calling loop — already runs, bounded; recommend surfacing the existing cap as a declared max_iterations field. - B. bounded map / fan-out — compatible if bounded (ordered results, fail-closed, validated ceiling); gets its own schema proposal. - C. conditional / until-good — refused in-spec; belongs to the orchestrator (BCE) that calls OA specs each pass. Bright line: OA iterates over data it can see before the first token; it never loops on a condition only knowable at runtime. Consistent with the markdown-interop boundary, no-orchestration, and depends_on acyclicity. Status: Proposed — docs-only; any schema change is a separate follow-up.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Incorporates maintainer review on the loops proposal: - Replace the private-constant reference with normative language (the tool-call loop and its mandatory iteration cap are §12.3; reference implementation uses 10). Keeps the doc runtime-agnostic. - Recommendation A now flags the two schema-PR decisions: field placement (tool loops are per-task, intelligence.config is spec-global) and naming (prefer max_tool_iterations — examples/multi-agent/loop.py already uses max_iterations for an orchestration loop). - B: add a paragraph clarifying bounded map is a NEW construct (a single DAG node iterating over data), not a loosening of §7.3's parallel-fan-out refusal, which is scoped to depends_on. Add a cost-vs-count note: the ceiling bounds iteration count, not per-element tool-loop cost. - C: tie to §7.3's existing permanent exclusions (conditional execution, loop control, retry semantics) and point at examples/multi-agent/loop.py as the in-repo orchestrator-loops pattern. - Refuse list: add retry-with-backoff and run-until-confidence explicitly.
- A: name the working field (max_tool_iterations) once inline for scan-ability, naming still formally deferred to the schema PR. - Future: note parallel fan-out would still be capped by the same fan-out ceiling and must preserve input order — preempts "parallel = unbounded". - How we manage it: record two on-acceptance follow-ups — a README / AGENTS.md pointer when this moves to Accepted, and npm-runtime parity + a conformance case in the schema PR for A. Both are later PRs.
aswhitehouse
left a comment
There was a problem hiding this comment.
Strong proposal — same quality bar as the markdown-interop write-up, and the bright line is the right one:
OA iterates over data it can see before the first token. It never loops on a condition it can only evaluate at runtime.
A / B / C sorting by determinism of termination is teachable and defensible. Naming the tool-call loop OA already has (A), fencing bounded map as its own construct rather than loosening depends_on (B), and refusing until-good with a pointer at examples/multi-agent/loop.py (C) all land correctly against every boundary we've drawn.
Agree, ship as Proposed
- Docs-only, status Proposed, schema deferred — right shape for a direction-setting PR.
max_tool_iterationsnaming (vs baremax_iterations) is a good catch given the orchestration loop inloop.py.- "Bounding count is not bounding cost" is an important honesty note; keep that when B is designed.
- Fail-closed default for map failures matches OA's posture.
- C joining "no orchestration" / "no skills task type" as a cited boundary is exactly how we should manage it.
Tighten before / as Accepted
1. Clarify "before the first token" for B when the array is upstream-produced.
If the map input arrives via depends_on merge from an LLM task, its length is not known at chain entry — only after that dep completes. The fan-out ceiling is still enforceable before the mapped task spends tokens, but it is not a §7.1 stage-1–5 static error for the whole chain. Spell that out so nobody reads "statically detectable" as "knowable from the YAML alone". Suggested gloss: ceiling is validated against the resolved input at the start of the mapped task (after merge), before any per-element invocation.
2. A's "npm parity" obligation is larger than a field.
The npm runtime still refuses tools: (UNSUPPORTED_FEATURE). A schema PR that adds max_tool_iterations and requires npm parity either needs to land tools on npm first, or to state that A is capability-scoped (tools) — declare it, enforce it where tools exist, and keep the honesty rule for runtimes that don't. Don't let the follow-up paint us into "field exists in schema, only Python honours it".
3. B canary to watch.
The slope from bounded map → filter/map → map-reduce → conditional fan-out is the same slope depends_on had toward orchestration. When the B design PR arrives, the hard wall should stay: no predicates on which elements run, no early-exit based on element output, no reduce-as-control-flow. Collect-partial as explicit opt-in (as you have) is the right default posture.
4. Tiny: on Proposed → Accepted, yes — README blurb + AGENTS.md pointer, same as markdown-interop. Not this PR.
No blocking changes for a docs-only Proposed document. Happy to mark Accepted once you've weighed (1) and (2), or leave them as notes for the follow-up PRs — either works.
What changed
Adds
docs/proposals/loops.md— a position doc on whether/how OA should incorporate "loops", following the same decide-the-boundary format asmarkdown-interop.md. Docs-only; no schema or runtime change. Opening as a draft to get the direction agreed before any code.The core argument
"Add loops to OA" is really three different features wearing one word, and they land very differently against OA's boundaries (no orchestration, no conditionals,
depends_onacyclicity):_MAX_TOOL_ITERATIONS) — just surface itBright line proposed: OA iterates over data it can see before the first token; it never loops on a condition it can only evaluate at runtime.
That line is drawn on determinism of termination, and it stays consistent with the deterministic-pipeline framing already in the 1.6 spec (§7 / §7.3 pre-flight checks) and the markdown-interop precedent.
Recommendations in the doc
intelligence.config.max_iterations. Names existing behaviour; no new semantics.Tper array element, ordered results, fail-closed by default, with a validated fan-out ceiling enforced as a pre-flight error (§7). Ships as its own proposal + schema PR if this direction is accepted.For discussion
Type of change
Checklist