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
ATPSettlementMiddlewareso 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:
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):
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 (defaultFalse).commitment: Solana commitment (default"confirmed").settlement_service_url: Facilitator URL (default fromATP_SETTLEMENT_URLorhttps://facilitator.swarms.world).fail_on_settlement_error: IfTrue, raise on settlement failure (defaultFalse).settlement_timeout: Timeout in seconds (default from env or300.0).
Protected endpoint example (return usage):
@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:
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
1.2 Server checklist
- Set
recipient_pubkeyto 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=Falseand checkatp_settlement_statuson 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:
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):
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:
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):
client = ATPClient()
health = asyncio.run(client.health_check())
Parse usage (no wallet needed):
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):
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):
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(), providewallet_private_key(constructor or per call). - Wallet key format: JSON array string
"[1,2,3,...]"or base58 keypair string. - Check
atp_settlement_statusin 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.
Scan to join WeChat group