langchain-ai/deepagents · error · RequestError

-32600

-32600

Error message

ACP limitation: this agent raised a free-form LangGraph interrupt(), which ACP cannot display.

ACP only supports human-in-the-loop permission prompts with a fixed set of decisions (approve/reject/edit).
Spec: https://agentclientprotocol.com/protocol/overview

Fix: use LangChain HumanInTheLoopMiddleware-style interrupts (action_requests/review_configs).
Docs: https://docs.langchain.com/oss/python/langchain/human-in-the-loop

This is a protocol limitation, not a bug in the agent.

What it means

When the streamed agent emits a LangGraph `__interrupt__` whose value is not a dict, the ACP server cannot map it to ACP's fixed approve/reject/edit permission prompt and raises a JSON-RPC RequestError with code -32600. ACP only supports HumanInTheLoopMiddleware-style interrupts carrying `action_requests`/`review_configs`; free-form `interrupt()` payloads cannot be rendered by ACP clients. This is a protocol limitation, not a bug in your agent.

Source

Thrown at libs/acp/deepagents_acp/server.py:1034

                _expected_len = 3  # (namespace, stream_mode, data)
                if not isinstance(stream_chunk, tuple) or len(stream_chunk) != _expected_len:
                    continue

                _namespace, stream_mode, data = stream_chunk
                # Check for cancellation during streaming
                if self._cancelled:
                    self._cancelled = False  # Reset for next prompt
                    return PromptResponse(stop_reason="cancelled")

                if stream_mode == "updates":
                    updates = data
                    if isinstance(updates, dict) and "__interrupt__" in updates:
                        interrupt_objs = updates.get("__interrupt__")
                        if interrupt_objs:
                            for interrupt_obj in interrupt_objs:
                                interrupt_value = interrupt_obj.value
                                if not isinstance(interrupt_value, dict):
                                    raise RequestError(
                                        -32600,
                                        (
                                            "ACP limitation: this agent raised a free-form "
                                            "LangGraph interrupt(), which ACP cannot display.\n\n"
                                            "ACP only supports human-in-the-loop permission "
                                            "prompts with a fixed set of decisions "
                                            "(approve/reject/edit).\n"
                                            "Spec: https://agentclientprotocol.com/protocol/overview\n\n"
                                            "Fix: use LangChain HumanInTheLoopMiddleware-style "
                                            "interrupts (action_requests/review_configs).\n"
                                            "Docs: https://docs.langchain.com/oss/python/langchain/"
                                            "human-in-the-loop\n\n"
                                            "This is a protocol limitation, not a bug in the agent."
                                        ),
                                        {"interrupt_value": interrupt_value},
                                    )

                            # The checkpoint backing this update may not be visible until

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Replace the free-form `interrupt()` call with LangChain HumanInTheLoopMiddleware-style interrupts that emit dicts with `action_requests`/`review_configs`
  2. If you must keep the raw interrupt, wrap the payload as a dict matching ACP's expected permission-prompt schema
  3. Move the free-form HITL flow out of the ACP-served agent into a client-side or non-ACP pathway
  4. See the docs linked in the message: https://docs.langchain.com/oss/python/langchain/human-in-the-loop

Example fix

# before
reply = interrupt("Approve this write?")
# after
from langchain.agents.middleware import HumanInTheLoopMiddleware
# configure the middleware with action_requests/review_configs so the
# interrupt value is a dict ACP can render as approve/reject/edit
Defensive patterns

Strategy: try-catch

Type guard

def is_acp_compatible_interrupt(value: object) -> bool:
    return isinstance(value, dict) and "action_requests" in value

Try / catch

try:
    resp = await conn.prompt(blocks, session_id)
except RequestError as exc:
    if exc.code == -32600 and "free-form" in str(exc):
        # Agent used bare interrupt(); switch to HumanInTheLoopMiddleware
        ...
    raise

Prevention

When it happens

Trigger: Calling `prompt()` against an agent that calls LangGraph's bare `interrupt(payload)` with a non-dict value (e.g. a string or dataclass), or a custom node interrupting with an unsupported payload shape, during `agent.astream(...)` in server.py:1031-1034.

Common situations: Porting an existing LangGraph agent to ACP without converting its raw `interrupt()` calls; hand-written HITL nodes using `interrupt('confirm?')`; library middleware or subgraphs that emit custom interrupt payloads the ACP bridge doesn't recognize.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/bf5ac97213f95fae. Report an issue: GitHub.