Skip to content

Direct agent invocations ignore the agent definition's iteration cap and use the global default of 10 #4868

Description

@graycyrus

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, OpenHumanAgentRunnerAgent::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

  1. 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).
  2. Run it.
  3. 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

  • Repro gone — a tools_agent-backed flow agent node completes a multi-model-call task without hitting a 10-iteration cap; the run succeeds and downstream output_parser validation passes.
  • All three call sites honor the definition's effective_max_iterations() (builder, flows_discover, and agent-nodes-at-runtime), ideally via one shared resolution point.
  • No unintended budget changes — agents without an extended policy keep their intended caps (audited before/after).
  • Regression safety — unit coverage asserting the runtime agent-node path and flows_discover resolve to the definition cap, not the global 10.
  • Diff coverage ≥ 80% on the fix PR.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions