Skip to content

A CrewAI agent that buys the data it needs.

A CrewAI tool that calls a paid endpoint on gateway.apiosk.com. The 402 is answered inside the tool body, so the agent asks a question and gets JSON back. No API key, no account.

pip install crewai "x402[requests,evm]"

What you are about to do

The whole integration is one tool definition and one wallet key. Everything specific to CrewAI is below; everything specific to payment happens inside the client.

Install crewai and the x402 requests client

01

pip install crewai "x402[requests,evm]". Custom tools ship inside crewai itself, so you do not need the [tools] extra. That one only pulls the prebuilt crewai_tools catalog. The evm extra brings eth-account and web3 with it. CrewAI needs Python 3.10 or newer.

Define the tool with @tool from crewai.tools

02

Build one paying requests.Session at module level, then decorate a plain function with @tool. CrewAI turns the type annotations and the docstring into the schema the model reads, so both are required. It raises ValueError without them. Reach for BaseTool with args_schema when you want to write the argument descriptions yourself.

Hand it to the Agent and kick off the Crew

03

Pass the decorated function into Agent(tools=[...]), give the Task an expected_output, then call Crew(agents=[...], tasks=[...]).kickoff(). The Agent's own llm defaults to gpt-4.1-mini, so set OPENAI_API_KEY or pass llm=. kickoff returns a CrewOutput; result.raw is the answer.

CrewAI, end to end

Copy these in order. The endpoints are placeholders. Swap in any endpoint from the catalog.

tools/convert_currency.pyPython
# tools/convert_currency.py
# pip install crewai "x402[requests,evm]"

import os

from crewai.tools import tool
from eth_account import Account
from x402 import x402ClientSync
from x402.http.clients.requests import x402_requests
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client

# The x402 client only signs payments. x402_requests turns it into a plain
# requests.Session that answers the 402 and retries the call. Build it once at
# import time; every tool below reuses it.
account = Account.from_key(os.environ["WALLET_PRIVATE_KEY"])
payments = x402ClientSync()
register_exact_evm_client(payments, EthAccountSigner(account))
session = x402_requests(payments)


@tool("Convert currency")
def convert_currency(from_code: str, to_code: str, amount: float) -> dict:
    """Convert an amount between two currencies using live FX rates.

    Paid per call in USDC on Base. No API key required.
    """
    response = session.get(
        "https://gateway.apiosk.com/v1/fx/convert",
        params={"from": from_code, "to": to_code, "amount": amount},
    )
    response.raise_for_status()
    return response.json()
tools/verify_email.pyPython
# tools/verify_email.py
# The subclass form. Use it when you want to name and describe the arguments
# yourself instead of letting CrewAI read them off the signature.

from crewai.tools import BaseTool
from pydantic import BaseModel, Field

from tools.convert_currency import session  # one paying session for every tool


class VerifyEmailInput(BaseModel):
    email: str = Field(description="Address to check, e.g. ada@example.com")


class VerifyEmailTool(BaseTool):
    name: str = "Verify email"
    description: str = (
        "Check whether an email address is deliverable. "
        "Returns the verdict and the reason for it."
    )
    args_schema: type[BaseModel] = VerifyEmailInput

    def _run(self, email: str) -> dict:
        response = session.get(
            "https://gateway.apiosk.com/v1/email/verify",
            params={"email": email},
        )
        response.raise_for_status()
        return response.json()
crew.pyPython
# crew.py
# Run with: python crew.py

from crewai import Agent, Crew, Task

from tools.convert_currency import convert_currency
from tools.verify_email import VerifyEmailTool

# @tool returns a Tool, which is a BaseTool, so both forms go in the same list.
analyst = Agent(
    role="Operations analyst",
    goal="Answer questions that need live data",
    backstory="You check numbers with a source before you report them.",
    tools=[convert_currency, VerifyEmailTool()],
    verbose=True,
)

task = Task(
    description="What is 250 EUR in USD right now?",
    expected_output="The converted amount and the rate used.",
    agent=analyst,
)

result = Crew(agents=[analyst], tasks=[task]).kickoff()
print(result.raw)  # kickoff returns a CrewOutput; .raw is the string answer

Three things to know

The key stays out of the crew

WALLET_PRIVATE_KEY is read once when the tool module imports, and the session is closed over by the function body. It never enters an Agent, a Task description or a tool argument, so it cannot reach the model's context or the crew log.

Sync tools, sync client

CrewAI executes a tool body synchronously, so pair x402ClientSync with x402_requests. The async pair, x402Client with httpx, raises TypeError here. x402_requests hands back an ordinary requests.Session, so params=, raise_for_status() and `with` all behave as usual.

The agent sees one tool call

The 402, the signature and the retry all happen inside session.get. The tool returns the JSON body and nothing else, so with verbose=True the crew log shows a single tool call rather than two requests. The settled call leaves an on-chain receipt on Base.

Good questions.

A few things to know before you start.

How pricing works
What is Apiosk?

Apiosk helps people and AI agents get data from paid APIs. Describe what you need, review the proposed service or research plan and its price, then approve the work. Apiosk handles the calls and returns the available results with their sources.

What is the difference between Answer and Research?

Answer helps with a direct data request, such as a company profile or filed accounts. Research creates a plan for requests that need several steps. It can resolve a company first and use that identity to retrieve its records. The plan shows what it can cover before you approve.

What if my question is unclear or data is missing?

Apiosk asks for context when it needs a company, location, period or other detail. If a provider does not have the requested data, the result should say what is missing. Data availability depends on the source; an API listing does not guarantee that every record exists.

How much does it cost?

The price depends on the services your request needs. Apiosk shows the total, including its service fee, before you approve. You pay per use from your balance, with no subscription required.

See pricing
Do I need to know how APIs work?

No. In the Apiosk app, you ask in ordinary language and approve the price. You do not need a separate API key or account for each provider. Developers can also connect through MCP or API.

Can I use Apiosk inside ChatGPT or Claude?

Yes. Apiosk is available as a connector for ChatGPT and Claude, and through MCP for other agents and tools. Connect once, sign in to Apiosk, and ask your question from there. The price is shown before anything runs and is paid from your Apiosk balance.

Connect an agent
Can my AI agent use Apiosk?

Yes. Connect a compatible agent through MCP or API and authorize its access to your Apiosk account. Spending limits and approval rules control what it can buy.

Connect an agent