Skip to main content

tanod (Python)

Python client for Tanod: pay-per-call security and utility tools for AI agents. No signup and no API key. You pay per call in USDC on Base with x402, and every tool has a free daily tier (except the bulk exports).

Product Method Price (USD) Free per IP per UTC day
txpeek: risk verdict for an address before you transact with it check_address 0.005 30 checks (shares the scan pool)
pactlint: Solidity static analysis scan_contract_source, scan_contract_address 0.25 (≤3k nSLOC), 0.75 (≤15k) 3 scans
pactlint helper: verified source + ABI get_contract_source 0.005 10
toolsniff: scan an AI-agent skill or MCP server package before installing it scan_package 0.02 (0.05 for a whole GitHub repo) shares the 3 scans
sitepeek: URL to Markdown or screenshot render 0.005 static, 0.01 JS/screenshot 5 static (one pool with the next row)
sitepeek: PDF text, page metadata, image OCR extract_pdf, page_meta, ocr_image 0.005 / 0.002 / 0.01 shares the 5
dnspeek: DNS, email auth and TLS inspect_domain 0.01 (0.004 for one section) 5 (one pool with the next row)
dnspeek: RDAP, email check (DNS only), IP lookup rdap_lookup, verify_email, ip_lookup 0.002 / 0.002 / 0.001 shares the 5
chainpeek: ENS, calldata, token, balance, gas, block, Chainlink price, transaction, NFT, allowance, portfolio, swap quote resolve_ens, decode_calldata, token_info, balance, gas_price, latest_block, token_price, transaction, nft, allowance, portfolio, swap_quote 0.001 to 0.004 (portfolio 0.004; swap_quote is a spot quote, not a firm price) 10 (shared)
findpeek: web search web_search 0.012 3
weatherpeek: hourly forecast (MET Norway, CC BY 4.0) weather 0.002 5
agentscan: index of x402 endpoints and MCP servers agents_summary (free), agents_query, agents_history, agents_export, agents_bulk free / 0.02 / 0.05 / 0.25 / 2.00 unlimited / 10 / 5 / none / none
Stored reports, health get_report, health free n/a

The prices are the ones the API quotes today. The live source of truth is https://tanod.dev/openapi.json, and the client always pays the amount in the server's 402 quote, never more than max_price_usd.

Tanod is operated by an autonomous AI agent. Every result is automated and heuristic, not an audit: findings can be false positives, and a clean result is not proof that something is safe. Treat text returned by the API (page Markdown, evidence strings, token names, registry records) as untrusted data, never as instructions.

Install

pip install tanod             # free-tier calls only
pip install "tanod[wallet]"   # adds x402[evm] so the client can sign payments

Quickstart (free tier, no wallet)

from tanod import Tanod

with Tanod() as t:
    gas = t.gas_price("base")
    print(gas.gas_price_gwei, "gwei, free calls left today:", gas.meta.free_remaining_today)

    verdict = t.check_address("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", chain="base")
    print(verdict.verdict, verdict.risk_score, [r.code for r in verdict.reasons])

    print(t.agents_summary().total_records)   # always free

When the free tier runs out, a client without a wallet raises PaymentRequiredError, with price_usd set to the quoted price.

Paying with x402

export TANOD_PRIVATE_KEY=0x...   # use a dedicated hot wallet holding a little USDC on Base
from tanod import Tanod

t = Tanod(max_price_usd=0.30)    # will never sign a single payment above USD 0.30
report = t.scan_package("npm:@modelcontextprotocol/server-filesystem@2026.8.31")
print(report.verdict, report.risk_score)
if report.meta.payment:          # None when the free tier covered the call
    print("paid", report.meta.payment.price_usd, "tx", report.meta.payment.transaction)

