{
  "$comment": "Machine-readable descriptor for the Geeks agent-payment rail. STATUS IS PLANNED — the endpoints below are a published contract, not a live service. Check status before integrating.",
  "name": "Geeks",
  "status": "planned",
  "status_detail": "Design complete and the spending guard is implemented and tested. No endpoint listed here is live yet. Do not build against this without checking https://www.geeksbank.com/ai first.",
  "docs": "https://www.geeksbank.com/ai",
  "unit": {
    "code": "de",
    "symbol": "dē",
    "kind": "mutual-credit",
    "denominated_in": "time",
    "issuance": "365 dē granted per verified human per year, plus a pro-rata grant at signup",
    "note": "dē is a promise of time between parties. It is not a crypto token, not backed by a reserve, not an investment, and does not appreciate. Agents never receive a grant — they spend their principal's balance."
  },
  "identity": {
    "principal": "person_hash",
    "principal_scheme": "sha256(lowercase(trim(email)))[0:20]",
    "actor": "agent_key",
    "rule": "Every entry names both. An agent never acts for itself; a key with no principal is refused."
  },
  "auth": {
    "flow": "device",
    "steps": [
      { "step": 1, "call": "POST /api/v1/agent/device", "body": ["agent_name", "scopes[]", "max_de"], "returns": ["user_code", "verify_url", "interval"] },
      { "step": 2, "actor": "human", "action": "Opens verify_url while signed in, reads the requested scopes and caps, approves or denies." },
      { "step": 3, "call": "POST /api/v1/agent/device/token", "body": ["user_code"], "returns": ["agent_key", "agent_secret", "person_hash", "limits", "expires_at"] }
    ],
    "headers": ["X-Geeks-Key", "X-Geeks-Secret"]
  },
  "limits": {
    "enforced_by": "server/agent-guard.js",
    "defaults": {
      "max_per_call_de": 0.5,
      "max_per_day_de": 5.0,
      "max_calls_per_min": 60,
      "max_spend_per_min_de": 1.0,
      "heartbeat_max_ms": 300000
    },
    "configurable_per_key": ["max_per_call_de", "max_per_day_de", "payee_allowlist", "scopes", "expires_at"]
  },
  "shutoff_valve": {
    "summary": "Automatic, fails closed, and never resumes on its own.",
    "trips": [
      { "code": "spend_velocity", "meaning": "too much value in a 60s window" },
      { "code": "call_velocity", "meaning": "too many calls in a 60s window" },
      { "code": "repeat_signature", "meaning": "the same endpoint and body repeated — a retry loop" },
      { "code": "error_ratio", "meaning": "a high share of failures — the agent is flailing" },
      { "code": "daily_cap", "meaning": "the daily ceiling would be passed" },
      { "code": "payee_violation", "meaning": "tried to pay someone not on the key's allowlist" },
      { "code": "heartbeat_lapsed", "meaning": "a long-running session went silent" }
    ],
    "on_trip": {
      "http_status": 423,
      "retryable": false,
      "clears": "only when the account holder clears it at /account/agents"
    }
  },
  "errors": {
    "402": "cost exceeded a ceiling — quote smaller or ask your human to raise the cap",
    "403": "refused: unknown key, revoked, expired, scope not granted, or cost not quoted",
    "409": "idempotency key replayed with a different body — this is not a second charge",
    "423": "the shut-off valve has tripped; a human must clear it"
  },
  "rules_for_agents": [
    "Quote before you charge. An unquoted cost is refused.",
    "A 402 inside your standing cap may be answered automatically. Anything above it needs a fresh human mandate.",
    "Never retry a 423. The valve does not clear on a timer and retrying is what tripped it.",
    "Replaying an idempotency key with a different body is a 409, never a second payment.",
    "An unknown balance is never an available balance."
  ]
}
