Skip to content

fix(agent-harness): route the no-progress nudge through InjectMessage so interactive turns don't crash (#4089)#4480

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
senamakel:fix/GH-4089-change-strategy-on-repeat
Jul 4, 2026
Merged

fix(agent-harness): route the no-progress nudge through InjectMessage so interactive turns don't crash (#4089)#4480
senamakel merged 1 commit into
tinyhumansai:mainfrom
senamakel:fix/GH-4089-change-strategy-on-repeat

Conversation

@senamakel

@senamakel senamakel commented Jul 3, 2026

Copy link
Copy Markdown
Member

Summary

Problem

Issue #4089: when a tool call keeps failing, the agent retries the same strategy instead of adapting; it should get a structured "no progress since step X" signal and change approach before the retry cap.

The tinyagents 1.5 migration (#4473) implemented the mechanism: the crate's no_progress::NoProgressTracker returns NoProgress::Nudge(instruction) — a [no progress since step N] … Do NOT repeat it. Change strategy … corrective — once before the same-strategy halt. OpenHuman's RepeatedToolFailureMiddleware delivered it via SteeringCommand::Redirect.

But Redirect is Background-only. The interactive-turn steering policy (orchestration.rs) deliberately permits just InjectMessage/Pause so a rogue steer can't redirect the user's live turn out from under them. RepeatedToolFailureMiddleware runs on every turn, so every interactive turn that hit the nudge aborted with steering command redirect is not permitted by the run policy. This red-lines the raw-tool-loop / monitor E2E coverage suites (agent_*_raw_coverage_e2e, monitor_agent_e2e) — visible on #4473 itself and every PR off that base.

Solution

Deliver the nudge as a system message via SteeringCommand::InjectMessage(Message::system(instruction)). The corrective is trusted, system-generated advisory text, so InjectMessage is both permitted (interactive + background) and semantically correct — it lands the same corrective at the same safe loop boundary without weakening the interactive policy (Redirect stays refused for rogue-steer protection). The only other Redirect sender (agent_orchestration/running_subagents.rs sub-agent steering) is legitimately Background and untouched.

Submission Checklist

  • Tests added or updated (happy path + failure/edge) — nudge-before-halt as an InjectMessage; interactive-policy-permits-the-lane regression (the failure path: a Redirect nudge is refused by interactive).
  • Diff coverage ≥ 80% — the changed Nudge arm + the new assertions are exercised by the test.
  • Coverage matrix updated — N/A: behaviour-fix to existing no-progress handling.
  • All affected feature IDs listed under ## Related — N/A.
  • No new external network dependencies introduced.
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: internal steering lane.
  • Linked issue closed via Closes #NNN.

Impact

  • Fixes a crash on interactive chat turns that repeat-fail a tool (they now get the change-strategy nudge instead of aborting the whole turn). No change to sub-agent steering. Unblocks the raw-tool-loop / monitor E2E suites on this base.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/GH-4089-change-strategy-on-repeat
  • Commit SHA: see head

Validation Run

  • pnpm --filter openhuman-app format:check — N/A (no frontend changes)
  • pnpm typecheck — N/A (no TS changes)
  • Focused tests: openhuman::tinyagents::middleware::tests::repeated_tool_failure_nudges_change_of_strategy_before_the_halt — execution deferred to CI (shared build host); the raw-tool-loop E2E suites that were crashing exercise the fix end-to-end
  • Rust fmt/check (if changed): rustfmt --edition 2021 --check clean; cargo check --bin openhuman-core passed (Finished dev)
  • Tauri fmt/check (if changed): N/A

Validation Blocked

  • command: cargo test --lib -- repeated_tool_failure_nudges_change_of_strategy_before_the_halt
  • error: none — shared build host saturated
  • impact: cargo check compiled clean; deterministic test validated by CI

Behavior Changes

  • Intended behavior change: the no-progress nudge is delivered via InjectMessage (permitted on all run classes) instead of Redirect (Background-only), so interactive turns get the change-strategy corrective instead of crashing.
  • User-visible effect: interactive chat turns that repeat-fail a tool no longer abort mid-turn; the model is steered to change approach.

Parity Contract

  • Legacy behavior preserved: the nudge content, threshold (nudge at 2, halt at 3), and the halt/Pause path are unchanged; only the steering lane changes. Sub-agent Redirect steering is untouched. Interactive still refuses Redirect.
  • Guard/fallback/dispatch parity checks: the test asserts the interactive policy permits InjectMessage and still refuses Redirect.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this one

@senamakel senamakel requested a review from a team July 3, 2026 23:40
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Updates repeated tool-failure handling to inject a system-message nudge instead of redirecting, and extends the config schema catalog test with two privacy mode methods.

Changes

Repeated tool failure steering

Layer / File(s) Summary
No-progress nudge injection
src/openhuman/tinyagents/middleware.rs
Replaces the no-progress escalation action with SteeringCommand::InjectMessage carrying the instruction as a system message.
Nudge drain helper and test
src/openhuman/tinyagents/middleware.rs
Adds a helper that drains only injected nudge texts and a tokio test that checks the second identical tool failure emits one no-progress nudge and preserves the interactive steering policy for InjectMessage and Redirect.

Privacy mode schema catalog update

Layer / File(s) Summary
Add privacy mode methods
tests/config_auth_app_state_connectivity_e2e.rs
Adds openhuman.config_get_privacy_mode and openhuman.config_set_privacy_mode to the expected schema catalog.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: agent, bug

Suggested reviewers: M3gA-Mind

Poem

A rabbit hops with wiser flair,
A nudge appears in system air,
No-progress whispers, soft and neat,
Two privacy spells join the suite,
Hop-hop, the schema’s now aware 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The config privacy-mode schema golden update is unrelated to #4089 and looks like a separate CI-only change. Move the schema golden update to a separate PR unless it is required for this repeated-failure regression.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The middleware change and regression test add the required no-progress nudge after repeated failures for #4089.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: moving the no-progress nudge to InjectMessage to avoid interactive-turn crashes.

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

@coderabbitai coderabbitai Bot added the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label Jul 3, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 3, 2026
… so interactive turns don't crash (tinyhumansai#4089)

The tinyagents 1.5 migration (tinyhumansai#4473) moved the no-progress escalation
ladder into the crate (`no_progress::NoProgressTracker`), which feeds a
structured "no progress since step X" corrective back into the loop as a
`NoProgress::Nudge` — giving the model one chance to change strategy
before the same-strategy retry cap. OpenHuman's
`RepeatedToolFailureMiddleware` delivered that nudge via
`SteeringCommand::Redirect`.

But `Redirect` is Background (sub-agent) only: the interactive-turn
steering policy deliberately permits just `InjectMessage`/`Pause` so the
user's live turn can't be redirected out from under them by a rogue steer
(`orchestration.rs`). The middleware runs on *every* turn, so every
interactive turn that hit the nudge aborted with `steering command
redirect is not permitted by the run policy` — a tinyhumansai#4473 regression that
red-lines the raw-tool-loop / monitor E2E coverage suites.

Deliver the nudge as a system message via the `InjectMessage` lane
instead. The corrective is trusted, system-generated advisory text, so
`InjectMessage` is both permitted (on interactive *and* background) and
semantically correct — the change-strategy steering tinyhumansai#4089 asks for now
actually reaches the model on interactive chat instead of crashing it.

Tests: the nudge fires once (as an InjectMessage carrying the "no
progress" signal + the failing call name) on the 2nd identical failure,
before the halt; and a regression assertion that the interactive steering
policy permits the `InjectMessage` lane the nudge now uses (and still
refuses `Redirect`).

Closes tinyhumansai#4089.

Claude-Session: https://claude.ai/code/session_01KcmdqJVpjmnH31HqTHRLwG
@senamakel senamakel force-pushed the fix/GH-4089-change-strategy-on-repeat branch from a57ca24 to e8172f5 Compare July 3, 2026 23:59
@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. bug labels Jul 4, 2026
@coderabbitai coderabbitai Bot removed the rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. label Jul 4, 2026
@senamakel senamakel changed the title test(agent-harness): cover the change-strategy nudge before the retry cap (#4089) fix(agent-harness): route the no-progress nudge through InjectMessage so interactive turns don't crash (#4089) Jul 4, 2026
@senamakel senamakel merged commit e6bb4bf into tinyhumansai:main Jul 4, 2026
9 of 18 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Team Openhuman Jul 4, 2026
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

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

[Harness] Change strategy after repeated unproductive results instead of retrying

1 participant