Skip to content

feat(langchain): add respond decision to HITL middleware#37095

Merged
Sydney Runkle (sydney-runkle) merged 1 commit into
masterfrom
sr/hitl-middleware-extension
Apr 30, 2026
Merged

feat(langchain): add respond decision to HITL middleware#37095
Sydney Runkle (sydney-runkle) merged 1 commit into
masterfrom
sr/hitl-middleware-extension

Conversation

@sydney-runkle
Copy link
Copy Markdown
Collaborator

Extends HumanInTheLoopMiddleware with a new respond decision type for "ask user" style tools — tools whose real implementation is the human's response. The interrupt is raised with the tool call as usual; the resume payload becomes the body of a synthetic ToolMessage with status="success", and the tool itself is not executed.

This complements reject (which produces a synthetic ToolMessage with status="error") by enabling the symmetric success path: a reviewer can answer on the tool's behalf without invoking it.

Changes

  • New RespondDecision TypedDict with a required message: str field; added to the Decision union.
  • "respond" added to the DecisionType literal.
  • _process_decision handles "respond" by emitting a ToolMessage with status="success" and preserving the original tool call on the AIMessage so provider-required tool-call/tool-message pairing is maintained.
  • The True shortcut in interrupt_on now expands to ["approve", "edit", "reject", "respond"], so existing callers that opted into "all decisions" pick up the new capability without code changes. The reject decision already permits a reviewer to inject arbitrary ToolMessage content, so respond extends the same trust model — not a new capability class.

Example

from langchain.agents.middleware import HumanInTheLoopMiddleware

middleware = HumanInTheLoopMiddleware(
    interrupt_on={"ask_user": {"allowed_decisions": ["respond"]}}
)
# Resume payload: {"decisions": [{"type": "respond", "message": "blue"}]}
# → synthetic ToolMessage(content="blue", status="success") for `ask_user`.

Implementation drafted with AI-agent assistance.

Extends `HumanInTheLoopMiddleware` with a new `respond` decision type for
"ask user" style tools whose real implementation is the human's response.
The interrupt is raised with the tool call as usual; the resume payload
becomes the body of a synthetic `ToolMessage` with `status="success"`,
and the tool itself is not executed.

This complements `reject` (synthetic `ToolMessage` with `status="error"`)
by providing the symmetric success path: a reviewer can answer on the
tool's behalf without invoking it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added feature For PRs that implement a new feature; NOT A FEATURE REQUEST internal langchain `langchain` package issues & PRs size: S 50-199 LOC labels Apr 30, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 30, 2026

Merging this PR will degrade performance by 99.6%

❌ 1 regressed benchmark
✅ 1 untouched benchmark
⏩ 13 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation test_create_agent_instantiation_with_middleware 15.1 ms 3,760.5 ms -99.6%

Comparing sr/hitl-middleware-extension (23aaa1d) with master (38553c3)

Open in CodSpeed

Footnotes

  1. 13 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@sydney-runkle Sydney Runkle (sydney-runkle) merged commit ba56ac6 into master Apr 30, 2026
54 of 55 checks passed
@sydney-runkle Sydney Runkle (sydney-runkle) deleted the sr/hitl-middleware-extension branch April 30, 2026 18:55
Sydney Runkle (sydney-runkle) added a commit that referenced this pull request Apr 30, 2026
Bumps `langchain` from 1.2.16 → 1.2.17.

Picks up:
- `respond` decision added to HITL middleware (#37095)

> This PR was opened with AI-agent assistance.
Sydney Runkle (sydney-runkle) added a commit to langchain-ai/docs that referenced this pull request May 1, 2026
Mason Daugherty (mdrxy) added a commit to langchain-ai/deepagents that referenced this pull request May 6, 2026
… decision (#3200)

The HITL trio (`test_hitl_agent`, `test_subagent_with_hitl`,
`test_subagent_with_custom_interrupt_on`) had been failing on every
model eval, because the `review_configs` assertions pinned the
pre-`respond` contract. Upstream
[langchain-ai/langchain#37095](langchain-ai/langchain#37095)
(in `langchain` 1.2.x) added a fourth `respond` decision and now
resolves `interrupt_on[tool] = True` to `["approve", "edit", "reject",
"respond"]`.
Mason Daugherty (mdrxy) added a commit to langchain-ai/deepagents that referenced this pull request May 6, 2026
The three HITL tests in `libs/evals/tests/evals/test_hitl.py` were
failing for every model the eval matrix ran against because they assert
SDK structural state (interrupt payload shape, `allowed_decisions`
contents) — not model behavior. When
[langchain-ai/langchain#37095](langchain-ai/langchain#37095)
added a fourth `respond` decision in 1.2.x, the auto-failure-analyzer
attributed the breakage to model capability gaps. Two-pronged fix: move
them where they belong, and lock CI dep resolution so the next surprise
upstream change is a deliberate commit instead of a fresh resolve.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature For PRs that implement a new feature; NOT A FEATURE REQUEST internal langchain `langchain` package issues & PRs size: S 50-199 LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants