fix: gate @agent.hitl on the generic call tool via when predicate - #170
Merged
Merged
Conversation
The generic combined 'call' action tool (the default since the per_action_tool flip) is named 'call', which matches no entry in srv.actions. buildHitlInterruptMap keys HITL on that match, so humanInTheLoopMiddleware returns no middleware and @agent.hitl is silently ignored. Non-hybrid test asserting HITL middleware is installed for the @agent.hitl submitOrder action, plus a per_action_tool contrast proving the cause.
The generic combined 'call' action tool (the default since the per_action_tool flip) is named 'call', which matches no entry in srv.actions, so buildHitlInterruptMap produced an empty map and @agent.hitl was silently ignored. Gate the 'call' tool per-invocation with LangChain's interruptOn[tool].when predicate, which reads the requested action from args.action and checks its @agent.hitl / @Common.IsActionCritical annotation. Per-action tools keep their direct name-based gating. Export buildHitlInterruptMap so the non-hybrid test can assert the predicate interrupts submitOrder but not getStock.
SummaryThe following content is AI-generated and provides a summary of the pull request: Titlefix: Gate HITL actions for generic CategoryBug Fix SummaryThis PR fixes HITL middleware wiring for the generic combined Changes
TestsAdds integration coverage for:
Related: #166 Have you...
PR Bot InformationVersion:
|
This was referenced Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With the generic combined
callaction tool (the default since theper_action_toolflip in #166),@agent.hitlwas silently ignored.HITL wiring in
lib/agents/middleware/hitl.jsbuilt its interrupt map by matchingtool.nameagainstsrv.actions[tool.name]["@agent.hitl"]:submitOrder→ matches the annotated action → gatedcall→ matches no action → interrupt map empty → not gatedThe generic tool collapses every action behind one name, with the target action passed in
args.action,so a tool-name match can't express the per-action
@agent.hitlgranularity.Fix
Gate the
calltool per-invocation using LangChain'sinterruptOn[tool].whenpredicate, which reads therequested action from
request.toolCall.args.actionand checks its@agent.hitl/@Common.IsActionCriticalannotation. Per-action tools keep their direct name-based gating.Tests
tests/integration/hitl-tool-wiring.test.js:@agent.hitlaction under the default (generic) configcalltool'swhenpredicate interruptssubmitOrderbut notgetStock