Skip to main content
A capability token is a short-lived, single-use credential that the SDK generates locally on your server for every eligible product response. It travels inside the _agentFeedback envelope as the submit.authorization value, giving a customer agent exactly enough authority to submit one outcome review — nothing more. Your product key never leaves your server, and agents never see it.
Your product key (af_live_...) is a server-side secret. It never appears in any response body, header, or envelope that reaches an agent. Only the derived, scoped capability token is shared.

Token format

Every capability token uses this three-part dot-separated structure:
A real token from the conformance test vector looks like this:

Claims

The claims object is serialized in this exact field order before encoding:
number
required
Protocol version. Always 1. The backend uses this to select the correct verification algorithm.
string (UUID)
required
The interaction ID. A randomly generated UUID v7 assigned at middleware time. The backend uses this to associate the submitted outcome with the correct interaction record.
number (Unix timestamp)
required
Issued-at time as a Unix timestamp (seconds since epoch). Records when the capability was created.
number (Unix timestamp)
required
Expiry time as a Unix timestamp. Set to no more than two hours after iat. The backend rejects any token presented after this time.
string (base64url)
required
A cryptographically random 18-byte nonce, base64url-encoded. Included to prevent identical-input collisions even if two capabilities share the same timestamps and interaction ID (which cannot happen in practice, but the nonce provides an additional layer of uniqueness).

How the SDK signs a token

The SDK performs all signing locally as part of building the response envelope. No network call is made to Agent Feedback at this stage.
  1. Extract the keyId (32 lowercase hex chars) and the full product key from af_live_<keyId>_<secret>.
  2. Derive the signing key: SHA-256(full_product_key) — the raw digest bytes, not a hex string.
  3. Generate a UUID interaction ID and 18 cryptographically random bytes for the nonce.
  4. Set iat to the current Unix timestamp and exp to iat + 7200 (two hours).
  5. Serialize the claims as compact JSON in the field order v, i, iat, exp, n.
  6. Base64url-encode the UTF-8 bytes of the JSON string (no padding).
  7. Form the signing input: "afr2_" + keyId + "." + encodedClaims.
  8. Compute HMAC-SHA256(signingKey, signingInput) and base64url-encode the result (no padding).
  9. Return signingInput + "." + signature.
The conformance.json file in the protocol repository contains a deterministic test vector you can use to validate your implementation of this algorithm.

Product key format

Your product key has this shape:
For example:
Keep this value in an environment variable and never commit it to source control. The SDK reads it at startup and derives the HMAC signing key from it once.

Security properties

Because the signing key is derived from your product key on your server, Agent Feedback can verify the capability’s authenticity without ever storing your product key in plaintext. The service verifies the HMAC signature on each incoming outcome submission using a one-way digest of your key — your raw product key is never accessible to the verification path.
A forged, expired, or revoked capability always returns 401 Unauthorized. The backend never provides a distinguishing error message between these cases, to avoid leaking information about key status.

What the capability does not contain

The claims carry only the minimum information needed for verification. A capability token never contains:
  • Your customer reference or any user identity
  • The agent’s prompt, instructions, or session context
  • Any product response data, query parameters, or content
  • Personal data of any kind
This means that even if an agent logs or forwards a capability token, no sensitive product or user data is exposed.