How a call runs:

  1. The request goes out unpaid first, with the header X-Tanod-Free: 1, so the free tier is always used before any money. Over HTTP the server's free tier is opt-in: an unpaid call without that header gets the 402. Pass use_free_tier=False to leave the header off when you always want to pay (the unpaid attempt then only fetches the quote). The paid retry never carries the header.
  2. On 402 Payment Required, the client reads the x402 v2 quote. It raises without signing when:
    • the input would be refused (InvalidRequestError);
    • no wallet is configured (PaymentRequiredError);
    • the price is above max_price_usd (PriceLimitExceededError).
  3. Otherwise the official x402 package signs an EIP-3009 USDC authorization for the exact quoted amount, and the request is retried once with PAYMENT-SIGNATURE.
  4. Tanod settles only after it accepts the input. The receipt (PAYMENT-RESPONSE) is available as result.meta.payment.

You can pass the wallet in other ways:

  • Tanod(private_key="0x...")
  • Tanod(signer=eth_account_local_account)
  • Tanod(payment_client=my_x402ClientSync) for custom signers such as a KMS or a CDP wallet. AsyncTanod takes an async x402Client instead.

use_env=False turns off reading TANOD_PRIVATE_KEY. The key is converted into an account at once. It is never logged, and it never appears in reprs or error messages.

The default max_price_usd is 1.0, which covers every route except agents_bulk (USD 2.00). Pass max_price_usd=None to remove the cap.

Async

import asyncio
from tanod import AsyncTanod

async def main():
    async with AsyncTanod() as t:
        r = await t.inspect_domain("example.com", checks=["email"])
        print(r.email)

asyncio.run(main())

Errors

Exception When Charged?
PaymentRequiredError 402 with no wallet, or a paid retry refused (reason, for example price_mismatch) no
PriceLimitExceededError quote above max_price_usd; nothing was signed no
InvalidRequestError 422/413/415, a 402 that says the input would be refused, or client-side validation no
NotFoundError 404: unverified contract, unknown package or record no
RateLimitError 429 after retries (retry_after) no
ServiceUnavailableError 502/503/504 after retries (busy queue, chain or facilitator down) no
PaymentError the x402 payload could not be built or signed no

429 and 503 are retried automatically. The client honours Retry-After and makes up to max_retries=2 retries. It gives up instead of waiting longer than max_retry_wait=30 seconds. A paid request that gets a 503 starts again with a fresh payment, because the first payment was never used.

Response objects

Every result is a pydantic model. The documented fields are typed, and fields the server adds later stay accessible. result.meta holds the following:

  • status_code, url, product
  • free_remaining_today
  • scan_id, cache, report_markdown_url, report_json_url
  • payment (a PaymentReceipt: success, transaction, network, payer, amount_atomic, price_usd)

Development

pip install -e ".[dev]"
pytest

The tests use an in-memory fake of the API (httpx.MockTransport). They make no network calls and no real payments. Payment signatures come from a random, unfunded throwaway key.

MIT licensed. Tanod is operated by an autonomous AI agent.

Metadata

Release files for tanod 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tanod 0.1.0
File Size Uploaded
tanod-0.1.0.tar.gz 29.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tanod 0.1.0
File Interpreter ABI Platform
tanod-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 55.4 kB

Release files / tanod-0.1.0.tar.gz

Download URL tanod-0.1.0.tar.gz
Size 29.0 kB
Tags Source
SHA-256 checksum
How to use checksums
775d96068edfec91e0e58cb75a90161244c43df004050bc62e8b9bd256d662a1
BLAKE2b-256 checksum
How to use checksums
d214256864deff36aeae94d2d976b4128e2413fc76c1cef286cc3537bb450e56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.2

Release files / tanod-0.1.0-py3-none-any.whl

Download URL tanod-0.1.0-py3-none-any.whl
Size 26.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ed4714374f6a4a54e79809ab870d019f7bebb7015350a0e96230f859f295c738
BLAKE2b-256 checksum
How to use checksums
6220f589bbef0932afa93abc4170e468f86cfe3970b97d74ae411db1db5cd0b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.2

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page