Resume LangGraph python interrupt from LangGraph JS SDK

Hello,

I am running a LangGraph agent in python locally using LangGraph server.

The agent is exposed in a webapp via an integration that uses the LangGraph JS SDK.

In my tool I have an interrupt to let the user approve the action.

I am able to catch the interrupt with the JS SDK and handle it in my frontend.

However, I don’t know how to resume with the JS SDK.

I read here (albeit the LangGraph JS and not the SDK) to send null but that doesn’t work: How to add dynamic breakpoints

Thanks in advance for any help!

Anyone?

I figured it out:

streamResponse = client.runs.stream(
        thread_id,
        // this is where we specify the assistant id to use
        agent["assistant_id"],
        {
          command: { resume: { correct: "y" } },
          streamMode: "updates",
          config: config
        }
      );
2 Likes

did that work? it’s not working for me either

hi @niek

Your solution looks correct, however, here’s a small snippet for React:

import { useCallback, useState } from "react";
import { Client } from "@langchain/langgraph-sdk";

const client = new Client({ apiUrl: "http://localhost:8123" });

export function useAgentRunner(threadId, assistantId) {
  const [pendingInterrupt, setPendingInterrupt] = useState(null);

  const run = useCallback(async (messages) => {
    const stream = client.runs.stream(threadId, assistantId, {
      input: { messages },
      streamMode: "updates",
    });

    for await (const event of stream) {
      // Render tokens/updates as needed
      // detect your interrupt using whatever shape you already handle
      if (event?.interrupt || event?.data?.interrupts) {
        setPendingInterrupt(event);
        break; // pause UI loop; wait for user action
      }
    }
  }, [threadId, assistantId]);

  const resume = useCallback(async (resumeValue) => {
    const stream = client.runs.stream(threadId, assistantId, {
      command: { resume: resumeValue },
      streamMode: "updates",
    });
    for await (const event of stream) {
      // continue rendering updates/messages
    }
    setPendingInterrupt(null);
  }, [threadId, assistantId]);

  return { run, resume, pendingInterrupt };
}

// Example UI handlers
// const { run, resume, pendingInterrupt } = useAgentRunner(threadId, assistantId);
// onSend: run([{ role: "human", content: input }])
// onApprove: resume({ approved: true })
// onEdit: resume(editedText)