Skip to main content

Agent Integration

Your agent backend now receives requests from Convoy instead of directly from your client. You need to do two things:
  1. Verify the request — check Convoy’s HMAC signature
  2. Report metrics — send latency, outcome, cost, and input/output to Convoy

1. Verify the request

Convoy signs every request it forwards using HMAC-SHA256 with your shared secret. Your agent must verify this signature to confirm the request came from Convoy.
If signature verification fails, reject the request immediately — return a 401 and do not run your agent. If you also need to accept direct callers on this route, add your own auth (e.g. API key or session token).

Headers Convoy adds

How to verify

  1. Parse X-Convoy-Signature to extract t (timestamp), v1 (HMAC), and optionally v2 (HMAC)
  2. Reject if timestamp is older than 5 minutes
  3. Build the signed payload: {timestamp}\n{METHOD}\n{path_with_query}\n{body} For example, a POST to /api/chat?session=abc with body {"msg":"hi"} at timestamp 1700000000:
    {path_with_query} is the path of the request as it arrives at your backend, including any query string. Convoy constructs this by concatenating the version’s base path with the client’s request path — for example, a version URL of /api/chat plus a client path of /completions produces /api/chat/completions.
  4. Compute HMAC-SHA256 using your secret
  5. Accept if either v1 or v2 matches
During secret rotation, Convoy sends both v1 (signed with the new secret) and v2 (signed with the old secret) for 24 hours. Your env has one secret — it will match one of them regardless of whether you’ve rotated yet. The code above handles this automatically.

2. Report metrics

After your agent processes the request, report metrics to Convoy. This data powers test evaluation — Convoy uses it to decide whether to promote or roll back. Endpoint: POST https://api.convoylabs.com/v1/ingest/sessions Auth: Authorization: Bearer <CONVOY_SECRET> (same secret)

Payload

Always required: Required on success, optional on error: Required on last step (unless outcome is "error"): When outcome is "error", the call may have crashed before producing cost, latency, input, or output. Include these fields if available, but omit them if the data doesn’t exist — don’t fabricate values.

Rules

  • input and output are required on the last step unless outcome is "error"
  • output is forbidden when is_last_step is false
  • input is allowed on any step — it overwrites the session’s stored input
  • On success, output should contain everything you want the judge prompt to evaluate — typically the agent’s response, and optionally reasoning or tool calls
  • For multi-step sessions (e.g. resumed or suspendable workflows), increment step_index per step (0, 1, 2…) and report the final step with is_last_step: true
  • If your agent retries a step, report each attempt with the same step_index but increment attempt_number (1, 2, 3…). All attempts are recorded

Code examples

Report metrics asynchronously so it doesn’t block your agent’s response. The examples above retry up to 3 times with exponential backoff. Duplicate (session_id, step_index, attempt_number) reports safely overwrite previous data.
Serverless runtimes (Vercel, AWS Lambda, Cloud Functions) may terminate your function immediately after you return the response, killing any in-flight fire-and-forget requests. To avoid losing metrics, either await the ingest call (with a short timeout) before returning, or use your platform’s execution extension (e.g. Vercel’s waitUntil).