@x402fly/langgraph
v0.1.2
Published
LangGraph.js integration for 402fly payment protocol
Maintainers
Readme
@402fly/langgraph
LangGraph.js integration for the X402 payment protocol, enabling complex AI agent workflows with autonomous payment capabilities.
Overview
This package provides LangGraph nodes and utilities for building stateful AI agent workflows that can autonomously handle X402 payments. It includes pre-built nodes for payment handling, conditional routing based on payment status, and seamless integration with LangGraph state machines.
Features
- Payment Nodes: Pre-built nodes for payment processing and resource fetching
- Conditional Routing: Built-in functions for payment-based workflow routing
- State Management: Full integration with LangGraph's state management
- Automatic Payment: Nodes automatically handle payment when encountering 402 responses
- Workflow Composition: Easily compose complex payment workflows
Installation
npm install @402fly/langgraph
# or
pnpm add @402fly/langgraph
# or
yarn add @402fly/langgraphUsage
Basic Payment Workflow
import { StateGraph } from '@langchain/langgraph';
import {
paymentNode,
fetchWithPaymentNode,
checkPaymentRequired,
checkPaymentCompleted,
PaymentState
} from '@402fly/langgraph';
import { Keypair } from '@solana/web3.js';
// Define your graph state
interface AgentState extends PaymentState {
url: string;
data?: any;
error?: string;
}
// Load wallet
const walletKeypair = Keypair.fromSecretKey(secretKeyBytes);
// Create workflow
const workflow = new StateGraph<AgentState>({
channels: {
url: null,
data: null,
error: null,
paymentRequired: null,
paymentRequest: null,
paymentCompleted: null
}
});
// Add nodes
workflow.addNode('fetch', fetchWithPaymentNode(walletKeypair));
workflow.addNode('process', processDataNode);
// Add edges with conditions
workflow.addEdge('__start__', 'fetch');
workflow.addConditionalEdges(
'fetch',
checkPaymentCompleted,
{
completed: 'process',
failed: '__end__'
}
);
workflow.addEdge('process', '__end__');
// Compile and run
const app = workflow.compile();
const result = await app.invoke({
url: 'https://api.example.com/premium-data'
});
console.log(result.data);Manual Payment Flow
import {
StateGraph,
END
} from '@langchain/langgraph';
import {
paymentNode,
checkPaymentRequired,
PaymentState
} from '@402fly/langgraph';
import { Keypair } from '@solana/web3.js';
interface AgentState extends PaymentState {
url: string;
response?: any;
}
const walletKeypair = Keypair.fromSecretKey(secretKeyBytes);
const workflow = new StateGraph<AgentState>({
channels: {
url: null,
response: null,
paymentRequired: null,
paymentRequest: null,
paymentCompleted: null
}
});
// Custom fetch node
async function fetchNode(state: AgentState) {
const response = await fetch(state.url);
if (response.status === 402) {
const paymentRequest = await response.json();
return {
paymentRequired: true,
paymentRequest
};
}
return {
response: await response.json(),
paymentRequired: false
};
}
// Add nodes
workflow.addNode('fetch', fetchNode);
workflow.addNode('pay', paymentNode(walletKeypair));
workflow.addNode('retry', fetchNode);
// Add routing
workflow.addEdge('__start__', 'fetch');
workflow.addConditionalEdges(
'fetch',
checkPaymentRequired,
{
required: 'pay',
not_required: END
}
);
workflow.addEdge('pay', 'retry');
workflow.addEdge('retry', END);
const app = workflow.compile();
const result = await app.invoke({
url: 'https://api.example.com/data'
});Multi-Step Workflow with Payments
import { StateGraph } from '@langchain/langgraph';
import {
fetchWithPaymentNode,
checkPaymentCompleted,
PaymentState
} from '@402fly/langgraph';
import { Keypair } from '@solana/web3.js';
interface MultiStepState extends PaymentState {
step: number;
urls: string[];
results: any[];
}
const walletKeypair = Keypair.fromSecretKey(secretKeyBytes);
const workflow = new StateGraph<MultiStepState>({
channels: {
step: null,
urls: null,
results: null,
paymentRequired: null,
paymentRequest: null,
paymentCompleted: null
}
});
// Fetch current URL
async function fetchCurrentUrl(state: MultiStepState) {
const currentUrl = state.urls[state.step];
const client = new Fly402AutoClient(walletKeypair);
try {
const response = await client.fetch(currentUrl);
return {
results: [...state.results, response.data],
paymentCompleted: true
};
} catch (error) {
return {
paymentCompleted: false,
error: error.message
};
} finally {
await client.close();
}
}
// Check if more URLs to process
function shouldContinue(state: MultiStepState) {
return state.step < state.urls.length - 1 ? 'next' : 'done';
}
// Increment step
function nextStep(state: MultiStepState) {
return { step: state.step + 1 };
}
workflow.addNode('fetch', fetchCurrentUrl);
workflow.addNode('next', nextStep);
workflow.addEdge('__start__', 'fetch');
workflow.addConditionalEdges('fetch', shouldContinue, {
next: 'next',
done: '__end__'
});
workflow.addEdge('next', 'fetch');
const app = workflow.compile();
const result = await app.invoke({
step: 0,
urls: [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3'
],
results: []
});
console.log(result.results); // All fetched dataAPI Reference
State Interface
PaymentState
Base state interface for payment workflows:
interface PaymentState {
paymentRequired?: boolean;
paymentRequest?: any;
paymentCompleted?: boolean;
error?: string;
}Nodes
paymentNode(walletKeypair: Keypair, rpcUrl?: string)
Node that processes a payment based on paymentRequest in state.
Returns updated state with paymentCompleted status.
fetchWithPaymentNode(walletKeypair: Keypair, rpcUrl?: string, options?)
Node that fetches a URL from state and automatically handles payments.
Expects state to have a url field.
Options:
{
maxRetries?: number;
autoRetry?: boolean;
maxPaymentAmount?: string;
}Conditional Functions
checkPaymentRequired(state: PaymentState)
Returns routing key based on payment requirement status:
'required'if payment is required'not_required'if payment is not required
checkPaymentCompleted(state: PaymentState)
Returns routing key based on payment completion status:
'completed'if payment completed successfully'failed'if payment failed or not completed
Re-exports
Fly402AutoClient- Re-exported from@402fly/clientfor convenience
Advanced Examples
Error Handling
import { StateGraph } from '@langchain/langgraph';
import { fetchWithPaymentNode, PaymentState } from '@402fly/langgraph';
interface ErrorHandlingState extends PaymentState {
url: string;
retryCount: number;
maxRetries: number;
}
function checkRetry(state: ErrorHandlingState) {
if (state.paymentCompleted) {
return 'success';
}
if (state.retryCount < state.maxRetries) {
return 'retry';
}
return 'failed';
}
const workflow = new StateGraph<ErrorHandlingState>({...});
workflow.addNode('fetch', fetchWithPaymentNode(walletKeypair));
workflow.addNode('incrementRetry', (state) => ({
retryCount: state.retryCount + 1
}));
workflow.addConditionalEdges('fetch', checkRetry, {
success: '__end__',
retry: 'incrementRetry',
failed: '__end__'
});
workflow.addEdge('incrementRetry', 'fetch');Documentation
For complete API documentation and guides, visit 402fly.github.io
Testing
pnpm testContributing
See CONTRIBUTING.md
License
MIT - See LICENSE
