How to propagate cancellation across multi-level LangGraph agents

Hi all,

We’re running a multi-agent setup using LangGraph with streaming enabled:

Supervisor agent → sub-agent → sub-sub-agent where each agent runs as an independent service (not in-process) and communicates over HTTP/A2A

When a user clicks “cancel” during a streaming response, we need that signal to propagate all the way down and stop execution at the deepest active agent.

A few details:

  • All agents are built with LangGraph
  • Deployed on Kubernetes with multiple replicas
  • Streaming responses are sent to the client in real time

Questions:

  • Does LangGraph support client-initiated cancellation natively?
  • I see server-side interrupts can pause execution but can the client trigger something similar?

Also curious if anyone has implemented this outside LangGraph, e.g.:

  • HTTP-level cancellation
  • Pub/sub or event-driven approaches

Would appreciate any patterns or real-world setups.

Thanks!

hi @sudokpr

have you tried sth like this:

from langgraph_sdk import get_client

client = get_client(url="http://...")

# Default: interrupt (preserves state)
await client.runs.cancel(thread_id, run_id)

# Or rollback (deletes everything)
await client.runs.cancel(thread_id, run_id, action="rollback", wait=True)
# By specific run IDs
await client.runs.cancel_many(
    thread_id=thread_id,
    run_ids=[run1_id, run2_id]
)

# By status (all running runs across all threads)
await client.runs.cancel_many(status="running")

Source code

# When streaming
async for chunk in client.runs.stream(
    thread_id,
    "agent",
    input={"messages": [{"role": "user", "content": "..."}]},
    on_disconnect="cancel",   # <-- key parameter
):
    print(chunk)

# When waiting for result
result = await client.runs.wait(
    thread_id,
    "agent",
    input={"messages": [{"role": "user", "content": "..."}]},
    on_disconnect="cancel",
)
async for part in client.runs.join_stream(
    thread_id, run_id,
    cancel_on_disconnect=True,  # cancels the run when this stream disconnects
):
    print(part)

source code 1
source code 2

Does it point you in the direction you expect?