Create ATP Protocol servers (FastAPI + middleware) and clients. Use when building ATP-protected APIs, adding payment middleware, or writing clients that call ATP endpoints or the settlement service.
Scanned 5/31/2026
Install via CLI
openskills install diegosouzapw/awesome-omni-skill---
name: atp
description: Create ATP Protocol servers (FastAPI + middleware) and clients. Use when building ATP-protected APIs, adding payment middleware, or writing clients that call ATP endpoints or the settlement service.
---
# ATP Protocol skill – servers and clients
Use this skill when you need to **create or modify ATP (Agent Trade Protocol) servers or clients**. ATP enables agent-to-agent payments on Solana: middleware on the server charges by token usage; the client pays and receives decrypted responses after settlement.
**Documentation index:** For full Claude Code docs (skills, agents, etc.), fetch: https://code.claude.com/docs/llms.txt
---
## 1. Creating an ATP server
### 1.1 Minimal FastAPI server with ATP middleware
- Use **FastAPI** and add **`ATPSettlementMiddleware`** so selected endpoints are paid per use.
- Endpoints must return **usage data** (input/output token counts) in a supported format so the middleware can compute and execute payment.
**Imports and app:**
```python
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from atp.middleware import ATPSettlementMiddleware
from atp.schemas import PaymentToken
app = FastAPI(title="My ATP-Protected API")
```
**Add middleware (required args):**
```python
app.add_middleware(
ATPSettlementMiddleware,
allowed_endpoints=["/v1/chat", "/v1/completions"], # exact path list
input_cost_per_million_usd=10.0, # USD per million input tokens
output_cost_per_million_usd=30.0, # USD per million output tokens
recipient_pubkey="YourSolanaWalletPublicKeyHere", # required; receives payment
payment_token=PaymentToken.SOL, # SOL or PaymentToken.USDC
)
```
**Optional middleware args:**
- `wallet_private_key_header`: Header name for wallet key (default `"x-wallet-private-key"`).
- `skip_preflight`: Skip Solana preflight (default `False`).
- `commitment`: Solana commitment (default `"confirmed"`).
- `settlement_service_url`: Facilitator URL (default from `ATP_SETTLEMENT_URL` or `https://facilitator.swarms.world`).
- `fail_on_settlement_error`: If `True`, raise on settlement failure (default `False`).
- `settlement_timeout`: Timeout in seconds (default from env or `300.0`).
**Protected endpoint example (return usage):**
```python
@app.post("/v1/chat")
async def chat(request: dict):
message = request.get("message", "")
# Your agent logic
response_text = "Agent response here"
return JSONResponse(content={
"response": response_text,
"usage": {
"input_tokens": 100,
"output_tokens": 50,
"total_tokens": 150
}
})
```
**Supported usage formats (middleware/settlement parses these):**
- **OpenAI:** `usage.prompt_tokens`, `usage.completion_tokens`, `usage.total_tokens`
- **Anthropic:** `usage.input_tokens`, `usage.output_tokens`
- **Google/Gemini:** `usageMetadata.promptTokenCount`, `candidatesTokenCount`, `totalTokenCount`
Paths not in `allowed_endpoints` are not charged (e.g. `/v1/health`).
**Run server:**
```python
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
```
### 1.2 Server checklist
- Set `recipient_pubkey` to the Solana wallet that should receive payments.
- Ensure every protected handler returns a body that includes one of the supported usage structures.
- Optional: set `ATP_ENCRYPTION_KEY` (base64 Fernet) for consistent response encryption across restarts; otherwise a key is generated per process.
- For production: use `fail_on_settlement_error=False` and check `atp_settlement_status` on the client; never log or persist wallet private keys.
---
## 2. Creating an ATP client
### 2.1 Client for ATP-protected endpoints
Use **`ATPClient`** to call ATP-protected APIs: it adds the wallet header and can decrypt responses after payment.
**Imports and constructor:**
```python
from atp.client import ATPClient
client = ATPClient(
wallet_private_key="[1,2,3,...]", # or base58 string; required for payment
settlement_service_url="https://facilitator.swarms.world", # optional
settlement_timeout=300.0, # optional
wallet_private_key_header="x-wallet-private-key", # optional
verbose=False, # optional, for debugging
)
```
**Making a paid request (POST):**
```python
import asyncio
response = asyncio.run(client.post(
url="https://api.example.com/v1/chat",
json={"message": "Hello!"},
# wallet_private_key=..., # optional override per request
# auto_decrypt=True, # default True
))
print(response["response"]) # agent output
print(response.get("atp_settlement")) # payment details
print(response.get("atp_settlement_status")) # e.g. "paid" or "failed"
```
**GET and other methods:**
```python
response = await client.get(url="https://api.example.com/v1/status")
response = await client.request("PUT", url=some_url, json=payload)
```
If `auto_decrypt=True` (default), the client decrypts encrypted response bodies when payment has succeeded.
### 2.2 Client for settlement service (facilitator) only
Use the same **`ATPClient`** for facilitator operations without calling an ATP-protected API.
**Health check (no wallet needed):**
```python
client = ATPClient()
health = asyncio.run(client.health_check())
```
**Parse usage (no wallet needed):**
```python
from atp.client import ATPClient
import asyncio
client = ATPClient()
usage = asyncio.run(client.parse_usage({"usage": {"prompt_tokens": 100, "completion_tokens": 50, "total_tokens": 150}}))
# usage -> e.g. {"input_tokens": 100, "output_tokens": 50, "total_tokens": 150}
```
**Calculate payment (no blockchain call):**
```python
from atp.schemas import PaymentToken
payment = await client.calculate_payment(
usage={"input_tokens": 1000, "output_tokens": 500},
input_cost_per_million_usd=10.0,
output_cost_per_million_usd=30.0,
recipient_pubkey="RecipientPublicKeyHere",
payment_token=PaymentToken.SOL,
)
```
**Execute settlement (spends SOL/USDC):**
```python
result = await client.settle(
usage={"input_tokens": 1000, "output_tokens": 500},
input_cost_per_million_usd=10.0,
output_cost_per_million_usd=30.0,
recipient_pubkey="RecipientPublicKeyHere",
payment_token=PaymentToken.SOL,
)
# result includes tx_signature, status, etc.
```
### 2.3 Client checklist
- For paid endpoint calls or `settle()`, provide `wallet_private_key` (constructor or per call).
- Wallet key format: JSON array string `"[1,2,3,...]"` or base58 keypair string.
- Check `atp_settlement_status` in responses to handle failures; never log or store private keys.
- Env vars (optional): `ATP_SETTLEMENT_URL`, `ATP_SETTLEMENT_TIMEOUT`, `ATP_WALLET_PRIVATE_KEY`, `ATP_ENDPOINT_URL`.
---
## 3. Project layout and references
- **Server examples:** `examples/server/example.py`, `examples/server/full_flow_example.py`
- **Client examples:** `examples/client/example_request.py`, `examples/client/example_settle.py`, `examples/client/example_health_check.py`
- **API reference:** `atp/middleware.py` (middleware), `atp/client.py` (client), `atp/schemas.py` (`PaymentToken`, config models)
- **Docs:** README.md in repo; full docs at https://docs.swarms.ai/docs/atp/overview
When creating or editing ATP servers or clients, follow the patterns above and use the existing examples and atp package as the source of truth.
No comments yet. Be the first to comment!