Skip to main content

Command Palette

Search for a command to run...

Stop Guessing Who's Calling Your Agents: Cryptographic Contracts in E-Commerce

Updated
3 min read
Stop Guessing Who's Calling Your Agents: Cryptographic Contracts in E-Commerce
A
Developer and designer. Completed and published several tools and applications.

The "Trust Me" Problem

You've built a beautiful multi-agent e-commerce system. The payment agent processes charges. The inventory agent manages stock. The fulfillment agent talks to an LLM. Everything works perfectly in your test environment.

Then you deploy to production, and suddenly your payment agent is accepting POST requests to /charge from... who exactly?

Without cryptographic verification, your payment agent is secured by hope, not by trust. Any service on your network — or anyone who can guess your API shape — can call it. That's not fear-mongering. That's how unauthenticated HTTP works.

Here's the practical fix using signed contracts between every agent pair, with about 30 lines of code total.

The Architecture

Four agents, four risk profiles:



┌────────┐     ┌────────┐     ┌────────┐
│   Order     │ ──▶│  Inventory  │     │  Payment.   │
│   Agent     │     │    Agent    │     │   Agent     │
│  (Low risk) │     │ (Med risk)  │     │ (High risk) │
└────────┘     └────────┘     └────────┘
       │                                        │
       │              ┌────────┐          │
       └────────▶│ Fulfillment │◀──────┘
                      │    Agent    │
                      │ (Med risk)  │
                      └────────┘

Each arrow in that diagram becomes a cryptographically signed contract. No contract = no call.


The Implementation (The Interesting Part)

1. Agent registration and contract issuance

from codios import CodiosClient

codios = CodiosClient(api_key="codios_sk_...")

order = codios.agents.register(name="order-agent")
payment = codios.agents.register(name="payment-agent")

contract = codios.contracts.issue(
    caller_did=order.did,
    callee_did=payment.did,
    scopes=["payment:charge:max_10000usd"],  # No refund permission here
    ttl_seconds=3600
)

The key insight: refund scope is deliberately excluded. If the order agent tries to call /refund, it physically cannot because the contract token doesn't include that scope. There's no runtime permission escalation possible.

2. Attaching the contract to every call

async def charge_customer(order_id: str, amount: float):
    resp = await httpx.post(
        "http://payment-agent/charge",
        json={"order_id": order_id, "amount": amount},
        headers={"X-Codios-Contract": contract.token},
    )
    return resp.json()

3. Verification on the receiving side (no network call, just crypto)

@app.post("/charge")
async def charge(request: Request, body: dict):
    contract = verify_contract(
        token=request.headers.get("X-Codios-Contract"),
        required_scope="payment:charge",
        platform_public_key=CODIOS_PUBLIC_KEY,
    )
    
    if body["amount"] > contract.scope_limit("payment:charge"):
        raise HTTPException(403, "Exceeds contract limit")
    
    return await process_payment(body["order_id"], body["amount"])

That verify_contract call checks:

  • Ed25519 signature (tamper-proof)
  • Nonce (replay attack protection)
  • Scope (permission boundary)
  • Expiry (time-limited access)

All in about 10 microseconds. No round-trip to a central service.


The Two Bonus Protections

Human approval for high-risk actions

Refunds over $500 require a real person to click Approve:

if body["amount"] > 500:
    decision = await approval.request(
        action="process_refund",
        details={"order_id": body["order_id"], "amount": f"${body['amount']:,.2f}"},
        notify=["ops-team@yourcompany.com"],
        timeout_seconds=600,
    )
    if not decision.approved:
        return {"status": "rejected"}

LLM prompt injection firewall

Customer-supplied addresses can contain injection attacks. Scan before the LLM sees anything:

scan = await fw.scan(content=body["address"], context="shipping_address")
if scan.threat_detected:
    raise HTTPException(400, "Invalid shipping address")

Why This Matters for Your Stack

Without contracts With contracts
Any service can call /charge Only callers with valid signed tokens
Permissions are runtime-configurable (risky) Permissions are cryptographically bound
No proof of who approved what Full audit trail of every agent action
Replay attacks possible Nonce checking prevents replays
LLM prompt injection vulnerabilities Pre-LLM scanning blocks injection

The Bottom Line

~30 lines of instrumentation. Free tier covers 5 agents. Runs entirely locally after contract issuance.

Multi-agent systems are powerful, but they multiply your attack surface. Cryptographic contracts are how you turn that surface into a feature instead of a liability.


Full tutorial with all code blocks: Codios Blog

Try Codios → codios.midlantics.com

Try A2A → a2a.midlantics.com