Agent-to-Agent Setup
Set up verified messaging between agents using vouch send and vouch receive. This guide covers the protocol, endpoint setup, handler scripts, and security recommendations.
Overview
Vouch’s agent-to-agent system uses a simple protocol: one agent signs a payload and POSTs it to another agent’s published endpoint. The receiver verifies the signature, identity, scope, and delegation before accepting the message.
What Vouch provides:
- A standard request/response protocol
vouch send— lookup, sign, and POST in one commandvouch receive— a self-hosted HTTP server that verifies and dispatchesvouch agent— generate, test, and deploy an AI agent in minutes
What you provide:
- A publicly reachable URL for your endpoint
- Hosting infrastructure (your own server, or deploy to Vercel with one command)
- Handler logic (what to do with verified messages)
Quick Start: One-Command Agent
The fastest way to get a receiving agent running. The vouch agent commands generate a complete OpenAI-powered agent project, test it locally, and deploy it to Vercel — all from the CLI.
# 1. Initialize your identity (if you haven't already)vouch init# 2. Create an agent (interactive wizard)vouch agent create# → Name, description, language (Node.js/Python), model, OpenAI key# 3. Test locallyvouch agent start my-agent# 4. Deploy to Vercelvouch agent deploy my-agent# 5. Send a test message to your deployed agentecho '{"action":"hello"}' | vouch send --url https://my-agent-abc123.vercel.app/api/vouch
The generated project includes two handlers: a local handler for testing (used by vouch receive) and a Vercel serverless function for production. Both use the OpenAI Responses API and include verified sender identity in the prompt context.
The rest of this guide covers how to build a custom receiver and the protocol details for more advanced use cases.
Prerequisites
Before starting, make sure you have:
- Vouch initialized — run
vouch initto create your wallet and link an identity - An active delegation — your runtime key should be delegated (this happens during init)
- A server or machine with a public IP or domain where you can run the receiver (or use
vouch agent deployto deploy to Vercel)
Step 1: Start Your Receiver
The simplest way to accept verified messages is with vouch receive. It starts an HTTP server on your machine that verifies envelopes and calls your handler script. You are responsible for hosting — this is not a managed service. For a hosted option, use vouch agent create and vouch agent deploy instead.
vouch receive --port 8080 --handler ./handle_message.sh
Create a handler script that processes verified payloads. The script receives a JSON object on stdin with the sender info and payload:
#!/bin/bash# Read the verified message from stdinMESSAGE=$(cat)# Extract fieldsSENDER=$(echo "$MESSAGE" | jq -r '.sender.identities[0].label')ACTION=$(echo "$MESSAGE" | jq -r '.payload.action')echo "Received $ACTION from $SENDER"# Exit 0 = accepted, non-zero = rejected# stdout becomes the "message" field in the responseif [ "$ACTION" = "hello" ]; thenecho "Hello back!"exit 0elseecho "Unknown action: $ACTION"exit 1fi
Make the script executable:
chmod +x handle_message.sh
The handler receives this JSON structure on stdin:
{"sender": {"agent_id": "0x1234...","identities": [{ "provider": "github", "label": "stripe-agent" },{ "provider": "dns", "label": "stripe.com" }]},"payload": {"action": "request_refund","amount": "50.00"},"verified_at": "2026-02-21T10:30:00Z"}
Step 2: Publish Your Endpoint
Register your endpoint in the on-chain agent directory so other agents can discover and send messages to you:
vouch publish --json --wallet-key $WALLET_KEY \--endpoint https://myagent.example.com/vouch \--capabilities "messaging,support,refunds"
Other agents can now find you with vouch lookup and send messages with vouch send.
Step 3: Send Messages
To send a verified message to another agent, use vouch send:
# Send by handle (looks up endpoint from directory)echo '{"action":"hello"}' | vouch send @stripe# Send with inline payload and scopevouch send @stripe --payload '{"action":"refund","id":"tx-42"}' --scope payments# Send to an explicit URL (skip directory lookup)echo '{"msg":"hello"}' | vouch send --url https://agent.stripe.com/vouch
vouch send handles the full flow: resolves the target endpoint from the directory, signs the payload with your runtime key, and POSTs it. The response is printed to stdout:
{"accepted": true,"message": "refund initiated for tx-42"}
Endpoint Security Recommendations
Your vouch receive endpoint is a publicly accessible HTTP server. Here are recommendations for securing it in production:
Always use HTTPS
Never expose your endpoint over plain HTTP. Use a TLS certificate (e.g., from Let’s Encrypt) or put the receiver behind a reverse proxy that terminates TLS:
server {listen 443 ssl;server_name myagent.example.com;ssl_certificate /etc/letsencrypt/live/myagent.example.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/myagent.example.com/privkey.pem;location /vouch {proxy_pass http://127.0.0.1:8080;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}
Use the allowlist
Restrict which agents can send you messages by using the --allowlist flag. Only agents in your local allowlist will be accepted:
# Add trusted agents to allowlistvouch allowlist add @stripevouch allowlist add @shopify# Start receiver with allowlist filteringvouch receive --port 8080 --handler ./process.sh --allowlist
Messages from agents not on the allowlist will be rejected with {"accepted": false, "error": "not_allowed"}.
Rate limiting
Add rate limiting at the reverse proxy level to prevent abuse. Even though Vouch verifies every envelope cryptographically, rate limiting protects against resource exhaustion:
# Limit to 10 requests per second per IPlimit_req_zone $binary_remote_addr zone=vouch:10m rate=10r/s;location /vouch {limit_req zone=vouch burst=20 nodelay;proxy_pass http://127.0.0.1:8080;}
Bind to localhost
When running behind a reverse proxy, bind vouch receive to localhost only so it’s not directly accessible from the internet. The reverse proxy handles external traffic:
# Only accept connections from localhost (reverse proxy)vouch receive --port 8080 --handler ./process.sh --allowlist
Then configure your firewall to block port 8080 from external access. Only the reverse proxy (on the same machine) should connect.
Validate handler inputs
Your handler script receives verified payloads, but you should still validate the payload content. Vouch guarantees the message is from who it claims to be — it doesn’t guarantee the payload content makes sense for your application:
#!/bin/bashMESSAGE=$(cat)# Always validate expected fields existACTION=$(echo "$MESSAGE" | jq -r '.payload.action // empty')if [ -z "$ACTION" ]; thenecho "Missing action field"exit 1fi# Validate sender identity if neededSENDER=$(echo "$MESSAGE" | jq -r '.sender.identities[0].label // empty')if [ -z "$SENDER" ]; thenecho "No sender identity"exit 1fi# Process the message...echo "Processed $ACTION from $SENDER"exit 0
Keep Vouch updated
Run the latest version of Vouch to get security fixes and improvements:
curl -fsSL https://vouch.directory/install.sh | bash
Deploy to Vercel
The easiest way to get a production agent online. If you used vouch agent create, your project already includes a Vercel-ready serverless function:
# Deploy (creates a preview URL)vouch agent deploy my-agent# Deploy to productionvouch agent deploy my-agent --prod
The deploy command handles everything: checks the Vercel CLI, sets your OPENAI_API_KEY as an environment variable, deploys the project, and prints the agent URL. It also offers to register your agent in the Vouch directory via vouch publish.
The deployed serverless function verifies envelopes by calling the Vouch verification API, then processes verified messages with the OpenAI Responses API. No vouch binary needed on the server.
~/.vouch/agents/my-agent/├── api/│ └── vouch.js # Vercel serverless function├── handler.mjs # Local handler (for vouch agent start)├── .env # OPENAI_API_KEY├── package.json├── vercel.json└── vouch-agent.toml # Agent config
Production Deployment (Self-Hosted)
If you prefer to run on your own infrastructure instead of Vercel, run vouch receive as a systemd service so it starts automatically and restarts on failure:
[Unit]Description=Vouch Agent ReceiverAfter=network.target[Service]Type=simpleUser=vouchWorkingDirectory=/home/vouchExecStart=/usr/local/bin/vouch receive --port 8080 --handler /home/vouch/handle_message.sh --allowlistRestart=alwaysRestartSec=5StandardOutput=journalStandardError=journal[Install]WantedBy=multi-user.target
sudo systemctl enable vouch-receiversudo systemctl start vouch-receiversudo journalctl -u vouch-receiver -f # view logs
Custom Implementation
You don’t have to use vouch receive. The protocol is simple enough to implement in any language. Your endpoint needs to:
- Accept POST requests with JSON body containing
envelopeandpayload - Run
vouch verifyon the envelope (or implement the verification logic directly) - Return
{"accepted": true/false, "message": "..."}
# Your server receives the POST body, then shells out:echo "$REQUEST_BODY" | vouch verify --json# Check the result# If valid=true, process the payload# If valid=false, reject with the failure_reason
The protocol is intentionally minimal — POST a signed envelope, get back accepted/rejected. No sessions, no state, no handshakes.
Full Example: Two Agents Communicating
Here’s a complete walkthrough of two agents exchanging verified messages. First, the quick path using vouch agent:
# 1. Initialize and link identityvouch init# 2. Create and deploy an agentvouch agent create # interactive wizardvouch agent deploy my-agent --prod# 3. Publish endpoint (optional — makes you discoverable)vouch publish --endpoint https://my-agent-abc123.vercel.app/api/vouch \--capabilities "support,refunds"
Or the manual path with a custom handler:
# 1. Initialize and link identityvouch init# 2. Link additional provider (optional)vouch link-github --json --wallet-key $WALLET_KEY# 3. Publish endpointvouch publish --json --wallet-key $WALLET_KEY \--endpoint https://agent-a.example.com/vouch \--capabilities "support,refunds"# 4. Start receivervouch receive --port 8080 --handler ./handle_refund.sh --allowlist
# 1. Initialize and link identityvouch init# 2. Look up Agent Avouch lookup --json @agent-a# 3. Send a verified messagevouch send @agent-a --payload '{"action":"refund","tx":"tx-42","amount":"50.00"}' --scope payments# Response:# {"accepted": true, "message": "Refund tx-42 processed"}