LangChain Integration

The @shade402/langchain package provides a LangChain tool that enables AI agents to make X402 payments for API access.

Installation

pnpm add @shade402/langchain @shade402/client @shade402/core @langchain/core langchain

Quick Start

import { createX402PaymentTool } from '@shade402/langchain';
import { ChatOpenAI } from '@langchain/openai';
import { AgentExecutor, createOpenAIFunctionsAgent } from 'langchain/agents';
import { Keypair } from '@solana/web3.js';

// Create wallet
const wallet = Keypair.generate();

// Create payment tool
const paymentTool = createX402PaymentTool({
  walletKeypair: wallet,
  rpcUrl: process.env.SOLANA_RPC_URL,
  maxPayment: '1.0',
});

// Create agent
const llm = new ChatOpenAI({ temperature: 0 });
const tools = [paymentTool];
const agent = await createOpenAIFunctionsAgent({ llm, tools, prompt: myPrompt });
const executor = new AgentExecutor({ agent, tools });

// Use agent
const result = await executor.invoke({
  input: 'Fetch data from https://api.example.com/premium-data',
});

Tool Configuration

Using createX402PaymentTool

const paymentTool = createX402PaymentTool({
  walletKeypair: wallet,           // Required: Wallet for payments
  rpcUrl: 'https://api.devnet.solana.com', // Optional: Solana RPC URL
  maxPayment: '1.0',               // Optional: Max payment (default: '1.0')
  name: 'x402_payment',            // Optional: Tool name
  description: 'Custom description', // Optional: Tool description
  allowLocal: false,               // Optional: Allow localhost (dev only)
});

Using X402PaymentTool Class

import { X402PaymentTool } from '@shade402/langchain';

const paymentTool = new X402PaymentTool({
  walletKeypair: wallet,
  rpcUrl: process.env.SOLANA_RPC_URL,
  maxPayment: '1.0',
  name: 'x402_payment',
  description: 'Make X402 payment for API access',
});

Tool Schema

The tool accepts the following parameters:

{
  url: string;        // Required: API endpoint URL
  method?: string;    // Optional: HTTP method (default: 'GET')
}

Tool Behavior

When the agent calls the tool:

  1. Makes HTTP request to the URL

  2. If 402 response received:

    • Parses payment request

    • Creates Solana payment transaction

    • Broadcasts transaction

    • Retries request with payment authorization

  3. Returns API response as string

Error Handling

The tool handles errors gracefully:

  • Payment errors: Returns error message with code

  • Network errors: Returns error message

  • Validation errors: Returns error message

Errors are returned as strings, allowing the agent to handle them:

// Agent receives error message
const result = await executor.invoke({
  input: 'Fetch from https://api.example.com/data',
});

// Result might be:
// "Payment error: INSUFFICIENT_FUNDS - Wallet has insufficient token balance"

Complete Example

import { createX402PaymentTool } from '@shade402/langchain';
import { ChatOpenAI } from '@langchain/openai';
import { AgentExecutor, createOpenAIFunctionsAgent } from 'langchain/agents';
import { ChatPromptTemplate, MessagesPlaceholder } from '@langchain/core/prompts';
import { Keypair } from '@solana/web3.js';

// Load wallet
const wallet = Keypair.fromSecretKey(
  Buffer.from(process.env.WALLET_SECRET_KEY!, 'base64')
);

// Create payment tool
const paymentTool = createX402PaymentTool({
  walletKeypair: wallet,
  rpcUrl: process.env.SOLANA_RPC_URL,
  maxPayment: '1.0',
  name: 'x402_payment',
  description: 'Make an X402 payment to access a paid API endpoint. Input should be a URL to the API endpoint. Returns the API response after successful payment.',
});

// Create prompt
const prompt = ChatPromptTemplate.fromMessages([
  ['system', 'You are a helpful assistant that can make payments for API access.'],
  ['human', '{input}'],
  new MessagesPlaceholder('agent_scratchpad'),
]);

// Create agent
const llm = new ChatOpenAI({ temperature: 0, modelName: 'gpt-4' });
const tools = [paymentTool];

const agent = await createOpenAIFunctionsAgent({
  llm,
  tools,
  prompt,
});

const executor = new AgentExecutor({
  agent,
  tools,
  verbose: true,
  maxIterations: 5,
});

// Use agent
const result = await executor.invoke({
  input: 'Fetch premium data from https://api.example.com/premium-data and summarize it',
});

console.log(result.output);

Multiple Payment Tools

You can create multiple payment tools with different configurations:

// Low-cost tool
const lowCostTool = createX402PaymentTool({
  walletKeypair: wallet,
  maxPayment: '0.1',
  name: 'x402_payment_low',
  description: 'Make low-cost X402 payment (max 0.1 tokens)',
});

// High-cost tool
const highCostTool = createX402PaymentTool({
  walletKeypair: wallet,
  maxPayment: '10.0',
  name: 'x402_payment_high',
  description: 'Make high-cost X402 payment (max 10 tokens)',
});

const tools = [lowCostTool, highCostTool];

Custom Tool Description

Provide a clear description to help the agent understand when to use the tool:

const paymentTool = createX402PaymentTool({
  walletKeypair: wallet,
  maxPayment: '1.0',
  description: `Make an X402 payment to access a paid API endpoint.
    
    Use this tool when:
    - You need to access a paid API endpoint
    - The API requires payment via X402 protocol
    - You want to fetch data from a monetized API
    
    Input: URL to the API endpoint
    Returns: API response after successful payment`,
});

Production Considerations

Wallet Management

// Load wallet securely
const wallet = Keypair.fromSecretKey(
  Buffer.from(process.env.WALLET_SECRET_KEY!, 'base64')
);

// Or use a key management service
const wallet = await loadWalletFromKMS();

Error Monitoring

const executor = new AgentExecutor({
  agent,
  tools,
  returnIntermediateSteps: true,
});

const result = await executor.invoke({
  input: 'Fetch data from API',
});

// Check for payment errors
if (result.intermediateSteps) {
  for (const step of result.intermediateSteps) {
    if (step.action.tool === 'x402_payment') {
      if (step.observation.includes('Payment error')) {
        // Log payment error
        console.error('Payment error:', step.observation);
      }
    }
  }
}

Rate Limiting

Consider implementing rate limiting for payment tools:

let paymentCount = 0;
const MAX_PAYMENTS_PER_HOUR = 100;

const paymentTool = createX402PaymentTool({
  walletKeypair: wallet,
  maxPayment: '1.0',
});

// Wrap tool to add rate limiting
const rateLimitedTool = {
  ...paymentTool,
  invoke: async (input: any) => {
    if (paymentCount >= MAX_PAYMENTS_PER_HOUR) {
      return 'Rate limit exceeded. Too many payments this hour.';
    }
    paymentCount++;
    return paymentTool.invoke(input);
  },
};

Best Practices

  1. Set appropriate maximum payment amounts

  2. Provide clear tool descriptions

  3. Monitor payment usage and costs

  4. Handle errors gracefully

  5. Use secure wallet storage

  6. Test with devnet before production

  7. Log payment transactions

  8. Consider rate limiting

  9. Use separate wallets for different agents if needed

  10. Monitor agent behavior and payment patterns

Next Steps

Last updated