Skip to content

fix(agent): resolve iteration cap from the agent definition, not the global default (#4868)#4870

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
graycyrus:fix/agent-iteration-cap-systemic
Jul 15, 2026
Merged

fix(agent): resolve iteration cap from the agent definition, not the global default (#4868)#4870
senamakel merged 1 commit into
tinyhumansai:mainfrom
graycyrus:fix/agent-iteration-cap-systemic

Conversation

@graycyrus

@graycyrus graycyrus commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Direct-invocation agent builds — flows_build, flows_discover, tinyflows
agent nodes, cron, subconscious, skill_runtime, task_dispatcher — all
funnel through Agent::from_config_for_agentbuild_session_agent_inner,
which unconditionally stamped the global config.agent.max_tool_iterations
(default 10)
onto every session agent, ignoring the per-agent
AgentDefinition.max_iterations / iteration_policy declared in each
agent.toml. Only the sub-agent-runner path (delegated sub-agents spawned
via spawn_subagent) applied effective_max_iterations() correctly — every
direct invocation silently got 10, regardless of what the agent's own
agent.toml declared (e.g. tools_agent — the repro agent from the issue —
declares iteration_policy = "extended" for an effective cap of 50, but got
10).

Closes #4868

The one-place fix

src/openhuman/agent/harness/session/builder/factory.rs
build_session_agent_inner: before the builder chain, clone config.agent
and, when a target_def is present, overwrite max_tool_iterations with
target_def.effective_max_iterations(). No definition → unchanged global
fallback (10). This is the single shared resolution point that closes #4868
for every direct-invocation call site at once.

Retiring the scoped apply_builder_iteration_cap

flows/ops.rs had a previous scoped fix (apply_builder_iteration_cap,
issue B31) that manually resolved workflow_builder's effective cap before
calling Agent::from_config_for_agent. The shared fix makes this redundant
deleted the function and its call site; flows_build now just passes
config straight through and gets the same 50.

The 4 reconciled callers

Four call sites pre-set max_tool_iterations before calling
from_config_for_agent/from_config; the shared fix would otherwise
silently clobber their override. Each is reconciled:

  1. cron/scheduler.rs — removed the manual
    effective.agent.max_tool_iterations = def.max_iterations; line. This
    also fixes a latent bug: it used the raw max_iterations instead of
    effective_max_iterations(), so extended-policy cron agents (e.g.
    tools_agent) got shortchanged to 10 instead of 50 even under the old
    scoped behavior.

  2. skill_runtime/run_machinery.rs — the 200-iteration
    WORKFLOW_RUN_MAX_ITERATIONS override moved to post-construction via
    a new Agent::set_max_tool_iterations(cap) setter
    (session/runtime.rs), since the shared fix would otherwise stamp
    orchestrator's definition cap (15) over the intentionally larger
    workflow-run budget. Verified still resolves to 200.

  3. agent/task_dispatcher/executor.rs — same pattern, TASK_RUN_MAX_ITERATIONS
    (200) moved to post-construction. Verified still resolves to 200.

  4. subconscious/session.rs + subconscious/profiles/memory.rs
    both hardcode a mode-specific 15 (Simple) / 30 (Aggressive/EventDriven)
    cap before construction. Both moved to post-construction re-application
    of the mode's cap via set_max_tool_iterations. This turned out to be
    necessary, not just a nice-to-have: the plan's original assumption
    was that both callers build via the subconscious definition (effective
    cap 30, so only Simple mode's 15 would've been silently widened to 30 —
    a minor issue). In fact profiles/memory.rs builds via Agent::from_config,
    which targets the orchestrator definition (effective cap 15, not
    30) — so without the post-construction fix, Aggressive/EventDriven
    mode's tick would have silently dropped from 30 iterations to 15, a
    real regression the plan didn't anticipate for this specific call site.
    Both are now fully decoupled from whatever the builder resolves.

Timeout scaling for extended-cap agent nodes

tinyflows/caps.rs's agent-node runtime (run_via_harness) now scales its
wall-clock timeout for agents whose effective cap exceeds 10, via a new pure
helper scale_timeout_for_iteration_cap(base_timeout_secs, effective_cap)
floor of effective_cap * 12s, capped at the existing 600s ceiling. A
50-iteration agent node (e.g. code_executor, tools_agent) can legitimately
run past the previous 240s default and would otherwise be killed by timeout
before exhausting its own declared budget.

Full before/after cap audit (re-verified against every agent.toml)

Re-derived directly from all 39 built-in agent.toml files in this branch
(not just carried over from the plan) — effective_max_iterations() =
max_iterations (strict) or max(max_iterations, 50) (extended). Matches
the plan's audit exactly, no discrepancies.
Pinned by a new snapshot test:
all_builtin_agent_definitions_have_expected_effective_max_iterations
(src/openhuman/agent/harness/definition_tests.rs), which is exhaustive
over every built-in id — a future agent.toml edit that changes an
effective cap (or a new agent landing without a reviewed cap) fails this
test instead of silently changing runtime behavior.

Agents whose cap INCREASES (extended policy, or high declared max_iterations)

Agent max_iterations policy effective Before After
orchestrator 15 strict 15 10 15
code_executor 10 extended 50 10 50
context_scout 8 extended 50 10 50
integrations_agent 10 extended 50 10 50
mcp_agent 10 extended 50 10 50
mcp_setup 12 extended 50 10 50
planner 8 extended 50 10 50
researcher 10 extended 50 10 50
skill_creator 10 extended 50 10 50
task_manager_agent 8 extended 50 10 50
tools_agent 10 extended 50 10 50
flow_discovery 12 extended 50 10 50
workflow_builder 12 extended 50 10 50 (already 50 via the now-retired scoped fix)
skill_executor 15 extended 50 10 50
tinyplace_agent 8 extended 50 10 50
subconscious 30 strict 30 10 (or 15/30 via the caller override, see above) 30 (mode-specific 15/30 preserved via post-construction override)

All side-effect tools on every extended-policy agent are approval-gated and
cost-budgeted independent of iteration count — the fix only restores the
budget each agent's agent.toml was authored to have.

Agents whose cap DECREASES (declared max_iterations < old global default of 10)

Agent max_iterations policy effective Before After
agent_memory 6 strict 6 10 6
account_admin_agent 8 strict 8 10 8
archivist 3 strict 3 10 3
critic 5 strict 5 10 5
crypto_agent 8 strict 8 10 8
desktop_control_agent 8 strict 8 10 8
goals_agent 5 strict 5 10 5
help 6 strict 6 10 6
image_agent 8 strict 8 10 8
markets_agent 8 strict 8 10 8
morning_briefing 8 strict 8 10 8
profile_memory_agent 8 strict 8 10 8
scheduler_agent 8 strict 8 10 8
screen_awareness_agent 8 strict 8 10 8
settings_agent 8 strict 8 10 8
summarizer 1 strict 1 10 1 (explicitly single-shot by design)
tool_maker 2 strict 2 10 2
trigger_reactor 6 strict 6 10 6
trigger_triage 2 strict 2 10 2
video_agent 8 strict 8 10 8
vision_agent 6 strict 6 10 6

Every decrease aligns an agent with the budget its own author declared in
agent.toml — none was relying on the inflated global 10 as a floor.

Unchanged

Agent max_iterations policy effective Before After
presentation_agent 10 strict 10 10 10
skill_setup 10 strict 10 10 10

Tests

  • build_session_agent_applies_extended_policy_definition_cap /
    build_session_agent_applies_strict_cap_below_global_default /
    build_session_agent_falls_back_to_global_default_when_no_definition
    (session/builder/builder_tests.rs) — drive build_session_agent_inner
    directly (now pub(crate)) with a hand-picked target_def, independent
    of the global registry singleton's init-once state.
  • agent_node_runtime_resolves_to_the_definitions_effective_iteration_cap
    + scale_timeout_for_iteration_cap_* (tinyflows/caps.rs) — agent-node
    runtime path resolves to the definition cap, and the timeout scaling
    formula is unit tested in isolation.
  • flows_discover_applies_the_flow_discovery_definitions_effective_iteration_cap
    (flows/ops_tests.rs) — flows_discover resolves to 50, not 10.
  • flows_build_applies_the_builder_definitions_effective_iteration_cap
    (flows/ops_tests.rs) — updated for the retired
    apply_builder_iteration_cap; now asserts the shared fix alone
    produces 50 with no per-caller override.
  • all_builtin_agent_definitions_have_expected_effective_max_iterations
    (agent/harness/definition_tests.rs) — audit snapshot test,
    exhaustive over all 39 built-in agents, pinning every value in the
    tables above.
  • set_max_tool_iterations_overrides_the_builder_resolved_cap /
    set_max_tool_iterations_survives_after_definition_backed_construction
    (session/tests.rs) — the new setter wins over the definition-resolved
    cap, mirroring exactly what skill_runtime/task_dispatcher rely on.
  • build_agent_preserves_simple_modes_15_iteration_cap /
    build_agent_preserves_aggressive_modes_30_iteration_cap
    (subconscious/session.rs) — mode-specific cap survives the shared fix.
  • profiles/memory.rs's equivalent path (run_agent) isn't unit-testable
    without a live model call (it runs a real turn inline), so it's covered
    by the same building-block tests above (Agent::from_config +
    set_max_tool_iterations) rather than an end-to-end test — noted here
    for reviewer visibility rather than silently skipped.

Verification run (this branch)

  • GGML_NATIVE=OFF cargo check --manifest-path Cargo.toml — clean
  • GGML_NATIVE=OFF cargo check --manifest-path app/src-tauri/Cargo.toml — clean
  • cargo test --manifest-path Cargo.toml --lib openhuman::agent:: -- --test-threads=1
    — 965 passed, 1 failed. The 1 failure
    (turn_triggers_configured_memory_agent_before_parent_prompt) is a
    pre-existing flake, confirmed identical on upstream/main before this
    change (verified via git stash).
  • cargo test --manifest-path Cargo.toml --lib openhuman::flows:: -- --test-threads=1
    — 289 passed, 0 failed.
  • cargo fmt — clean.

Risk

  • Agents getting more iterations: safe — only iteration_policy = "extended" agents change, and that policy is a deliberate author choice;
    all side-effect tools stay approval- and cost-gated independent of
    iteration count.
  • Agents getting fewer iterations: safe — every decrease aligns an agent
    with its own declared max_iterations; nothing depended on the inflated
    global 10 as a minimum.
  • Sub-agent runner: untouched — it never calls from_config_for_agent /
    build_session_agent_inner, so there's no double-apply risk.
  • Pre-existing overrides: all 4 reconciled above; the subconscious
    discrepancy against the plan's assumption is called out explicitly rather
    than silently fixed.
  • Timeout kills: handled via scale_timeout_for_iteration_cap.

Test plan

  • cargo check (both crates) clean
  • cargo test --lib openhuman::agent:: (single-threaded) — only the
    pre-existing, branch-independent flake remains
  • cargo test --lib openhuman::flows:: (single-threaded) — all green
  • cargo fmt clean
  • Full before/after cap audit re-verified against every agent.toml in
    this branch and pinned by a snapshot test

Summary by CodeRabbit

  • Bug Fixes
    • Agent-specific iteration limits are now applied consistently across workflows, scheduled jobs, autonomous tasks, flow discovery, and long-running sessions.
    • Extended agent policies receive their intended larger iteration budgets.
    • Mode-specific subconscious iteration limits are preserved.
    • Workflow and agent-node timeouts now scale appropriately with higher iteration limits, up to a safe maximum.
    • Runtime overrides for iteration limits are now honored reliably.

…global default (tinyhumansai#4868)

Direct-invocation agent builds (flows_build, flows_discover, tinyflows agent
nodes, cron, subconscious, skill_runtime, task_dispatcher) all funnel through
`Agent::from_config_for_agent` -> `build_session_agent_inner`, which
unconditionally stamped the global `config.agent.max_tool_iterations`
(default 10) onto every session agent -- ignoring the per-agent
`AgentDefinition.max_iterations`/`iteration_policy` declared in each
`agent.toml`. Only the sub-agent-runner path (used for delegated sub-agents)
applied `effective_max_iterations()` correctly.

The fix is one shared resolution point: `build_session_agent_inner` now
clones `config.agent`, and when a `target_def` is present, overwrites
`max_tool_iterations` with `target_def.effective_max_iterations()` before
handing it to the builder. No definition -> unchanged global fallback.

Four callers pre-set `max_tool_iterations` before calling
`from_config_for_agent` and would otherwise have their override silently
clobbered by the new shared logic:
- `flows/ops.rs`: deleted the now-redundant `apply_builder_iteration_cap`
  scoped fix for `workflow_builder` -- the shared fix gives it the same 50.
- `cron/scheduler.rs`: removed the manual `def.max_iterations` set, which
  also fixes a latent bug where it used the raw `max_iterations` instead of
  `effective_max_iterations()` (so extended-policy agents got shortchanged).
- `skill_runtime/run_machinery.rs` and `agent/task_dispatcher/executor.rs`:
  moved their 200-iteration workflow/task-run override to a new
  post-construction `Agent::set_max_tool_iterations` setter, since the
  shared fix would otherwise stamp `orchestrator`'s definition cap (15) over
  their intentionally larger budget.
- `subconscious/session.rs` and `subconscious/profiles/memory.rs`: same
  post-construction pattern, re-applying their mode-specific 15/30 cap after
  construction -- `profiles/memory.rs` in particular builds via
  `Agent::from_config` (-> `orchestrator`, cap 15), so without this the
  Aggressive/EventDriven tick would have silently dropped from 30 to 15.

`tinyflows/caps.rs`'s agent-node runtime now also scales its wall-clock
timeout for extended-cap agents (new `scale_timeout_for_iteration_cap`,
floor of `effective_cap * 12s` capped at the existing 600s ceiling), since a
50-iteration agent can legitimately run past the previous 240s default.

Full audit of every built-in `agent.toml`'s effective cap before/after is
pinned by a new snapshot test (`all_builtin_agent_definitions_have_expected_effective_max_iterations`)
so a future agent.toml edit can't silently change runtime behavior.

Closes tinyhumansai#4868
@graycyrus
graycyrus requested a review from a team July 14, 2026 20:23
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Direct agent construction now applies each named definition’s effective iteration cap. Runtime callers can override that cap after construction, subconscious modes preserve their budgets, and tinyflow agent-node timeouts scale with the resolved iteration limit.

Changes

Iteration cap resolution and runtime budgets

Layer / File(s) Summary
Definition-derived session caps
src/openhuman/agent/harness/{definition_tests.rs,session/builder/*,session/runtime.rs,session/tests.rs}
Session construction resolves named definitions through effective_max_iterations(), preserves the global default without a definition, and supports explicit post-construction overrides.
Direct invocation call sites
src/openhuman/cron/scheduler.rs, src/openhuman/flows/{ops.rs,ops_tests.rs}
Cron and flow paths rely on shared definition-cap resolution instead of mutating configuration at each call site.
Specialized runtime budgets
src/openhuman/agent/task_dispatcher/executor.rs, src/openhuman/skill_runtime/run_machinery.rs, src/openhuman/subconscious/{profiles/memory.rs,session.rs}
Autonomous tasks, workflow runs, and subconscious modes reapply their intended iteration budgets after agent construction.
Iteration-aware agent-node timeouts
src/openhuman/tinyflows/caps.rs
Agent-node timeouts scale from the constructed agent’s effective iteration cap, with coverage for scaling, ceilings, and definition-derived caps.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant AgentDefinition
  participant SessionBuilder
  participant Agent
  Caller->>SessionBuilder: build agent for named definition
  SessionBuilder->>AgentDefinition: resolve effective_max_iterations()
  AgentDefinition-->>SessionBuilder: return effective cap
  SessionBuilder->>Agent: construct with definition cap
  Caller->>Agent: set_max_tool_iterations(explicit budget)
Loading

Possibly related PRs

Suggested labels: rust-core, agent, bug

Suggested reviewers: senamakel, yellowsnnowmann

Poem

I’m a rabbit with caps in a neat little row,
Definition by definition, the budgets now grow.
Build, run, and discover—each knows what to do,
While timeouts stretch gently when iterations do.
Hop, hop—no task stops at ten! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: resolving iteration caps from the agent definition instead of the global default.
Linked Issues check ✅ Passed The changes address #4868 by using definition-based caps for direct invocations, preserving caller overrides, adding runtime coverage, and removing the scoped workaround.
Out of Scope Changes check ✅ Passed The added tests, setter, timeout scaling, and related call-site fixes all support the iteration-cap resolution objective and do not appear unrelated.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. bug rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. labels Jul 14, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 329f8571e0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +937 to +938
let timeout_secs =
scale_timeout_for_iteration_cap(base_timeout_secs, effective_iteration_cap);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor explicit timeout_secs on agent nodes

When an agent node provides timeout_secs, this now still passes the clamped explicit value through scale_timeout_for_iteration_cap, so any extended-policy agent with a 50-iteration cap turns a requested 30s/120s timeout into 600s. The existing contract in this file says the node's requested timeout_secs is clamped to 10..=600, and the unit test in src/openhuman/tinyflows/tests.rs asserts Some(120) -> 120; this change makes explicit fast-fail/SLA bounds ineffective for code_executor, tools_agent, etc. Scale only the default/no-timeout case, or otherwise preserve caller-supplied lower bounds.

Useful? React with 👍 / 👎.

def_cap,
config.agent.max_tool_iterations,
);
effective_agent_config.max_tool_iterations = def_cap;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Raise Flow Scout timeout for its extended cap

This shared assignment also gives flow_discovery its extended effective cap of 50, but flows_discover still wraps the turn in FLOW_DISCOVER_TIMEOUT_SECS = 300 at src/openhuman/flows/ops.rs:3198-3200. With slower providers or tool calls averaging just over 6s per loop, the fixed 300s wall-clock timeout fires before the newly applied definition cap can be reached; workflow_builder was moved to a 600s bound for the same 50-iteration budget, so Flow Scout needs the same treatment or equivalent scaling.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/openhuman/subconscious/session.rs (1)

177-195: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Correct mode-cap preservation; same missing state-transition log.

Shares the same root cause as the other three specialized-budget override sites; see the consolidated comment below.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/subconscious/session.rs` around lines 177 - 195, The
build_agent method correctly reapplies mode_iteration_cap after constructing the
subconscious agent; add the missing state-transition log at this specialized
budget override, matching the logging behavior used by the other three override
sites.

Source: Coding guidelines

🧹 Nitpick comments (1)
src/openhuman/agent/harness/session/runtime.rs (1)

161-174: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider logging the override for observability.

set_max_tool_iterations mutates a state established by the newly-introduced definition-cap resolution flow (issue #4868), but the setter itself is silent — none of its current call sites (task_dispatcher::executor, subconscious::session, subconscious::profiles::memory) log the override either, they only carry a code comment. Given this is exactly the kind of state transition that caused confusion before this fix, a log::debug!/tracing::debug! line here (old cap → new cap, stable prefix) would make future cap-mismatch bugs much easier to diagnose across all call sites at once.

♻️ Proposed logging addition
 pub fn set_max_tool_iterations(&mut self, cap: usize) {
+    log::debug!(
+        "[agent::runtime] set_max_tool_iterations agent_id={} {} -> {}",
+        self.agent_definition_name,
+        self.config.max_tool_iterations,
+        cap
+    );
     self.config.max_tool_iterations = cap;
 }

As per coding guidelines, "New or changed flows should log entry/exit, branches, external calls, retries/timeouts, state transitions, and errors with stable prefixes and correlation fields."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/agent/harness/session/runtime.rs` around lines 161 - 174,
Update set_max_tool_iterations to log the override as a debug-level state
transition using a stable prefix, including the previous
self.config.max_tool_iterations value and the new cap before assigning it. Keep
the setter’s existing mutation behavior unchanged so all current call sites gain
consistent observability.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/agent/task_dispatcher/executor.rs`:
- Around line 153-159: In the post-construction override near
agent.set_max_tool_iterations, add a state-transition log recording that the
autonomous task-run iteration budget is being pinned to TASK_RUN_MAX_ITERATIONS,
using the project’s established stable prefix and correlation fields consistent
with factory.rs definition-cap logging.

In `@src/openhuman/skill_runtime/run_machinery.rs`:
- Around line 198-204: Add the missing state-transition log alongside the
post-construction WORKFLOW_RUN_MAX_ITERATIONS override in the workflow-run
execution path. Match the task-dispatcher executor’s logging behavior and ensure
the log records that the agent’s tool-iteration budget was updated after
construction.

In `@src/openhuman/subconscious/profiles/memory.rs`:
- Around line 163-175: Preserve the post-construction override in the memory
tick, and add the missing state-transition log around
agent.set_max_tool_iterations(mode_iteration_cap). Log the agent’s transition to
the mode-specific iteration cap so this specialized budget change is observable,
consistent with the other budget sites.

---

Outside diff comments:
In `@src/openhuman/subconscious/session.rs`:
- Around line 177-195: The build_agent method correctly reapplies
mode_iteration_cap after constructing the subconscious agent; add the missing
state-transition log at this specialized budget override, matching the logging
behavior used by the other three override sites.

---

Nitpick comments:
In `@src/openhuman/agent/harness/session/runtime.rs`:
- Around line 161-174: Update set_max_tool_iterations to log the override as a
debug-level state transition using a stable prefix, including the previous
self.config.max_tool_iterations value and the new cap before assigning it. Keep
the setter’s existing mutation behavior unchanged so all current call sites gain
consistent observability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7b01c64f-c300-4676-a256-c9421db7e29a

📥 Commits

Reviewing files that changed from the base of the PR and between 0939279 and 329f857.

📒 Files selected for processing (13)
  • src/openhuman/agent/harness/definition_tests.rs
  • src/openhuman/agent/harness/session/builder/builder_tests.rs
  • src/openhuman/agent/harness/session/builder/factory.rs
  • src/openhuman/agent/harness/session/runtime.rs
  • src/openhuman/agent/harness/session/tests.rs
  • src/openhuman/agent/task_dispatcher/executor.rs
  • src/openhuman/cron/scheduler.rs
  • src/openhuman/flows/ops.rs
  • src/openhuman/flows/ops_tests.rs
  • src/openhuman/skill_runtime/run_machinery.rs
  • src/openhuman/subconscious/profiles/memory.rs
  • src/openhuman/subconscious/session.rs
  • src/openhuman/tinyflows/caps.rs

Comment on lines +153 to +159
// Issue #4868 — apply the autonomous task-run iteration budget AFTER
// construction. The session builder now stamps the resolved agent
// definition's own cap onto the agent; an autonomous task run
// intentionally needs a much larger budget (200), so this must be a
// post-construction override rather than a pre-set on `config` (which
// the builder would otherwise clobber).
agent.set_max_tool_iterations(TASK_RUN_MAX_ITERATIONS);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Post-construction override is correct; missing state-transition log.

The override logic itself is sound and matches set_max_tool_iterations's documented contract. However, this is a state transition (pinning the iteration budget to 200) with no log line, unlike the definition-cap resolution logging in factory.rs.

As per coding guidelines, "New or changed flows should log entry/exit, branches, external calls, retries/timeouts, state transitions, and errors with stable prefixes and correlation fields."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/agent/task_dispatcher/executor.rs` around lines 153 - 159, In
the post-construction override near agent.set_max_tool_iterations, add a
state-transition log recording that the autonomous task-run iteration budget is
being pinned to TASK_RUN_MAX_ITERATIONS, using the project’s established stable
prefix and correlation fields consistent with factory.rs definition-cap logging.

Source: Coding guidelines

Comment on lines +198 to +204
// Issue #4868 — apply the workflow-run iteration budget AFTER
// construction. The session builder now stamps `orchestrator`'s
// definition cap (15) onto the agent; a full workflow run
// intentionally needs a much larger budget (200), so this must be
// a post-construction override rather than a pre-set on `config`
// (which the builder would otherwise clobber).
agent.set_max_tool_iterations(WORKFLOW_RUN_MAX_ITERATIONS);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Correct override; same missing state-transition log as the task-dispatcher executor.

Shares the same root cause as src/openhuman/agent/task_dispatcher/executor.rs — see the consolidated comment below.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/skill_runtime/run_machinery.rs` around lines 198 - 204, Add the
missing state-transition log alongside the post-construction
WORKFLOW_RUN_MAX_ITERATIONS override in the workflow-run execution path. Match
the task-dispatcher executor’s logging behavior and ensure the log records that
the agent’s tool-iteration budget was updated after construction.

Source: Coding guidelines

Comment on lines +163 to +175
let mode_iteration_cap = effective.agent.max_tool_iterations;

let mut agent = Agent::from_config(&effective).map_err(|e| {
warn!("[subconscious:memory] agent init failed: {e}");
format!("agent init: {e}")
})?;
// Issue #4868 — `Agent::from_config` builds as the `orchestrator`
// definition (max_iterations=15, strict), so the session builder
// would stamp orchestrator's cap onto this agent regardless of mode
// — silently dropping `Aggressive`/`EventDriven` mode's intended
// 30-iteration budget set above to 15. Re-apply the mode-specific
// cap post-construction so this tick keeps its previous behavior.
agent.set_max_tool_iterations(mode_iteration_cap);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Correct fix for the orchestrator-cap clobbering; same missing state-transition log.

Confirmed against Agent::from_config's delegation to from_config_for_agent(config, "orchestrator") — the override is necessary and correctly applied. Shares the same missing-log root cause as the other three specialized-budget sites; see the consolidated comment below.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/subconscious/profiles/memory.rs` around lines 163 - 175,
Preserve the post-construction override in the memory tick, and add the missing
state-transition log around agent.set_max_tool_iterations(mode_iteration_cap).
Log the agent’s transition to the mode-specific iteration cap so this
specialized budget change is observable, consistent with the other budget sites.

Source: Coding guidelines

@senamakel
senamakel merged commit 4143ddf into tinyhumansai:main Jul 15, 2026
22 of 26 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Team Openhuman Jul 15, 2026
graycyrus added a commit to graycyrus/openhuman that referenced this pull request Jul 15, 2026
…ut, log cap pins

Post-merge follow-up on PR tinyhumansai#4870 (issue tinyhumansai#4868) addressing Codex/CodeRabbit
findings that shipped unaddressed:

- caps.rs: scale_timeout_for_iteration_cap was applied unconditionally to
  base_timeout_secs in run_via_harness, so an agent node that explicitly set
  timeout_secs (a fast-fail/SLA bound) got silently scaled up to match a high
  iteration cap. Added resolve_run_timeout_secs, which only scales the
  *default* 240s timeout — an explicit caller value is clamped (10..=600) but
  never widened.

- flows/ops.rs: flow_discovery now resolves to a 50-iteration cap (like
  workflow_builder), but FLOW_DISCOVER_TIMEOUT_SECS was left at 300s while
  workflow_builder's equivalent got bumped to 600s. Raised it to 600 to match.

- Added state-transition debug logs at the three post-construction
  agent.set_max_tool_iterations(...) overrides (task_dispatcher/executor.rs,
  skill_runtime/run_machinery.rs, subconscious/profiles/memory.rs) noting the
  iteration budget was pinned after construction, mirroring factory.rs's
  cap-resolution logging convention.
graycyrus added a commit to graycyrus/openhuman that referenced this pull request Jul 15, 2026
…ut, log cap pins

Post-merge follow-up on PR tinyhumansai#4870 (issue tinyhumansai#4868) addressing Codex/CodeRabbit
findings that shipped unaddressed:

- caps.rs: scale_timeout_for_iteration_cap was applied unconditionally to
  base_timeout_secs in run_via_harness, so an agent node that explicitly set
  timeout_secs (a fast-fail/SLA bound) got silently scaled up to match a high
  iteration cap. Added resolve_run_timeout_secs, which only scales the
  *default* 240s timeout — an explicit caller value is clamped (10..=600) but
  never widened.

- flows/ops.rs: flow_discovery now resolves to a 50-iteration cap (like
  workflow_builder), but FLOW_DISCOVER_TIMEOUT_SECS was left at 300s while
  workflow_builder's equivalent got bumped to 600s. Raised it to 600 to match.

- Added state-transition debug logs at the three post-construction
  agent.set_max_tool_iterations(...) overrides (task_dispatcher/executor.rs,
  skill_runtime/run_machinery.rs, subconscious/profiles/memory.rs) noting the
  iteration budget was pinned after construction, mirroring factory.rs's
  cap-resolution logging convention.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. bug rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

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

2 participants