Low-level orchestration framework for building stateful, multi-actor applications with LLMs
Client implementation for calling remote LangGraph APIs deployed on LangGraph Cloud or LangSmith. RemoteGraph behaves identically to CompiledStateGraph and can be used as a node in another graph.
Client for remote graph execution via HTTP API.
class RemoteGraph<
InputType = any,
OutputType = any
> extends Runnable<InputType, OutputType> implements PregelInterface {
graphId: string;
client: Client;
syncClient: Client;
constructor(params: RemoteGraphParams);
invoke(
input: InputType,
options?: PregelOptions
): Promise<OutputType>;
stream(
input: InputType,
options?: PregelOptions
): IterableReadableStream;
streamEvents(
input: InputType,
options: PregelOptions & { version: "v1" | "v2" }
): IterableReadableStream<StreamEvent>;
getState(
config: LangGraphRunnableConfig,
options?: GetStateOptions
): Promise<StateSnapshot>;
getStateHistory(
config: LangGraphRunnableConfig,
options?: CheckpointListOptions
): AsyncIterableIterator<StateSnapshot>;
updateState(
config: LangGraphRunnableConfig,
values: UpdateType | Command,
asNode?: string
): Promise<RunnableConfig>;
getGraph(
config?: RunnableConfig & { xray?: boolean | number }
): DrawableGraph;
getSubgraphs(
namespace?: string,
recurse?: boolean
): IterableIterator<[string, Pregel]>;
getSubgraphsAsync(
namespace?: string,
recurse?: boolean
): AsyncIterableIterator<[string, Pregel]>;
withConfig(config: Partial<PregelOptions>): this;
}Configuration for RemoteGraph client.
interface RemoteGraphParams {
graphId: string;
client?: Client;
url?: string;
apiKey?: string;
headers?: Record<string, string>;
streamResumable?: boolean;
checkpointer?: BaseCheckpointSaver | false;
store?: BaseStore;
cache?: BaseCache;
interruptBefore?: string[] | All;
interruptAfter?: string[] | All;
name?: string;
description?: string;
}graphId - Unique identifier for the remote graphclient - LangGraph SDK Client instance (optional, created from other params if not provided)url - Base URL of the remote LangGraph APIapiKey - API key for authenticationheaders - Additional HTTP headersstreamResumable - Whether streaming can be resumed after interruptioncheckpointer - Local checkpoint saver (for offline operation)store - Local store for long-term memorycache - Local cache for resultsinterruptBefore - Nodes to interrupt before (overrides remote config)interruptAfter - Nodes to interrupt after (overrides remote config)name - Graph namedescription - Graph descriptionimport { RemoteGraph } from "@langchain/langgraph/remote";
const remoteGraph = new RemoteGraph({
graphId: "my-deployed-graph",
url: "https://api.langgraph.cloud",
apiKey: process.env.LANGGRAPH_API_KEY
});
const result = await remoteGraph.invoke({
messages: [{ role: "user", content: "Hello!" }]
});import { Client } from "@langchain/langgraph-sdk";
import { RemoteGraph } from "@langchain/langgraph/remote";
const client = new Client({
apiUrl: "https://api.langgraph.cloud",
apiKey: process.env.LANGGRAPH_API_KEY
});
const remoteGraph = new RemoteGraph({
graphId: "my-graph",
client
});const remoteGraph = new RemoteGraph({
graphId: "stateful-graph",
url: process.env.LANGGRAPH_URL,
apiKey: process.env.LANGGRAPH_API_KEY
});
// First invocation
await remoteGraph.invoke(input, {
configurable: { thread_id: "thread-123" }
});
// Continue from checkpoint
await remoteGraph.invoke(null, {
configurable: { thread_id: "thread-123" }
});for await (const chunk of await remoteGraph.stream(input, {
streamMode: "values",
configurable: { thread_id: "thread-1" }
})) {
console.log(chunk);
}for await (const chunk of await remoteGraph.stream(input, {
streamMode: ["values", "updates", "debug"],
configurable: { thread_id: "thread-1" }
})) {
const [namespace, mode, data] = chunk;
console.log(`Mode: ${mode}`, data);
}const state = await remoteGraph.getState({
configurable: { thread_id: "thread-1" }
});
console.log(state.values); // Current state
console.log(state.next); // Next nodes to execute
console.log(state.tasks); // Pending tasksfor await (const snapshot of remoteGraph.getStateHistory({
configurable: { thread_id: "thread-1" }
}, {
limit: 10
})) {
console.log(snapshot.values);
console.log(snapshot.metadata);
}await remoteGraph.updateState(
{ configurable: { thread_id: "thread-1" } },
{ messages: [{ role: "user", content: "Override" }] },
"node_name" // Act as if this node made the update
);import { StateGraph, Annotation } from "@langchain/langgraph";
import { RemoteGraph } from "@langchain/langgraph/remote";
const remoteResearchAgent = new RemoteGraph({
graphId: "research-agent",
url: process.env.LANGGRAPH_URL,
apiKey: process.env.LANGGRAPH_API_KEY
});
const State = Annotation.Root({
messages: Annotation<BaseMessage[]>({
reducer: (a, b) => a.concat(b),
default: () => []
}),
researchData: Annotation<any>
});
const mainGraph = new StateGraph(State)
.addNode("local_processing", localNode)
.addNode("remote_research", remoteResearchAgent) // Use as node
.addNode("synthesis", synthesisNode)
.addEdge("__start__", "local_processing")
.addEdge("local_processing", "remote_research")
.addEdge("remote_research", "synthesis")
.addEdge("synthesis", "__end__")
.compile();
await mainGraph.invoke(input);const remoteGraph = new RemoteGraph({
graphId: "my-graph",
url: "https://api.langgraph.cloud",
apiKey: process.env.LANGGRAPH_API_KEY,
headers: {
"X-Custom-Header": "value",
"Authorization": `Bearer ${process.env.CUSTOM_TOKEN}`
}
});const remoteGraph = new RemoteGraph({
graphId: "interruptible-graph",
url: process.env.LANGGRAPH_URL,
apiKey: process.env.LANGGRAPH_API_KEY,
interruptBefore: ["human_review"]
});
// First call - will interrupt
const result = await remoteGraph.invoke(input, {
configurable: { thread_id: "thread-1" }
});
if (isInterrupted(result)) {
console.log("Waiting for human input");
// Resume with Command
await remoteGraph.invoke(
new Command({ resume: humanInput }),
{ configurable: { thread_id: "thread-1" } }
);
}import { RemoteException } from "@langchain/langgraph";
try {
const result = await remoteGraph.invoke(input);
} catch (error) {
if (error instanceof RemoteException) {
console.error("Remote graph error:", error.message);
} else {
console.error("Network or other error:", error);
}
}for await (const event of remoteGraph.streamEvents(input, {
version: "v2",
streamMode: "values",
configurable: { thread_id: "thread-1" }
})) {
console.log(event);
}const graph = remoteGraph.getGraph();
console.log(graph.nodes); // Nodes in remote graph
console.log(graph.edges); // Edges in remote graph
// Generate visualization
const mermaid = graph.drawMermaid();
console.log(mermaid);// Iterate through subgraphs
for (const [namespace, subgraph] of remoteGraph.getSubgraphs()) {
console.log(`Subgraph: ${namespace}`);
}
// Async iteration
for await (const [namespace, subgraph] of remoteGraph.getSubgraphsAsync(undefined, true)) {
console.log(`Subgraph: ${namespace}`);
}// Environment-based configuration
const remoteGraph = new RemoteGraph({
graphId: process.env.GRAPH_ID!,
url: process.env.LANGGRAPH_API_URL!,
apiKey: process.env.LANGGRAPH_API_KEY!,
headers: {
"X-Environment": process.env.NODE_ENV || "production"
}
});
// Retry wrapper
async function invokeWithRetry(input: any, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await remoteGraph.invoke(input);
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}function createTenantGraph(tenantId: string) {
return new RemoteGraph({
graphId: "multi-tenant-graph",
url: process.env.LANGGRAPH_URL!,
apiKey: process.env.LANGGRAPH_API_KEY!,
headers: {
"X-Tenant-ID": tenantId
}
});
}
const tenantGraph = createTenantGraph("tenant-123");
await tenantGraph.invoke(input, {
configurable: { thread_id: `${tenantId}-${sessionId}` }
});const endpoints = [
"https://api1.langgraph.cloud",
"https://api2.langgraph.cloud",
"https://api3.langgraph.cloud"
];
function getBalancedGraph() {
const url = endpoints[Math.floor(Math.random() * endpoints.length)];
return new RemoteGraph({
graphId: "balanced-graph",
url,
apiKey: process.env.LANGGRAPH_API_KEY
});
}LangGraph SDK Client for direct API access.
class Client {
constructor(config: {
apiUrl: string;
apiKey?: string;
headers?: Record<string, string>;
});
threads: ThreadsClient;
runs: RunsClient;
crons: CronsClient;
assistants: AssistantsClient;
}Use the Client directly for advanced operations beyond RemoteGraph capabilities.
import { Client } from "@langchain/langgraph-sdk";
const client = new Client({
apiUrl: "https://api.langgraph.cloud",
apiKey: process.env.LANGGRAPH_API_KEY
});
// List assistants
const assistants = await client.assistants.list();
// Get thread state
const threadState = await client.threads.getState(threadId);
// List runs
const runs = await client.runs.list(threadId);