Python · LangChain · OpenAI Agents

Safety checks for Python agents that pay

fizzl gives a Python agent four checks to run before it signs or pays, as plain functions and as LangChain tools and as OpenAI Agents SDK tools (StructuredTool works in LangGraph, CrewAI and other frameworks that take LangChain tools too). The checks only check: they never sign, pay or move anything themselves.

Listed in the LangChain docs ↗ — Fizzl is listed in the LangChain docs under tools.

Install

pip install "fizzl[langchain]"         # LangChain tools
pip install "fizzl[openai-agents]"     # OpenAI Agents SDK tools (Python 3.10+)
pip install "fizzl[langchain,x402]"    # plus the x402 client, to pay for the full checks

Try it without a wallet

With no payment set up, the token, signing and endpoint checks answer with the free quick check: the verdict only, a few per hour, marked "free": True.

from langchain.agents import create_agent
from fizzl.langchain import fizzl_tools

agent = create_agent(
    "anthropic:claude-sonnet-5-5",
    tools=fizzl_tools(),
    system_prompt="Before you pay any API, call check_endpoint_before_paying. "
                  "Before you sign anything, call check_before_signing. Never continue on red or no_go.",
)
result = agent.invoke({"messages": [{"role": "user", "content":
    "Is USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) on Base safe to buy?"}]})
print(result["messages"][-1].content)

Or call a check directly:

from fizzl import Fizzl

Fizzl().check_token("base", "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913")
# {'verdict': 'green', 'grade': 'SAFE', 'free': True, 'note': 'Free quick check: ...'}

OpenAI Agents SDK

from agents import Agent, Runner
from fizzl.openai_agents import fizzl_tools

agent = Agent(
    name="buyer",
    tools=fizzl_tools(),   # free quick checks; pass session=... or credit_keys=... for the full ones
    instructions="Before you pay any API, call check_endpoint_before_paying. "
                 "Before you sign anything, call check_before_signing. Never continue on red or no_go.",
)
print(Runner.run_sync(agent, "Is https://ichimoku-signal.fizzl.eu/signal/BTC-USDT safe to pay?").final_output)

The checks run in a worker thread, so the agent's event loop isn't blocked. Bad arguments from the model come back as {"error": "bad_input"} without calling, or paying for, the check.

The tools

ToolWhat it checksFull checkFree quick check
check_before_signingA transaction, token approval or signature (permit, Permit2, Seaport) before signing: drainers, unlimited approvals, look-alike dapps. Green / orange / red with reasons.$0.01verdict only
check_tokenA token before buying, holding or accepting it: honeypots, rug-pull signs, look-alikes. Solana and EVM chains.$0.01verdict and grade
check_wallet_approvalsEvery open token approval of an EVM wallet, and which ones to revoke.$0.02none
check_endpoint_before_payingAn x402 or MPP paid API before paying it: go / caution / no_go, the cheapest option that settles, budget, track record, bait signs.$0.001go / caution / no_go with the problems found

Pick some with fizzl_tools(only=["check_endpoint_before_paying"]). A failed check comes back as {"error": ..., "message": ...} instead of raising, so the model can tell its user.

The full checks: pay per call over x402

Wrap a requests session with the x402 client. The agent pays each check in USDC on Base from its own wallet.

import requests
from eth_account import Account
from x402 import x402ClientSync
from x402.http.clients import wrapRequestsWithPayment
from x402.mechanisms.evm.exact import ExactEvmScheme
from fizzl.langchain import fizzl_tools

payer = x402ClientSync().register("eip155:8453", ExactEvmScheme(Account.from_key(AGENT_KEY)))
session = wrapRequestsWithPayment(requests.Session(), payer)
tools = fizzl_tools(session=session)

Or prepaid credits

Buy a pack once (presign-guard: 100 checks for $0.80; x402 Doctor: 1000 preflights for $0.80), then pass the keys:

tools = fizzl_tools(credit_keys={"presign": PRESIGN_CREDIT_KEY, "doctor": DOCTOR_CREDIT_KEY})

Options

OptionDefault
sessiona plain requests.SessionAnything with request(method, url, **kw); wrap it with x402 to pay per check
credit_keysnone{"presign": ..., "doctor": ...}, sent as x-credit-key
onlyall fourTool names to include
freeTrueFall back to the free quick check when a check can't be paid
timeout30Seconds per check

More