Gong Agent Identity Protocol
A minimal cryptographic identity layer for autonomous AI agents. Hardware-anchored. Model-agnostic. Socially unengineerable.
Abstract
GAIP answers three questions every agent interaction requires:
- 1.Who authorized this agent?
- 2.What is it allowed to do?
- 3.Did it actually do what it claimed?
The root of trust is a human operator holding a hardware-bound key across multiple Apple Secure Enclave devices. No software-only path to signing exists. Any LLM on any platform can participate.
Core Concepts
Key Hierarchy
operator_key (hardware P-256, 2-of-N Shamir across devices)
│
├── HKDF("agent:research-1") → agent_key_1
├── HKDF("agent:coder-1") → agent_key_2
└── HKDF("agent:payments-1") → agent_key_3
│
└── HKDF("subagent:…") → sub_key
(narrowed permissions)Revoking the operator key invalidates the entire tree instantly. No key rotation ceremony. No chasing down API keys.
Share Custody — Operator Responsibility
Gong is a verification service, not a custodian.
Your key is yours. Gong never holds a share. Gong never sees your master key. Gong stores only your public key — the same information you would put on a business card.
Recommended hardware configuration:
Share 1 → iPhone (Apple Secure Enclave) Share 2 → Watch (Apple Secure Enclave) Share 3 → iPad (Apple Secure Enclave) Share 4 → Cold storage (printed, laminated, stored offline) Share 5 → Trusted contact (sealed envelope, lawyer or spouse) Threshold: any 2 of 5 reconstruct your key.
You can lose your iPhone, Watch, and iPad simultaneously and still recover using shares 4 and 5. Gong is not in that chain.
- ✓ Your public key
- ✓ Commitment history
- ✓ Agent registrations
- ✗ Any share
- ✗ Your master key
- ✗ Anything that could impersonate you
Recovery Protocol
Loss of a single share: use any other two to re-enroll. Loss of two or more shares without cold storage: identity is unrecoverable. This is correct behavior.
Recovery requires one valid share and a mandatory 72-hour waiting period. During that window:
Hour 0 Recovery initiated
→ All recovery contacts notified
→ Any active enrolled device can ABORT
Hour 0–72 Abort window — real owner can cancel
Hour 72 If no abort received:
→ Old identity retired permanently
→ New pubkey enrolled
→ Old shares cryptographically tombstonedThe guarantee with no exceptions:
- Gong cannot recover your identity.
- Gong cannot be compelled to recover your identity.
- Gong cannot shorten the 72-hour window.
- Gong cannot be socially engineered into bypassing recovery.
Support staff have no recovery capability — by design, not policy. There is no internal escalation path. This makes social engineering structurally impossible.
API Endpoints
Verify an agent's signature — stateless, no account required, always free
// Request
{
"pubkey": "ecdsa-p256-v1:04ab…", // agent's P-256 public key
"payload": "string, max 4 KB", // the claim being signed
"timestamp": 1714256789, // unix seconds (±300s window)
"signature": "ecdsa-p256-v1:3045…" // ECDSA-P256-SHA256 over payload+"|"+timestamp
}
// Response 200 — signature valid (default: pure crypto, zero storage)
{
"ok": true,
"pubkey": "ecdsa-p256-v1:04ab…",
"verified_at": 1714256789
// no "enrolled" field — we stored nothing, we logged nothing
}
// Response 200 — with ?enrolled=true (costs one DB read)
{
"ok": true,
"pubkey": "ecdsa-p256-v1:04ab…",
"enrolled": true,
"signer_name": "Jeff Gong",
"verified_at": 1714256789
}
// Response 401 — bad signature
{ "ok": false, "error": "signature invalid" }
// Response 429 — rate limited (100 req/min per IP)
{ "ok": false, "error": "rate limited — 100 req/min per IP" }# Python (cryptography)
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
import time
canonical = f"{payload}|{int(time.time())}"
sig = key.sign(canonical.encode(), ec.ECDSA(hashes.SHA256()))
# sig is DER-encoded — prefix with "ecdsa-p256-v1:"
# Node.js (WebCrypto)
const canonical = `${payload}|${Math.floor(Date.now()/1000)}`
const sig = await crypto.subtle.sign({name:'ECDSA',hash:'SHA-256'}, privateKey,
new TextEncoder().encode(canonical))
// sig is ArrayBuffer — hex-encode, prefix with "ecdsa-p256-v1:"Human operator delegates authority to an agent keypair
// Request (signed by operator's Gong key)
{
"operator_id": string,
"agent_pubkey": string, // "ecdsa-p256-v1:04…"
"agent_name": string,
"model": string, // "claude-opus-4-6" | "gpt-4o" | …
"permissions": string[], // ["read","write","pay:100","spawn"]
"expires_at": integer, // unix seconds, max 90 days
"operator_signature": string
}
// Response 200
{ "agent_id": string, "registered_at": integer }Agent signs a commitment to an action — permanent, auditable
// Request (agent-signed)
{
"agent_id": string,
"action": string, // human-readable description
"payload_hash": string, // sha256:<hex> of actual payload
"counterparty_id": string, // agent_id or "public"
"signature": string
}
// Response 200
{
"commitment_id": string, // permanent
"signed_at": integer,
"chain_hash": string // sha256(prev_commitment_id || this_id)
}Agent Negotiation Flow
Two agents agree on a task, commit cryptographically, deliver, and create a permanent auditable trail — all without a human in the loop.
1. Agent A → GET /api/agent/verify/:agent_b
Confirms: valid, not revoked, has required permissions
2. Agent A → POST /api/agent/sign
action: "hire agent_b for: <task description>"
Gets: commitment_id abc-123
3. Agent A → Agent B
{ task, commitment_id: "abc-123", agent_id: "agent-a" }
4. Agent B → GET /api/agent/commitment/abc-123
Verifies A actually committed to the terms
5. Agent B Does the work
6. Agent B → POST /api/agent/sign
action: "delivered to agent_a, commitment:abc-123"
Gets: delivery_commitment_id xyz-456
7. Agent B → Agent A
{ result, delivery_commitment_id: "xyz-456" }
8. Agent A → GET /api/agent/commitment/xyz-456
Verifies delivery, accepts work
Audit trail: two commitment IDs, cryptographically linked
to human operators. Fully attributable. Permanent.System Prompt Snippet
Include this in any agent's system prompt to onboard it to the Gong trust network. Copy the template and fill in your values.
You have a Gong identity.
Your pubkey: {AGENT_PUBKEY} # "ecdsa-p256-v1:04…"
Your private key is in your secure context — never transmit it.
To prove you authorized an action, sign this payload:
canonical = "{your_claim}|{unix_timestamp}"
POST https://server.gong.com/v1/agent/verify
{ pubkey, payload, timestamp, signature }
Rules:
- Sign every consequential action before executing it
- Include the verification URL when handing off work to another agent
- Timestamps must be within ±300s of real time — keep your clock synced
- Your operator is accountable under law for your signed actions