fix(agent): steer background review to permitted tools - #65803
fix(agent): steer background review to permitted tools#65803henrynguyeninfo1 wants to merge 1 commit into
Conversation
Rejected: narrow review tool schemas | breaks prompt-cache byte parity with the parent agent Not-tested: live provider response after a denied file-tool call RISK: model self-correction remains probabilistic across providers
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved (read-only token — formal approval requires write access)
Improves the denial message for background review when a non-whitelisted tool is called. The new message guides users toward the correct tools (skill_view, skill_manage) instead of just saying "not allowed."
- Small, helpful UX improvement
- Good test coverage verifying the new message includes skill_view, skill_manage, and memory keywords
Reviewed by Hermes Agent
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused mitigation. The premise is confirmed on current main: agent/background_review.py:819-835 installs a memory/skills-only runtime whitelist while retaining parent schemas for cache parity, and its current denial text at agent/background_review.py:832-833 does not identify replacement tools. The thread-local dispatcher formats that message for blocked calls at hermes_cli/plugins.py:2137-2143; tools/skill_manager_tool.py:382-408 confirms that skill_view is the required read path before a review can mutate an existing skill.
Problems
tests/run_agent/test_background_review_toolset_restriction.pyadds assertions forskill_view,skill_manage, andmemory, but notskills_list. The message explicitly advertisesskills_list; that portion can regress without coverage.
Suggested changes
- Assert that
skills_listis present indeny_msg.
A member has also identified open PR #61618 as the broader duplicate, including equivalent proactive-prompt guidance. This is an automated hermes-sweeper review.
| assert "read_file" in deny_msg | ||
| assert "skill_view" in deny_msg | ||
| assert "skill_manage(action='patch'" in deny_msg | ||
| assert "memory" in deny_msg |
There was a problem hiding this comment.
Please also assert "skills_list" in deny_msg. The changed production message advertises it as the discovery path, but the new regression test does not currently protect that wording.
SummaryTwenty-four PRs address or reference this background-review complex: they cover cache-key parity ( Related pull requests
Duplicates#17276 and #25427 were salvaged into #25434; #29568 was salvaged into #29704; #18973, #20674, #27510, #30532, and the reasoning portion of #36995 converge on #64379. #27422, #40007, #40060, and #46684 share the one-off Suggested consolidationKeep #65803 open with a salvage path: preserve its cache-parity-safe denial steering, add the reviewer-requested Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I61521(["issue #61521 (open)"])
subgraph Dup61529 ["PRs duplicating each other"]
P61529["PR #61529 (open)"]
P65803["PR #65803 (open)"]
end
P65803 -->|best fix| I61521
class I61521 open
class P61529 open
class P65803 open
class P65803 best
class P65803 target
click I61521 "https://github.com/NousResearch/hermes-agent/issues/61521"
click P61529 "https://github.com/NousResearch/hermes-agent/pull/61529"
click P65803 "https://github.com/NousResearch/hermes-agent/pull/65803"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 24 pull requests and 7 issues in this complex. Each diff was read against this issue; Assessment working set: 179 kB of PR diffs, 96 kB of issue/PR text, 43 kB of discussion (53 comments), 51 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
Summary
skills_list,skill_view, andskill_managepathread_filedenial through the real thread-local dispatch gateRoot cause
The review fork intentionally advertises the parent agent's full tool schema, but runtime dispatch only permits memory and skill tools. The denial result previously said only that memory/skill tools were allowed, so it did not redirect models from
read_fileorpatchto the APIs that satisfy the skill manager's read-before-write guard.Testing
uv run --extra dev pytest tests/run_agent/test_background_review.py tests/run_agent/test_background_review_cost_controls.py tests/run_agent/test_background_review_cache_parity.py tests/run_agent/test_background_review_summary.py tests/run_agent/test_background_review_toolset_restriction.py tests/test_background_review_session_isolation.py tests/test_background_review_list_shapes.py tests/hermes_cli/test_plugins.py::TestThreadToolWhitelist -quv run --extra dev ruff check agent/background_review.py tests/run_agent/test_background_review_toolset_restriction.pyuv run --extra dev python -m py_compile agent/background_review.py tests/run_agent/test_background_review_toolset_restriction.pyTested on macOS.
Alternative considered
Narrowing the fork's advertised schemas would eliminate invalid calls earlier, but it would break the intentional byte parity with the parent request and lose prompt-cache reuse. This change keeps parity and improves self-correction at the dispatch boundary.
Fixes #61521