> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meterlane.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Meterlane x402 Payments with LangChain Agent Tools

> Wrap a Meterlane gateway route as a LangChain DynamicStructuredTool so your agent automatically pays x402 APIs with USDC on Base Sepolia.

LangChain's `DynamicStructuredTool` lets you expose any HTTP endpoint as a callable tool inside an agent graph. By combining it with `createAgentClient` from `@meterlane/x402/client`, your agent handles x402 payment negotiation invisibly — it sends a request, receives **402** if unpaid, signs an ERC-3009 USDC authorization, and retries with the payment header, all before returning a result to the model.

<Note>
  All examples on this page target **Base Sepolia** (`eip155:84532`) and the public sandbox demo route. Do not use mainnet keys or mainnet URLs in development or CI.
</Note>

<Steps>
  <Step title="Install dependencies">
    You need `@langchain/core` for the tool primitive, `zod` for the parameter schema, and `@meterlane/x402` for the payment client.

    <CodeGroup>
      ```bash npm theme={null}
      npm add @meterlane/x402 @langchain/core zod
      ```

      ```bash yarn theme={null}
      yarn add @meterlane/x402 @langchain/core zod
      ```

      ```bash pnpm theme={null}
      pnpm add @meterlane/x402 @langchain/core zod
      ```
    </CodeGroup>

    Import the MIT-licensed client entry point specifically — not the server middleware:

    ```typescript theme={null}
    import { createAgentClient } from "@meterlane/x402/client";
    ```
  </Step>

  <Step title="Set your environment variable">
    <Warning>
      Never hard-code your private key in source files or commit it to version control. Store it in an environment variable and load it at runtime. Use a dedicated hot wallet funded only with the USDC you need for testing — do not reuse cold-storage or exchange keys.
    </Warning>

    Create a `.env` file (and add it to `.gitignore`):

    ```bash theme={null}
    AGENT_PRIVATE_KEY=0xYOUR_BASE_SEPOLIA_PRIVATE_KEY
    ```

    Get test USDC for Base Sepolia from the [Circle faucet](https://faucet.circle.com) — select **Base Sepolia** before requesting.
  </Step>

  <Step title="Build the tool">
    Save the following as `langchain-meterlane-tool.ts`. The tool calls the public sandbox demo route, but you can replace the URL with any active Meterlane gateway route.

    ```typescript theme={null}
    import { DynamicStructuredTool } from "@langchain/core/tools";
    import { z } from "zod";
    import type { Hex } from "viem";
    import { createAgentClient } from "@meterlane/x402/client";

    const privateKey = process.env.AGENT_PRIVATE_KEY as Hex | undefined;
    if (!privateKey?.startsWith("0x")) {
      throw new Error("Set AGENT_PRIVATE_KEY to a 0x-prefixed Base Sepolia funded key");
    }

    // paidFetch is a drop-in replacement for fetch that handles 402 automatically
    const paidFetch = createAgentClient(privateKey, "eip155:84532");

    const gatewayBase =
      process.env.GATEWAY_URL ?? "https://gateway.meterlane.app";
    const orgSlug = process.env.ORG_SLUG ?? "demo";

    export const meterlanePaidGetTool = new DynamicStructuredTool({
      name: "meterlane_paid_http_get",
      description:
        "GET an x402-protected Meterlane gateway route. Signs and pays on HTTP 402 using USDC on Base Sepolia.",
      schema: z.object({
        path: z
          .string()
          .describe("Route path under /gateway/:orgSlug, e.g. /demo"),
      }),
      func: async ({ path }) => {
        const normalized = path.startsWith("/") ? path : `/${path}`;
        const url = `${gatewayBase}/gateway/${orgSlug}${normalized}`;

        const res = await paidFetch(url, { method: "GET" });
        const body = await res.text();

        if (!res.ok) {
          throw new Error(`HTTP ${res.status}: ${body.slice(0, 500)}`);
        }

        return body;
      },
    });

    // Standalone smoke test — runs without a model
    async function main() {
      const result = await meterlanePaidGetTool.invoke({ path: "/demo" });
      console.log("Paid response (first 200 chars):", result.slice(0, 200));
    }

    main().catch((err) => {
      console.error(err);
      process.exit(1);
    });
    ```

    Run the smoke test directly:

    ```bash theme={null}
    AGENT_PRIVATE_KEY=0xYOUR_KEY npx tsx langchain-meterlane-tool.ts
    ```

    You should see the first 200 characters of the demo route's **200** response body.
  </Step>

  <Step title="Register the tool with your agent">
    Wire `meterlanePaidGetTool` into your agent the same way you would any other LangChain tool — via `bindTools`, a ReAct executor, or a LangGraph tool node:

    ```typescript theme={null}
    import { ChatOpenAI } from "@langchain/openai";
    import { createReactAgent } from "@langchain/langgraph/prebuilt";
    import { meterlanePaidGetTool } from "./langchain-meterlane-tool";

    const model = new ChatOpenAI({ model: "gpt-4o-mini" });

    const agent = createReactAgent({
      llm: model,
      tools: [meterlanePaidGetTool],
    });

    const result = await agent.invoke({
      messages: [
        {
          role: "user",
          content: "Fetch the Meterlane demo route at /demo and summarize the response.",
        },
      ],
    });

    console.log(result.messages.at(-1)?.content);
    ```

    The agent decides when to call the tool; `createAgentClient` handles the 402 → pay → retry cycle transparently each time.
  </Step>
</Steps>

## How it works

When your tool calls `paidFetch(url)` instead of raw `fetch`, the following happens automatically:

1. The client sends the original `GET` request.
2. If the server returns **402**, it reads the `X-Payment-Requirements` header for the USDC amount and receiver address.
3. `ExactEvmScheme` uses your private key to produce an ERC-3009 signed authorization on Base Sepolia.
4. The client retries the request with the payment authorization header attached.
5. On **200**, your tool function receives the response body and returns it to the model.

The MIT license on `@meterlane/x402/client` means you can — and should — audit the payment logic before running it with a funded wallet.
