Summary
Direct (non-delegated) Agent invocations run with the global config.agent.max_tool_iterations (default 10) instead of the agent definition's effective_max_iterations(). Tools/research agents that legitimately need more than 10 model calls get paused mid-task at the cap and return incomplete output — which then fails downstream (e.g. an output_parser schema validation), so the whole operation fails.
Problem
Agent::from_config_for_agent(...) → build_session_agent_inner stamps .config(config.agent.clone()), whose max_tool_iterations is the global user-config default (10). The per-agent AgentDefinition::effective_max_iterations() (which honors agent.toml's iteration_policy = "extended" → 50) is applied only on the sub-agent-runner delegate path — not on the direct-invocation call sites. So any agent invoked directly is silently capped at 10 regardless of its declared budget.
Three direct-invocation call sites, same root cause:
| Call site |
Agent |
Status |
flows_build (src/openhuman/flows/ops.rs) |
workflow_builder |
✅ Fixed in #4865 (B31) via a scoped apply_builder_iteration_cap override |
flows_discover (src/openhuman/flows/ops.rs:3182) |
flow_discovery (Flow Scout) |
❌ still global 10 (intended 12) — LOW impact, read-only |
Agent nodes at runtime (src/openhuman/tinyflows/caps.rs:~592, OpenHumanAgentRunner → Agent::from_config_for_agent + run_single) |
any flow agent_ref (e.g. tools_agent) |
❌ still global 10 — HIGH impact: breaks actual flow runs |
The caps.rs doc comment (≈L592–596) even asserts the agent node "gains its curated … max_iterations" — but the code stamps the global 10, so the doc and behavior disagree.
Impact (HIGH case): a flow agent node backed by a tools/research agent cannot complete a multi-step task (multiple web searches + a compile step). It hits model-call cap reached — completed=10 cap=10, is paused, returns incomplete non-JSON text, and any output_parser/response_format requirement then fails the node → the run fails.
Steps to reproduce
- Build a flow:
trigger → agent (agent_ref: "tools_agent", a web-search/research prompt, output_parser requiring a field e.g. newsletter_body) → tool_call (post the field somewhere).
- Run it.
- Observe the run fail. Core logs show:
routing chat turn through tinyagents harness max_iterations=10 tools=268
model-call cap reached — requesting graceful pause completed=10 cap=10
agent_runner: structured output requested but the harness turn did not parse as JSON — falling back to the {text} shape
engine node failed after retries node=<agent node>
flows_run: run failed ... output_parser: value failed schema validation after auto-fix: $: missing required property `<field>`
Environment: desktop dev build, current main (post-#4865), macOS.
Solution (optional)
Apply the agent definition's effective_max_iterations() for all direct invocations rather than patching each call site. Preferred: make Agent::from_config_for_agent (or build_session_agent_inner) resolve the cap from the named definition when one exists, falling back to config.agent.max_tool_iterations otherwise — this subsumes the #4865 scoped override and closes the flows_discover + agent-node-runtime gaps in one place. Guard against unexpectedly raising other agents' budgets (verify each definition's declared cap before/after). The scoped apply_builder_iteration_cap in flows_build can then be removed in favor of the shared path.
Acceptance criteria
Related
Summary
Direct (non-delegated)
Agentinvocations run with the globalconfig.agent.max_tool_iterations(default 10) instead of the agent definition'seffective_max_iterations(). Tools/research agents that legitimately need more than 10 model calls get paused mid-task at the cap and return incomplete output — which then fails downstream (e.g. anoutput_parserschema validation), so the whole operation fails.Problem
Agent::from_config_for_agent(...)→build_session_agent_innerstamps.config(config.agent.clone()), whosemax_tool_iterationsis the global user-config default (10). The per-agentAgentDefinition::effective_max_iterations()(which honorsagent.toml'siteration_policy = "extended"→ 50) is applied only on the sub-agent-runner delegate path — not on the direct-invocation call sites. So any agent invoked directly is silently capped at 10 regardless of its declared budget.Three direct-invocation call sites, same root cause:
flows_build(src/openhuman/flows/ops.rs)workflow_builderapply_builder_iteration_capoverrideflows_discover(src/openhuman/flows/ops.rs:3182)flow_discovery(Flow Scout)src/openhuman/tinyflows/caps.rs:~592,OpenHumanAgentRunner→Agent::from_config_for_agent+run_single)agent_ref(e.g.tools_agent)The
caps.rsdoc comment (≈L592–596) even asserts the agent node "gains its curated …max_iterations" — but the code stamps the global 10, so the doc and behavior disagree.Impact (HIGH case): a flow
agentnode backed by a tools/research agent cannot complete a multi-step task (multiple web searches + a compile step). It hitsmodel-call cap reached — completed=10 cap=10, is paused, returns incomplete non-JSON text, and anyoutput_parser/response_formatrequirement then fails the node → the run fails.Steps to reproduce
trigger → agent (agent_ref: "tools_agent", a web-search/research prompt, output_parser requiring a field e.g.newsletter_body) → tool_call (post the field somewhere).Environment: desktop dev build, current
main(post-#4865), macOS.Solution (optional)
Apply the agent definition's
effective_max_iterations()for all direct invocations rather than patching each call site. Preferred: makeAgent::from_config_for_agent(orbuild_session_agent_inner) resolve the cap from the named definition when one exists, falling back toconfig.agent.max_tool_iterationsotherwise — this subsumes the #4865 scoped override and closes theflows_discover+ agent-node-runtime gaps in one place. Guard against unexpectedly raising other agents' budgets (verify each definition's declared cap before/after). The scopedapply_builder_iteration_capinflows_buildcan then be removed in favor of the shared path.Acceptance criteria
tools_agent-backed flowagentnode completes a multi-model-call task without hitting a 10-iteration cap; the run succeeds and downstreamoutput_parservalidation passes.effective_max_iterations()(builder,flows_discover, and agent-nodes-at-runtime), ideally via one shared resolution point.extendedpolicy keep their intended caps (audited before/after).flows_discoverresolve to the definition cap, not the global 10.Related
workflow_buildervia a scoped override (B31); this issue is the systemic generalization.flows_discoverinstance and recommended a systemic fix infrom_config_for_agent.src/openhuman/flows/ops.rs(apply_builder_iteration_cap,flows_discover),src/openhuman/tinyflows/caps.rs(OpenHumanAgentRunner),src/openhuman/agent/harness/definition.rs(effective_max_iterations).