Metadata-Version: 2.4
Name: x402-agent
Version: 0.2.0
Summary: Framework-agnostic payer for the x402 HTTP payment protocol. Works with LangChain, CrewAI, AutoGen, LangGraph, or any other agent framework.
Project-URL: Homepage, https://github.com/xenarch-ai/x402-agent
Project-URL: Repository, https://github.com/xenarch-ai/x402-agent
Project-URL: Issues, https://github.com/xenarch-ai/x402-agent/issues
Author-email: Xenarch <hello@xenarch.dev>
License: MIT
License-File: LICENSE
Keywords: ai-agents,autogen,base,crewai,http-402,langchain,langgraph,micropayments,usdc,x402
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Requires-Dist: eth-account>=0.11
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.0
Requires-Dist: x402[evm]<3,>=2.8
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: pay-json
Requires-Dist: pay-json<2,>=1.2; extra == 'pay-json'
Description-Content-Type: text/markdown

# x402-agent

Framework-agnostic payer for the [x402 HTTP payment protocol](https://github.com/x402-foundation/x402).

> **`x402-agent` is an independent open-source package.** It is not affiliated with, endorsed by, or sponsored by the x402 Foundation, LF Projects, LLC, or Coinbase, Inc. "x402" is used nominatively to refer to the open HTTP payment protocol. Maintained by [Xenarch](https://xenarch.dev).

Zero framework dependencies. Subclass or compose from **LangChain**, **CrewAI**, **AutoGen**, **LangGraph**, or anything else that wants to let an agent spend USDC against a `402 Payment Required` response without rolling its own pay loop.

## What it does

```python
from decimal import Decimal
from x402_agent import X402Payer, BudgetPolicy

payer = X402Payer(
    private_key="0x...",
    budget_policy=BudgetPolicy(
        max_per_call=Decimal("0.05"),
        max_per_session=Decimal("1.00"),
    ),
)

result = payer.pay("https://example.com/gated/article")
# {"success": True, "body": "...", "amount_usd": "0.01", ...}
```

`pay(url)` walks the full challenge: GET → parse `402` → pick a supported (scheme, network) → enforce your budget → sign an EIP-3009 USDC authorisation → retry with the version-correct payment header (`PAYMENT-SIGNATURE` for V2, `X-PAYMENT` for V1 legacy gates) → return the unlocked body. Never raises; every failure mode is a dict you can show an LLM.

Async via `await payer.pay_async(url)`.

## What's in the package

| Symbol | Purpose |
| --- | --- |
| `X402Payer` | Neutral pay loop with `_pre_payment_hook` / `_post_payment_hook` for subclasses |
| `BudgetPolicy` | Per-call + per-session spend caps, optional human-approval callback, thread-safe |
| `select_accept` | Pick a supported `(scheme, network)` from a parsed `PaymentRequired` |
| `price_usd` | Atomic-units → `Decimal` USD using the advertised asset decimals |
| `is_public_host` / `is_public_host_async` | SSRF guard for agent-provided URLs |
| `budget_hint_exceeds` | Early-refusal check against `pay.json` `budget_hints` |
| `payment_headers` | Return the `(request, response)` header pair for V1 vs V2 wire |

Constants (`DEFAULT_NETWORK`, `DEFAULT_SCHEME`, `X_PAYMENT_HEADER`, `X_PAYMENT_RESPONSE_HEADER`, `PAYMENT_SIGNATURE_HEADER`, `PAYMENT_RESPONSE_HEADER`) are exported so adapters don't have to hard-code them.

## Subclassing

The four hooks are the intended extension point. Override any subset:

```python
class MyPayer(X402Payer):
    def _pre_payment_hook(self, *, url, accept, price):
        # Return an error dict to abort before the budget lock.
        if self._is_suspicious(accept.pay_to):
            return {"error": "refused_by_policy"}
        return None

    def _post_payment_hook(self, result, paid_response):
        # Mutate result in place; post runs after budget.commit().
        result["signed_by"] = "my-facilitator"
```

Pre-hook runs *before* the budget lock so a slow external check (reputation lookup, etc.) can't block other concurrent payments. Post-hook runs *after* the spend is committed so a receipt fetch failure can't revert a paid GET.

## Stability

`__all__` defines the v0.x stable surface. Anything in `x402_agent._helpers` or `x402_agent._payer` is accessible but subject to rename.

## Licence

MIT.
