Replace API keys with agent identity
Sign outbound HTTP requests with the agent's DID. Partners verify the signature against a public key — no shared secrets, no key rotation.
Your agent calls a partner API. The partner needs to verify the request really came from your specific agent — not from a stolen key, not from a different service. Sign the request body with the agent's DID; the partner verifies with a public key they pull once.
import json
import httpx
from agentfield import Agent, DIDAuthenticator
app = Agent(node_id="outbound-agent", enable_did=True)
@app.reasoner()
async def call_partner(query: str) -> dict:
# Build an authenticator from the agent's own credentials
authenticator = DIDAuthenticator(
did=app.did_manager.get_agent_did(),
private_key_jwk=app.did_manager.identity_package.agent_did.private_key_jwk,
)
body = json.dumps({"query": query}).encode()
auth_headers = authenticator.sign_headers(body)
# auth_headers contains:
# X-Caller-DID: did:key:z6Mk...
# X-DID-Signature: <base64 Ed25519 signature>
# X-DID-Timestamp: <unix seconds>
# X-DID-Nonce: <random hex>
async with httpx.AsyncClient() as client:
resp = await client.post(
"https://partner.example.com/api/data",
content=body,
headers={**auth_headers, "Content-Type": "application/json"},
)
return resp.json()
app.run()The partner verifies by resolving your agent's public key (one-time fetch) and checking the signature:
# Partner pulls your agent's public key once — did:web is resolvable over plain HTTPS
curl https://your-platform.com/agents/outbound-agent/did.json
# Or via the control plane registry
curl http://localhost:8080/api/v1/registered-didsWhat this gives you
- No shared API keys per agent — keys live only in the agent's encrypted keystore.
- Receivers identify which specific agent made the call (not just "your service").
- Compromised partner credentials don't grant access; the signing key never leaves the agent.
Next
- Identity reference — DID auth section
- Pair with: Cryptographic receipts