Agent Expiration · spec v0.1 · draft

Ten fields so authorization has a shelf life.

A platform that records these ten things about each agent can answer the questions that matter when something goes wrong: when was it last alive, when does its authority lapse, who renews it, what can wake it, what can it touch, who else can it call, and who owns it. Nothing here is novel. It's housekeeping, written down so it can be checked.

Fields

FieldTypeMeaning
agent_idrequiredstringStable identifier. Survives renames and redeploys.
ownerrequiredstringA named person or on-call rotation accountable for this agent. Empty means orphaned, and orphaned is a finding, not a default.
issued_atdate-timeWhen the current credential was issued. Rotation age starts here.
last_run_atrequireddate-timeLast time the agent actually executed. Dormancy is measured from here, not from deployment.
expires_atrequireddate-timeWhen the agent's authority lapses unless renewed. Must be a real date. "Never" is not a value; it is the absence of a control.
revoke_on_idle_daysintegerIdle threshold after which credentials are revoked automatically, regardless of expires_at. Dormancy revokes; re-enabling is a human decision.
renewed_bystringWho or what may extend expires_at. A person, a role, or a signed approval flow. If the agent can renew itself, write that down and expect the question.
trigger_signingrequiredenumrequired · optional · none. Whether the agent refuses unsigned wake-up calls.
trigger_sourcesstring[]Allowlist of principals, services, or networks that may invoke the agent. An empty list with trigger_signing: none means anyone who finds the endpoint.
reachrequiredobject[]Each system the agent can touch: {system, tier, mode}. tier is public · internal · sensitive · regulated. mode is read · write · delete. This is the blast radius, written in advance.
delegates_tostring[]Other agents this one can invoke. Delegation to an agent with different permissions is how a wake becomes a chain.

Nine named fields plus reach's three sub-fields. Ten is a round number; the point is that none of them are optional in spirit.

Rules

An agent with no live credential has nothing to act with. That is the whole control.

Example

{
  "agent_id": "invoice-reconciler",
  "owner": "m.chen",
  "issued_at": "2026-07-01T00:00:00Z",
  "last_run_at": "2026-08-14T03:10:00Z",
  "expires_at": "2026-09-29T00:00:00Z",
  "revoke_on_idle_days": 60,
  "renewed_by": "finance-platform-oncall",
  "trigger_signing": "required",
  "trigger_sources": ["svc://erp-events", "cron://nightly"],
  "reach": [
    { "system": "erp-ledger", "tier": "regulated", "mode": "write" },
    { "system": "object-store/invoices", "tier": "sensitive", "mode": "read" }
  ],
  "delegates_to": ["vendor-lookup"]
}

Read it the way the inventory would: last run August 14, idle window 60 days, so this agent's authority lapsed on October 13 and it has been overdue since. Signed triggers only, so it cannot be woken from outside. The credential should already be revoked. If it is not, that is the finding.

JSON Schema

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://agentshelflife.com/spec/v0.1/agent-expiration.schema.json",
  "title": "Agent Expiration v0.1",
  "type": "object",
  "required": ["agent_id", "owner", "last_run_at", "expires_at", "trigger_signing", "reach"],
  "additionalProperties": true,
  "properties": {
    "agent_id": { "type": "string", "minLength": 1 },
    "owner": { "type": "string", "minLength": 1 },
    "issued_at": { "type": "string", "format": "date-time" },
    "last_run_at": { "type": "string", "format": "date-time" },
    "expires_at": { "type": "string", "format": "date-time" },
    "revoke_on_idle_days": { "type": "integer", "minimum": 1 },
    "renewed_by": { "type": "string" },
    "trigger_signing": { "type": "string", "enum": ["required", "optional", "none"] },
    "trigger_sources": { "type": "array", "items": { "type": "string" } },
    "reach": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["system", "tier", "mode"],
        "properties": {
          "system": { "type": "string" },
          "tier": { "type": "string", "enum": ["public", "internal", "sensitive", "regulated"] },
          "mode": { "type": "string", "enum": ["read", "write", "delete"] }
        }
      }
    },
    "delegates_to": { "type": "array", "items": { "type": "string" } }
  }
}

Conformance checklist

Six questions a platform can answer yes or no to. A platform that answers yes to all six has given its agents a shelf life.

  1. Every agent record carries a real expires_at. No nulls, no sentinel "never."
  2. Idle agents lose their credentials automatically. revoke_on_idle_days is enforced by the platform, not by a reminder email.
  3. Renewals leave a record. Who extended, when, for how long.
  4. Unsigned external triggers are rejected or flagged. The platform can list every agent for which they are allowed.
  5. Reach is declared and enforced. Access outside the declared reach is blocked or alerted.
  6. Orphans are reported at creation. The platform can list every agent without an owner, today.

CSV mapping for the inventory

The inventory accepts a flattened CSV with these columns. Dates may be given as YYYY-MM-DD or as days ago.

agent_id, owner, group, last_run_at, credential_state, trigger, reach_count, reach_tier, reach_mode, delegates_to

trigger collapses trigger_signing + trigger_sources into one of scheduled · signed · internal_unsigned · external_unsigned. reach_* summarizes the worst entry in reach. delegates_to is a count. group is any cohort label you want the portfolio view to split on.

Why "shelf life"

Food has a printed date because the thing inside changes whether or not anyone looks at it. Authorization is the same. A credential issued in July is not the same object in October: the person who approved it may have moved on, the system it reaches may have changed sensitivity, the trigger that wakes it may now be reachable from places it wasn't. The date on the label is a forcing function for a question nobody wants to schedule: is this still supposed to exist?

Good housekeeping, hygiene, manners for machines. Pick the metaphor you like. The control is the same: authority evaporates by default, and keeping it alive is a decision someone signs.