A LangChain tool that pays for its own call.
Wrap any endpoint on gateway.apiosk.com in a @tool your Python agent can call. The tool body makes one request; the 402, the USDC payment on Base and the retry all happen inside the session.
pip install "x402[requests,evm]" langchain-coreWhat you are about to do
The whole integration is one tool definition and one wallet key. Everything specific to LangChain is below; everything specific to payment happens inside the client.
Install x402 with the extras
pip install "x402[requests,evm]" langchain-core. The requests extra pulls in the sync HTTP path; the evm extra pulls in eth-account and web3, so x402[requests] alone fails at the Account import. Add langchain and langchain-anthropic when you wire up the agent.
Define the tool
Build the payment session once at module scope, then decorate a normal function with @tool. The body makes one request against gateway.apiosk.com; the 402, the signature and the retry happen inside session.get.
Hand it to create_agent
Pass the tool into create_agent alongside the model. From there the model decides when the job needs an FX rate or an email check, and the call is paid at the moment it is made.
LangChain, end to end
Copy these in order. The endpoints are placeholders — swap in any endpoint from the catalog.
Three things to know
The wallet stays in your process
The private key is read from the environment once, at import time, and lives in the module that builds the session. The agent never sees it and never handles a 402. From the model's side a paid call returns the same JSON any other tool would.
A sync tool needs the sync client
A @tool body is called synchronously, so use x402ClientSync with x402_requests. x402Client is the async client; the requests adapter raises TypeError if you hand it one. Build the session at module scope, not inside the tool, so a loop of calls reuses one connection pool.
The docstring is the tool spec
@tool(parse_docstring=True) parses a Google-style Args: block into per-argument descriptions, which is what the model reads when it fills in the call. One naming rule from langchain-core: do not call a tool argument config, run_manager, or callbacks. Those are reserved; take a ToolRuntime parameter if you need runtime access.
Frequently asked questions
Should I import tool from langchain.tools or langchain_core.tools?
Either. In LangChain v1 the slim langchain package re-exports tool straight from langchain_core.tools, so both imports give the identical decorator. The current docs write from langchain.tools import tool; the snippets here use langchain_core.tools so the tool file depends only on langchain-core, with no agent package required.
Do I need an API key or an account to call the endpoint from a tool?
No. gateway.apiosk.com replies 402 Payment Required with the price for that request. The session built by x402_requests signs a USDC payment on Base and retries, inside the same session.get call. There is no key to store, no account to register, and no invoice at the end of the month.
Does this work with an async agent?
Not as written. x402ClientSync and x402_requests are the sync pair, and a sync @tool body is what create_agent calls. For an async tool, install "x402[httpx,evm]" and build x402HttpxClient(x402Client()) instead, then define the tool with async def and await the request. Handing an async x402Client to the requests adapter raises TypeError at runtime.
Every listed API, on the same tool interface.
Agents call the comparison. Providers get into it.