How to add node retry policies¶
There are many use cases where you may wish for your node to have a custom retry policy. Some examples of when you may wish to do this is if you are calling an API, querying a database, or calling an LLM, etc.
In order to configure the retry policy, you have to pass the retryPolicy
parameter to the addNode
function. The retryPolicy
parameter takes in a RetryPolicy
named tuple object. Below we instantiate a RetryPolicy
object with the default parameters:
In [1]:
Copied!
import { RetryPolicy } from "@langchain/langgraph"
const retryPolicy: RetryPolicy = {};
import { RetryPolicy } from "@langchain/langgraph"
const retryPolicy: RetryPolicy = {};
In [4]:
Copied!
import Database from "better-sqlite3"
import { ChatAnthropic } from "@langchain/anthropic"
import { MessagesAnnotation, StateGraph, START, END } from "@langchain/langgraph"
import { AIMessage } from "@langchain/core/messages"
// Create an in-memory database
const db: typeof Database.prototype = new Database(':memory:');
const model = new ChatAnthropic({ model: "claude-3-5-sonnet-20240620" });
const callModel = async (state: typeof MessagesAnnotation.State) => {
const response = await model.invoke(state.messages);
return { messages: [response] };
}
const queryDatabase = async (state: typeof MessagesAnnotation.State) => {
const queryResult: string = JSON.stringify(db.prepare("SELECT * FROM Artist LIMIT 10;").all());
return { messages: [new AIMessage({content: "queryResult"})]};
};
const workflow = new StateGraph(MessagesAnnotation)
// Define the two nodes we will cycle between
.addNode("call_model", callModel, { retryPolicy: {maxAttempts: 5}})
.addNode("query_database", queryDatabase, { retryPolicy: { retryOn: (e: any): boolean => {
if (e instanceof Database.SqliteError) {
// Retry on "SQLITE_BUSY" error
return e.code === 'SQLITE_BUSY';
}
return false; // Don't retry on other errors
}}})
.addEdge(START, "call_model")
.addEdge("call_model", "query_database")
.addEdge("query_database", END);
const graph = workflow.compile();
import Database from "better-sqlite3"
import { ChatAnthropic } from "@langchain/anthropic"
import { MessagesAnnotation, StateGraph, START, END } from "@langchain/langgraph"
import { AIMessage } from "@langchain/core/messages"
// Create an in-memory database
const db: typeof Database.prototype = new Database(':memory:');
const model = new ChatAnthropic({ model: "claude-3-5-sonnet-20240620" });
const callModel = async (state: typeof MessagesAnnotation.State) => {
const response = await model.invoke(state.messages);
return { messages: [response] };
}
const queryDatabase = async (state: typeof MessagesAnnotation.State) => {
const queryResult: string = JSON.stringify(db.prepare("SELECT * FROM Artist LIMIT 10;").all());
return { messages: [new AIMessage({content: "queryResult"})]};
};
const workflow = new StateGraph(MessagesAnnotation)
// Define the two nodes we will cycle between
.addNode("call_model", callModel, { retryPolicy: {maxAttempts: 5}})
.addNode("query_database", queryDatabase, { retryPolicy: { retryOn: (e: any): boolean => {
if (e instanceof Database.SqliteError) {
// Retry on "SQLITE_BUSY" error
return e.code === 'SQLITE_BUSY';
}
return false; // Don't retry on other errors
}}})
.addEdge(START, "call_model")
.addEdge("call_model", "query_database")
.addEdge("query_database", END);
const graph = workflow.compile();