Observed since 20 Oct, 21:52 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
agentescrow402
Python SDK, LangChain tool, MCP server, and CLI for AgentEscrow402 — trustless AI agent escrow payments on Casper Network
Python SDK, LangChain Tool, and MCP Server for trustless AI agent escrow payments on Casper Network.
This directory contains three integration layers for AgentEscrow402:
| Component | File | Description |
|---|---|---|
| Python SDK | client.py | Async client with Ed25519 signing, full escrow lifecycle |
| CLI | cli.py | ae402 console script — thin wrapper over the SDK |
| Verifier | verify.py | Offline Ed25519 verification of arbiter multisig votes |
| LangChain Tool | langchain_tool.py | Drop-in EscrowPaymentTool for any LangChain agent |
| MCP Server | mcp_server.py | 26 tools for any MCP-compatible LLM (Claude, GPT, etc.) |
For judges and first-time developers. Zero config, zero secrets, works against the live sandbox.
# 1. clone + install (30s)
git clone https://github.com/alexbelij/AgentEscrow402.git
cd AgentEscrow402
pip install httpx cryptography pydantic
# 2. run the quickstart (60s)
python examples/quickstart.py --api-url https://agentescrow402-api-ywm8.onrender.com
Expected output (real testnet, one create + one release):
connected: {'status': 'ok', ...}
buyer identity: <64-hex>
escrow created: <service_hash> status=created
escrow released: status=released deploy_hash=<hex>
That's it. The deploy_hash links to cspr.live if you want to inspect the on-chain state yourself.
EscrowClient.generate() produced a fresh Ed25519 identity (no
wallet setup, no funded testnet account required for the sandbox
flow).create_escrow produced a signed request; the server locked funds
and returned a service_hash you can reference later.release produced another signed request; the server released the
funds and returned a deploy_hash.For the full autonomous buyer/seller/arbiter loop (with a real dispute and an LLM arbitration call), run:
python examples/escrow_agent.py --api-url https://agentescrow402-api-ywm8.onrender.com
EscrowPaymentTool into any agent — see
sdk/langchain_tool.py.sdk/mcp_server.py.docs/HOW_TO_JUDGE.md maps the 8 criteria to concrete
files and endpoints.pip install httpx cryptography pydantic
# For MCP server:
pip install mcp
# For LangChain:
pip install langchain
from sdk.client import EscrowClient
async with EscrowClient.generate("https://agentescrow402-api-ywm8.onrender.com") as client:
escrow = await client.create_escrow(
receiver="ab" * 32, # receiver's 64-hex Casper account hash
amount=5000,
ttl=300
)
print(f"Escrow created: {escrow['service_hash']}")
# Release funds after work is delivered
await client.release(escrow["service_hash"], amount=5000)
from sdk.langchain_tool import EscrowPaymentTool
tool = EscrowPaymentTool("https://agentescrow402-api-ywm8.onrender.com", sender="agent-001")
result = await tool.run("create", receiver="ab" * 32, amount=5000)
result = await tool.run("release", service_hash=result["service_hash"])
result = await tool.run("reputation", agent="agent-001")
Supported actions: create, release, refund, dispute, status, reputation, batch_release, batch_cancel, claim_stream, risk
# stdio (default — for Claude Desktop, Cursor, etc.)
python -m sdk.mcp_server
# SSE (for remote/web connections)
pip install mcp[sse] uvicorn starlette
python -m sdk.mcp_server --transport sse --port 8402
The live API verifies Ed25519-signed X-Payment headers on every request. EscrowClient.generate() handles this automatically:
from sdk.client import EscrowClient
# Auto-generates a keypair and signs all requests
async with EscrowClient.generate("https://agentescrow402-api-ywm8.onrender.com") as client:
print(client.sender) # your 64-hex Ed25519 public key
To reuse the same identity across runs:
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
key = Ed25519PrivateKey.generate() # persist this for reuse
client = EscrowClient("https://agentescrow402-api-ywm8.onrender.com", private_key=key)
async with EscrowClient("http://localhost:8000", sender="agent-001", sandbox=True) as client:
escrow = await client.create_escrow(receiver="ab" * 32, amount=5000, ttl=300)
| Method | Description |
|---|---|
create_escrow(receiver, amount, ttl) | Lock funds in a new escrow |
release(service_hash, amount) | Release funds to receiver |
refund(service_hash) | Return funds to sender |
dispute(service_hash, reason_hash) | Open a dispute |
get_escrow(service_hash) | Get escrow status and details |
list_escrows(status, limit, offset) | List escrows with filters |
get_reputation(agent) | Query on-chain reputation score |
get_stats() | Aggregate escrow statistics |
batch_release(service_hashes) | Release multiple escrows atomically |
batch_cancel(service_hashes) | Cancel multiple pending escrows |
build_x402_header(service_hash, amount) | Build x402 payment header |
| Domain | Tool | Description |
|---|---|---|
| Escrow | create_escrow | Lock funds between sender and receiver |
release_escrow | Release funds to receiver | |
refund_escrow | Return funds to sender | |
dispute_escrow | Open a dispute on active escrow | |
get_escrow | Fetch escrow status and details | |
list_escrows | List escrows with status filter | |
get_escrow_history | Full state-change history | |
build_x402_header | Build x402 payment header | |
compute_hash | Compute deterministic service hash | |
estimate_fee | Estimate fees and insurance cost | |
| Reputation | get_reputation | Query agent's on-chain reputation |
list_agents | List all agents with scores | |
get_stats | Aggregate escrow statistics | |
get_events | Recent escrow events | |
health_check | API and blockchain health | |
| Arbitration | submit_dispute_arbitration | Submit for AI-assisted arbitration |
get_arbitration_result | Get AI verdict and reasoning | |
appeal_arbitration | Appeal within allowed window | |
| Risk | calculate_risk_score | IsolationForest anomaly detection |
get_risk_dashboard | Aggregated risk scores | |
| Identity | register_identity | Register agent with public key |
get_identity | Look up agent identity | |
| Advanced | elect_arbiter | VRF-based on-chain arbiter election |
batch_release | Release multiple escrows atomically | |
batch_cancel | Cancel multiple pending escrows | |
claim_stream | Claim fully-vested streaming escrow |
The x402 protocol header format used by the live API:
x402-v1;<escrow_hash>;<amount>;<sender>;<timestamp>;<nonce>;<signature>
Where signature = Ed25519.sign(key, "x402-v1;<escrow_hash>;<amount>;<sender>;<timestamp>;<nonce>;<METHOD>;<path>"), binding it to the exact HTTP method and path.
examples/quickstart.py — minimal signed create → releaseexamples/escrow_agent.py — full autonomous buyer/seller lifecycle with dispute and AI arbitration| Document | Description |
|---|---|
| SDK Guide | Full SDK documentation with examples |
| API / SDK / MCP Reference | Complete 62-endpoint REST API reference |
| Architecture | System architecture and design decisions |
| OpenAPI Spec | Machine-readable API specification |
| MCP Tools Schema | MCP tool definitions (JSON) |
| Console (interactive) | Live interactive API/SDK/MCP documentation |
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
cryptographyEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | cryptography>=41 | runtime |
httpxEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | httpx>=0.24 | runtime |
pydanticEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pydantic>=2.0 | runtime |
mypyEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | mypy>=1.5; extra == "dev" | runtime |
pytest-asyncioEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest-asyncio>=0.21; extra == "dev" | runtime |
pytest-httpxEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest-httpx>=0.28; extra == "dev" | runtime |
pytestEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest>=7.0; extra == "dev" | runtime |
ruffEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | ruff>=0.1; extra == "dev" | runtime |
langchainEnvironment{
"extras": "",
"marker": "extra == \"langchain\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | langchain>=0.1; extra == "langchain" | runtime |
mcpEnvironment{
"extras": "",
"marker": "extra == \"mcp\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | mcp<2,>=0.9; extra == "mcp" | runtime |
bdist_wheel · 69.53 KB · Python py3
sdist · 90.79 KB · Python source
Observed since 20 Oct, 21:52 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:93aa973093de9482be6dcbaace61c67deed8b777a59d71f006f2de3397bbdff7