Skip to content

fix(agent): synthesize results after terminal loop caps - #76080

Closed
seppegadeyne wants to merge 1 commit into
NousResearch:mainfrom
seppegadeyne:fix/tool-loop-cap-final-synthesis
Closed

fix(agent): synthesize results after terminal loop caps#76080
seppegadeyne wants to merge 1 commit into
NousResearch:mainfrom
seppegadeyne:fix/tool-loop-cap-final-synthesis

Conversation

@seppegadeyne

Copy link
Copy Markdown
Contributor

What does this PR do?

Terminal loop_web_search_cap and loop_subagent_cap guardrails currently replace all collected work with a canned stop message. This PR preserves the cap while asking the current model for one tool-free final response from the evidence already in the turn.

It also makes terminal-cap handling fail-closed within a mixed tool batch: when the next emitted batch would cross one of these caps, calls are reserved in order and every call after the capped search/delegation is closed with a synthetic skipped result instead of being allowed to start concurrently.

The summary path:

  • performs exactly one provider attempt (no empty-response retry)
  • sends no tool definitions for Chat Completions, Anthropic Messages, Codex Responses, or Bedrock Converse
  • uses an ephemeral instruction rather than persisting a synthetic user message
  • records the extra attempt in result["api_calls"]
  • avoids replaying Codex output that was already streamed
  • falls back to the existing controlled-halt text if the provider fails or returns empty content

Other hard-stop guardrails retain their current behavior. This is intentionally narrower than a general “one rebound” implementation.

Related Issue(s)

Related to #64322.

Complements, but does not supersede, the broader recovery proposal in #64363. This PR handles only the terminal per-turn caps added in #66600; it does not give other hard-stop guardrails another tool-enabled model round.

Testing

  • scripts/run_tests.sh tests/run_agent/test_tool_call_guardrail_runtime.py tests/agent/test_tool_guardrails.py tests/run_agent/test_agent_guardrails.py tests/run_agent/test_run_agent.py tests/run_agent/test_tool_batch_segmentation.py tests/run_agent/test_tool_call_incremental_persistence.py tests/run_agent/test_concurrent_interrupt.py tests/run_agent/test_tool_executor_contextvar_propagation.py -q
    • 314 passed on Arch Linux
  • The focused ARM64 guardrail/segmentation set:
    • 70 passed on Raspberry Pi OS / Debian 13
  • Full local suite:
    • 23,661 passed, 1 unrelated failure
  • .venv/bin/ruff check .
  • .venv/bin/python scripts/check-windows-footguns.py --all
  • python -m py_compile for all changed Python files
  • git diff --check

The lone full-suite failure was tests/agent/test_compression_concurrent_fork.py::test_fence_cancelled_compression_leaves_lock_reacquirable; this timing-sensitive compression file also fails in a clean upstream/main worktree with the same environment. Required GitHub CI remains authoritative for the complete matrix.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactor
  • Documentation
  • Other (please describe):

Checklist

  • I tested this locally
  • I added/updated tests for my changes
  • All tests pass locally with ./scripts/run_tests.sh
  • Code is formatted and follows project conventions
  • I performed a self-review
  • No secrets, credentials, or personal data included
  • I updated documentation (if applicable)

The full-suite checkbox is intentionally left unchecked only because the clean-base failure documented above reproduces unchanged on upstream/main; the focused 314-test regression set is green.

Platform

  • OS: Arch Linux (Aorus) and Debian GNU/Linux 13 ARM64 (Raspberry Pi 5 focused tests)
  • Python: 3.11
  • Install method: local editable checkout / existing Hermes development venv

Screenshots / Logs

Not applicable — agent runtime/control-flow change.

Additional Notes

Brave Search PR #75333 is unrelated: it changes setup-time capability detection only. The exact cap code is produced by #66600, while #31448 made controlled halt text visible to clients. This PR keeps both protections and changes only the terminal-cap recovery path.

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint tool/web Web search and extraction tool/delegate Subagent delegation P2 Medium — degraded but workaround exists needs-decision Awaiting maintainer decision before any implementation labels Aug 1, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #64363 proposes a broader tool-enabled rebound after hard stops, while this PR limits terminal caps to one tool-free final synthesis. Maintainers should choose the intended recovery contract.

@teknium1

teknium1 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Thank you for the focused cap-handling work and the provider-specific tests.

  • This automated hermes-sweeper review verified that current main still emits the controlled halt at agent/conversation_loop.py:6198-6218, so the reported UX is real.
  • The proposed recovery intentionally sends a provider request with tools removed (tools_for_api=[] / tools=None, agent/chat_completion_helpers.py, commit e71cd8fb5cb3083d37c7dc344bf30ac2b2b781da). That matches the standing tools-disabled policy: Hermes must not omit or unload tool schemas from the model request.
  • Please retain the existing tool-enabled controlled-halt behavior. Any future recovery proposal must preserve tool schemas on the wire rather than use a tool-free final call.

This is an automated hermes-sweeper review.


Closed as not-planned per standing maintainer policy (tools-disabled). This is a design-direction decision, not a code-quality judgment — see the Contribution Rubric in AGENTS.md for what the project is looking for. If you believe this policy was misapplied to your change, comment here and a maintainer will take a look.

@teknium1 teknium1 closed this Aug 1, 2026
@teknium1 teknium1 added the sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) label Aug 1, 2026
@seppegadeyne

Copy link
Copy Markdown
Contributor Author

Acknowledged. This proposal intentionally used a tool-free terminal synthesis, so the tools-disabled policy applies; I will not request reopening under the current design. The provider/security/accounting follow-up work remains only on the fork branch for reference, and the local runtime patch has been rolled back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists sweeper:not-planned Sweeper: closed per standing maintainer policy (design direction) tool/delegate Subagent delegation tool/web Web search and extraction type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants