Skip to main content

arc-agent-pay

CI PyPI Python 3.11+ License: MIT Chain: Arc Testnet

Python SDK for AI agents that autonomously pay for API services using USDC nanopayments on Arc via the x402 protocol.

An agent discovers paid APIs, hits a real HTTP 402, signs an EIP-3009 authorization off-chain, retries — and gets the data. Every payment settles as a real on-chain transferWithAuthorization transaction on Arc Testnet. No wallets to manage, no approval prompts, no pre-funded accounts in the hot path.

Live playground: agentpay.bond Docs: agentpay.bond/docs


Quick start

pip install arc-agent-pay
from arc_agent_pay import PaymentClient, ServiceRegistry
from arc_agent_pay.models import Chain
from eth_account import Account

registry = ServiceRegistry()
services = registry.search("crypto prices")

account = Account.from_key("0x" + private_key)

async with PaymentClient(account=account, budget_usdc="0.05", chain=Chain.ARC_TESTNET) as client:
    response = await client.get(services[0].url)   # 402 → pay → retry, all automatic
    data = response.json()
    print(client.summary())

That's the whole loop: PaymentClient wraps httpx, intercepts the 402 Payment Required, checks the BudgetGuard, signs an EIP-3009 transferWithAuthorization off-chain, retries with the X-PAYMENT header, and hands you the data plus the settlement tx hash.

Prerequisites: Python 3.11+, a funded Arc Testnet EOA wallet (see Wallets).


How it works

sequenceDiagram
    autonumber
    participant A as Agent<br/>(PaymentClient)
    participant R as ServiceRegistry
    participant S as x402 API Server
    participant C as Arc Testnet

    A->>R: search("USDC payments")
    R-->>A: Web Research API, Whale Tracker, Price Feed
    A->>S: GET /whales
    S-->>A: 402 Payment Required<br/>(price 0.010 USDC, pay_to)
    Note over A: BudgetGuard checks session spend limit
    Note over A: Sign EIP-3009 TransferWithAuthorization<br/>(off-chain — no gas, no chain call yet)
    A->>S: retry GET /whales + X-PAYMENT header
    S->>C: transferWithAuthorization(...)
    C-->>S: tx confirmed
    S-->>A: 200 OK + PAYMENT-RESPONSE header<br/>(tx hash)

Chain: Arc Testnet — chain ID 5042002 USDC: 0x3600000000000000000000000000000000000000 (native, EIP-3009 v2) Explorer: https://explorer.testnet.arc.network


Install

The core package (PaymentClient, ServiceRegistry, BudgetGuard) has minimal dependencies. Optional extras add heavier features — install only what you need:

Extra Adds Use when
[agent] langgraph, langchain-core, langchain-openai, openai Building the LangGraph tool-calling research agent
[llm] openai Just the LLM synthesis layer (provider-agnostic)
[rag] chromadb, fastembed Semantic (embedding-based) service discovery
[onchain] web3 ERC-8004 onchain agent identity + reputation
[observability] langfuse Trace agent runs (Langfuse; optional, no-op without keys)
[mcp] mcp Expose discovery + pay-and-fetch as an MCP server
[all] every extra above Trying out everything at once
pip install "arc-agent-pay[agent]"   # the paying research agent
pip install "arc-agent-pay[all]"     # every feature

import arc_agent_pay stays light regardless — heavy dependencies are lazy-imported by the modules that need them.


Architecture

arc_agent_pay/                  core SDK — minimal deps
  models.py        Service, Chain, PaymentRecord — core data types
  budget.py        BudgetGuard — session spend enforcement
  interceptor.py   PaymentClient — httpx wrapper, handles 402 → sign → retry
  registry/        service discovery
    __init__.py    ServiceRegistry — keyword/tag search (default)
    catalog.py     external HTTP service catalog sync + TTL cache
    semantic.py    SemanticServiceRegistry — embeddings + Chroma ([rag] extra)
  llm/             provider-agnostic LLM layer (OpenAI / ArcAPIs / template)
  identity/        ERC-8004 onchain agent identity + reputation ([onchain] extra)
  onchain/         verified ERC-8004 addresses + ABIs (Arc Testnet)
  observability/   Langfuse tracing (no-op fallback) + offline eval harness
  mcp_server/      Model Context Protocol server ([mcp] extra)
  agent/           ResearchAgent
    graph.py       real LangGraph tool-calling agent (the [agent] extra)
    linear.py      dependency-light plan → fetch → synthesize fallback
    trust.py       ReputationGate — reputation-gated spending policy

The research agent

ResearchAgent runs the full loop — discover → pay → fetch → synthesize — behind one interface, with two execution paths: a real LangGraph tool-calling agent (the LLM decides which services to discover and pay for) when the [agent] extra and an LLM key are present, and a dependency-light linear pipeline otherwise (runs with zero API keys, template-mode synthesis).

from arc_agent_pay.agent import ResearchAgent

agent = ResearchAgent(private_key=key, budget_usdc="0.10")
report = await agent.run("USDC payments on Arc network")

Scope: what the agent can answer

The agent is not hardcoded to any subject. The loop is topic-agnostic; the agent is only as broad as the catalog of services it can reach. Point ARC_REGISTRY_CATALOG_URL at an external catalog and the registry syncs + caches it on startup (builtins become a fallback). The architecture consumes any x402-priced service through the same Discovery protocol and PaymentClient — the constraint is purely which services settle on the chain this agent pays on. As Arc-settling x402 services appear, they become reachable here with no code change.

Spending controls

An agent that spends on its own needs guardrails, all enforced before any payment is signed:

  • BudgetGuard — hard per-session budget cap; once hit, further payments are blocked.
  • ReputationGate (agent/trust.py) — with a trust policy set, the agent reads a provider's on-chain ERC-8004 reputation and refuses to pay anyone below the floor. Off by default, fail-open; strict mode via require_provider_identity.
  • Allowlist / denylist by provider agent id, and a kill switch (payments_disabled) to stop all spending instantly.
agent = ResearchAgent(
    private_key=key,
    budget_usdc="0.10",
    min_provider_reputation=3.0,      # refuse providers rated below 3.0
    provider_denylist=[999000001],    # never pay this provider
)

Wallets

The agent needs one funded Arc Testnet EOA (the payer):

python -c "from eth_account import Account; import secrets; a = Account.from_key('0x'+secrets.token_hex(32)); print('key:', a.key.hex()); print('addr:', a.address)"

Fund from a Circle wallet:

circle wallet transfer <ADDRESS> --amount 5 --address 0x40a2f3926fb79b91b8012c8f1dc3a1c6e4ded2cc --chain ARC-TESTNET --testnet

Use dedicated, low-balance testnet keys. Never reuse a key that holds mainnet funds.


Onchain agent identity (ERC-8004)

An agent can carry a verifiable onchain identity and track record across all three ERC-8004 registries:

  • Identity — an ERC-721 "agent id" (AgentIdentity). Who the agent is.
  • Reputation — feedback an agent accrues (ReputationClient). Its track record.
  • Validation — attestations that an agent's work was checked (ValidationClient). Its work was verified.

This is optional and independent of payments: PaymentClient works with no identity configured. Reads need no gas (just the [onchain] extra and an RPC); registering, leaving feedback, or recording a validation are writes that need a funded EOA.

from arc_agent_pay.identity import AgentIdentity, ReputationClient

identity = AgentIdentity()                       # read-only; uses Arc Testnet RPC
agent_id = identity.resolve("0x<agent-address>") # most recent id minted to an address
profile = identity.profile(agent_id, reputation=ReputationClient())

print(profile.agent_id, profile.address)
print(profile.reputation_score, profile.feedback_count)

Registering an identity (write — needs [onchain] and a funded account):

from eth_account import Account
from arc_agent_pay.identity import AgentIdentity

account = AgentIdentity(account=Account.from_key("0x" + private_key))
new_id = account.register("https://your-agent-metadata.example")

Validation is two-sided: the agent owner requests validation of a piece of work, then a validator (a different wallet) responds with a 0–100 score:

from arc_agent_pay.identity import ValidationClient

# owner (owns the agent id) requests; validator responds
ValidationClient(account=owner).request_validation(
    validator_address=validator.address, agent_id=838889, request_hash=work_hash)
ValidationClient(account=validator).respond(
    request_hash=work_hash, response=100, confirm_ready=True)

Contract addresses + ABIs are committed under arc_agent_pay/onchain/ (verified Arc Testnet addresses) and overridable via ERC8004_IDENTITY_REGISTRY / ERC8004_REPUTATION_REGISTRY / ERC8004_VALIDATION_REGISTRY.

Who plays which role (important)

ERC-8004 reputation and validation are only meaningful when they come from a party other than the agent — that's what makes them trustless. In a mature ecosystem these roles are separate businesses:

Role What it does Who plays it in production
Agent Does work, pays, holds an identity You (this SDK)
Seller / provider Sells the data/API/LLM the agent buys Independent services
Reputation giver Leaves feedback after transacting The agent's counterparties
Validator Independently verifies the agent's work A separate auditor / validation service

⚠️ In the hosted playground demo the same operator plays every role so the full three-registry flow can be shown end-to-end on Arc Testnet. That makes those records self-attested — they demonstrate the plumbing, not independent trust. In production you'd run only the agent, and consume reputation and validation from independent parties.


MCP server

Expose arc-agent-pay over the Model Context Protocol so Claude Desktop, Cursor, or any MCP client can discover and pay for x402 services through it. The wallet key and a session budget ceiling come from the environment (never tool args), and spend is capped across the whole session.

pip install "arc-agent-pay[mcp]"
export AGENT_PRIVATE_KEY=0x...        # funded Arc Testnet EOA
export ARC_AGENT_PAY_BUDGET=0.50      # optional session ceiling (USDC)
arc-agent-pay-mcp                     # stdio transport

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "arc-agent-pay": {
      "command": "arc-agent-pay-mcp",
      "env": { "AGENT_PRIVATE_KEY": "0x...", "ARC_AGENT_PAY_BUDGET": "0.50" }
    }
  }
}

Tools: discover_services, list_registered_services, pay_and_fetch, get_budget_status, get_agent_identity.


LLM synthesis providers

The llm layer is provider-agnostic with three backends, picked by environment:

  • ArcAPIs (ARCAPIS_TOKEN_ID) — on-chain inference via arcapis.com; each call is authenticated with a per-call EIP-712 signature whose signer must own the packet NFT on-chain.
  • OpenAI (OPENAI_API_KEY) — direct, off-chain.
  • Template — keyless deterministic fallback; the agent runs with zero API keys.

Observability & evals

Trace every agent run (discovery → each paid fetch → synthesis) with Langfuse — opt-in and self-hostable, a no-op when unconfigured:

pip install "arc-agent-pay[observability]"
export LANGFUSE_PUBLIC_KEY=... LANGFUSE_SECRET_KEY=... LANGFUSE_HOST=...

Evaluate service-discovery quality offline (deterministic, no keys, no spend):

python -m arc_agent_pay.observability.evals.run_evals            # keyword
python -m arc_agent_pay.observability.evals.run_evals --semantic # RAG

Reports precision / recall / F1 / hit-rate over a labelled dataset.


Trust & safety

This SDK signs payments with a private key, so read the code — that's the point of it being open. Safeguards in place: testnet-only funds, a hard budget cap checked before every signature, reputation-gated spending, allow/deny lists and a kill switch, single-use EIP-3009 nonces, and pip-audit + gitleaks in CI. Full details, including honest limitations, in SECURITY.md.


Development

git clone https://github.com/hamedkharazmi/arc-agent-pay
cd arc-agent-pay
uv sync --group dev --extra all
uv run pytest -q
uv run ruff check .

Related

  • Hosted playground + APIagentpay.bond: run the agent from your browser against live Arc Testnet settlement, no install. The playground's server side (orchestration, SSE streaming, auth, hosting) lives in a separate repo; everything payment-critical is in this SDK.
  • x402 protocol — the HTTP 402 payment standard this SDK implements the client side of.
  • ERC-8004 — onchain agent identity/reputation/validation registries.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

arc_agent_pay-0.1.0.tar.gz (386.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

arc_agent_pay-0.1.0-py3-none-any.whl (74.3 kB view details)

Uploaded Python 3

File details

Details for the file arc_agent_pay-0.1.0.tar.gz.

File metadata

  • Download URL: arc_agent_pay-0.1.0.tar.gz
  • Upload date:
  • Size: 386.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for arc_agent_pay-0.1.0.tar.gz
Algorithm Hash digest
SHA256 687f6751022fb0b0f46b78aa92e783828cffe897ec976cf34ebbefa45abedc4d
MD5 0ad97ab2d23bfbc8d62a1e7385d7b141
BLAKE2b-256 22926467cf4a78a660cb4f563aa83ee96be88337fa5b891094beb95f3180ffaa

See more details on using hashes here.

Provenance

The following attestation bundles were made for arc_agent_pay-0.1.0.tar.gz:

Publisher: release.yml on hamedkharazmi/arc-agent-pay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file arc_agent_pay-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: arc_agent_pay-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 74.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for arc_agent_pay-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d8153c3386122b3ff49bed3996ab270f4f7a3ca531836e8b6347ec3a9c03b604
MD5 338a50dd35246e8191e95a78e9a9a094
BLAKE2b-256 bcc2f2ae9ba6c71ac01d0ac6962f4bcfbfed9a3b22603a599f1e8a1adfdb12e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for arc_agent_pay-0.1.0-py3-none-any.whl:

Publisher: release.yml on hamedkharazmi/arc-agent-pay

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page