Skip to main content

PACT — Protocol for Agent Constitutional Trust

When an autonomous agent pays an invoice on your behalf, three questions follow your auditor: who approved the spend, how much could the agent ever spend, and how do we prove it after the fact? PACT is the lightweight protocol Invoica uses to answer all three on every settlement. A signed mandate travels with the request, encodes the human-authorized spend ceiling, and is verified against a shared secret before the invoice can transition to SETTLED. This page documents PACT v0.2 as implemented in Invoica today.

Why mandates, not just API keys

API keys authenticate the agent. They do not bound what the agent can spend. An agent with a working key plus a buggy retry loop could drain a budget overnight before anyone notices. A PACT mandate is a separate, narrower authorization:
  • Signed by the grantor (the human principal or their key-management service)
  • Scoped to a specific grantee (the agent identity)
  • Capped at a maxPaymentUsdc ceiling — enforced at the invoice layer, not as a soft business rule
  • Expires automatically, so a leaked or replayed mandate has a bounded blast radius
  • Hash-bound to every settled invoice, so the audit trail reproduces who authorized what years later

Mandate shape

A PACT mandate is JSON with seven fields. The full shape:
Required fields enforced by the verifier: A mandate missing expiresAt or maxPaymentUsdc is rejected outright — no blank cheques. This is intentional (TICKET-044, P0).

Signature scheme

The signature is computed over a canonical JSON serialization of the mandate fields excluding signature itself, using HMAC-SHA256 with a secret shared between the grantor’s signer and Invoica:
Verification uses crypto.timingSafeEqual to compare expected vs. supplied signatures — constant-time, immune to timing-oracle attacks.

Sending a mandate with a payment

Include the mandate JSON in the X-Pact-Mandate header on any settle-side call:
If a mandate is present and valid, the settle proceeds. If a mandate is present but invalid or over-cap, the response is HTTP 403 with code: PACT_DENIED and a reason string. If no mandate header is present, the endpoint behaves as before — mandates are an additive trust layer, not a hard requirement.

Verification logic

The verifier rejects in five distinct cases: The verifier returns { allowed: true } only when all checks pass.

Helixa trust ceiling (PACT Chamber 2)

In addition to per-mandate caps, Invoica enforces a per-grantor reputation ceiling via Helixa. When a mandate is present, Invoica fetches the grantor’s current trust score and applies a tier-based USDC ceiling: If Helixa is unreachable, the policy is configurable via HELIXA_POLICY:
  • fail-closed (production default): denies the settle with HELIXA_UNAVAILABLE
  • fail-open (founder-only opt-in): proceeds without the ceiling check
Both the mandate cap and the Helixa ceiling must pass — the lower of the two wins.

Audit trail

Every settled invoice records the mandate hash in its paymentDetails.mandate_hash field, and (for ClinPay sessions) in the DRS receipt. Seven years on, you can reproduce:
  • Which mandate authorized the settle
  • Who the grantor was
  • What the maximum ever-authorized amount was
  • When the mandate expired
The mandate itself does not need to be stored — its canonical form + signature can be reconstructed from any copy a counterparty retains, and the hash is the proof.

Configuration

Two environment variables on the Invoica backend:

Versioning

PACT v0.2 is the current shipped spec (HMAC-SHA256 + canonical JSON). PACT v0.3.2 is what ClinPay receipts stamp into the DRS — the bump reflects the addition of the Helixa Chamber 2 ceiling and the synthetic-mandate shape used in the ClinPay sponsor → panelist flow. PACT lives as a separate package, @godman-protocols/pact, with the reference implementation maintained alongside Invoica.

Further reading