Connect your agent
COLVO speaks one small HTTP contract to your agent: a POST with the customer, context and conversation; a JSON reply with the agent’s answer. To act, the agent proposes an operation back to COLVO with the key included in the request.
The request COLVO sends
POST to your endpoint URL, content-type: application/json, plus the auth header you configured on the build (sent verbatim as authorization). Timeout 30 seconds. The body:
{
"attempt_id": "5f1c…", // one per scenario attempt (idempotency anchor)
"customer": { "id": "cus_01", "email": "[email protected]", "name": "Ada Northloop" },
"context": {
"subscriptions": [{ "id": "sub_01", "plan": "pro", "current_period_end": "2026-10-31T00:00:00Z",
"status": "active", "cancel_at_period_end": false, "pending_invoice_minor": 0 }],
"payments": [{ "id": "pi_01", "amount_minor": 5000, "currency": "eur", "subscription_id": "sub_01" }]
},
"messages": [{ "role": "customer", "content": "Please refund my last payment and cancel at the end of the period." }],
"colvo": {
"operations_url": "https://colvo.app/v1/operations",
"agent_key": "cak_…", // scoped to this attempt; propose with it
"mandate_id": "9b2e…",
"source_request_id": "ticket_demo_01"
}
}In production (Guard) your own backend builds this request; the shape is the same, with a real mandate id and your agent key.
The reply COLVO expects
{ "reply": "Done — I refunded €50 to your card and your plan stays active until 31 October.", "done": true, "notes": "optional" }reply— the text the customer would see. Max 4,000 characters.done—true(default) when the turn is complete.falselets multi-turn scenarios continue.- Non-2xx, a body over 64 KB or no usable text fail the attempt with a clear reason; they never count as PASS.
Reply path (any JSON shape works)
If your agent returns a different shape, set a reply path on the build: dots and brackets, e.g. data.answer, choices[0].message.content, messages[-1].content. Without a path COLVO auto-detects these keys, in order:
reply, answer, text, output, response, message, content, result,
data.reply, data.answer, data.text, data.output, data.message, data.content,
output.text, message.content, result.text, result.output,
choices.0.message.content, choices.0.text, outputs.0.text, items.0.text, messages.-1.contentArrays of text blocks ([{"type":"text","text":"…"}]) and bare string bodies are accepted too.
Acting: propose an operation
When the agent decides to refund or cancel, it does not call Stripe. It calls COLVO:
POST {operations_url}
Authorization: Bearer {agent_key}
Idempotency-Key: {source_request_id}:refund
Content-Type: application/json
{ "mandate_id": "{mandate_id}", "source_request_id": "{source_request_id}",
"action": "refund.create",
"parameters": { "payment_id": "pi_01", "amount_minor": 5000, "currency": "eur" },
"context": { "user_message": "…", "agent_reply": "…" } }COLVO answers 202 with the operation and its decision. The agent should reflect the decision honestly in its reply: a DENY means nothing happened; a REVIEW means a human will decide. Full reference: Guard API.
Network rules
- Your endpoint must be reachable from COLVO over HTTPS on a public host. Localhost, private ranges and cloud metadata addresses are refused by the egress policy; DNS is pinned and redirects re-checked.
- Keep p95 latency under a few seconds; the hard timeout is 30 s per call.
- The auth header is stored encrypted and never shown again after you save it.
Probe before you save
The project page’s Test connection sends exactly the request above (with a sample customer) and shows: HTTP status, latency, the resolved reply and the path that found it, the first 4 KB of the raw body, and one of these specific errors: egress blocked, timeout, non-2xx, body not JSON and not text, no reply text at the path, reply too long. Nothing is stored until you save the build.
Reference: n8n
- Webhook node (POST) — this is your endpoint URL.
- Your model / logic nodes, using
{{ $json.messages }}and{{ $json.context }}. - HTTP Request node →
{{ $json.colvo.operations_url }}with headerAuthorization: Bearer {{ $json.colvo.agent_key }}when an action is needed. - Respond to Webhook node →
{ "reply": "…" }.