Skip to content

Spec Proposal: Usage Policy — Token Quota Governance for Federated Agent Invocation #59

Description

@ejoaquin

The Problem

Agentic invocations are fundamentally different from traditional API calls. A single request may trigger multi-step LLM reasoning, tool chains, sub-agent calls, and iterative loops — compounding token usage unpredictably and without an upper bound visible to the consumer at request time.

In a federated ecosystem where agents from one enterprise's registry are invoked by consumers in another, this creates a cost governance gap:

  1. Unbounded cost exposure for publishers — A publishing enterprise exposes agents to federated partners. Without quota governance, the partner's workload can impose uncapped inference cost on the publisher's infrastructure.

  2. No feedback loop for consumers — Consuming registries have no protocol-level mechanism to know they're approaching a usage limit, or that their access will be degraded, until invocations start failing.

  3. Hard failures break workflows — Without a degradation model, quota exhaustion results in rejected requests. The consumer's orchestration chain breaks mid-execution with no recovery path.

  4. Rate limiting is insufficient — Traditional rate limits (requests/second) don't capture the real cost driver: token consumption. A simple query and a complex multi-step reasoning task may both be one request, but differ by 100x in token cost.

These gaps become acute in B2B federation where usage patterns are unpredictable, SLAs are contractual, and both parties need governed visibility into consumption.

Dependencies

This proposal depends on and extends:

Relationship to #53 (Federation Interoperability)

The federation lifecycle is: DISCOVER → AGREE → ENFORCE.

usagePolicy operates across two of these phases:

Phase usagePolicy Role
DISCOVER Agent Card declares executionContract.hasQuotaGovernance: true — consumers see quota terms exist before federating
AGREE Full usagePolicy object is negotiated as part of the execution contract during the mutual trust handshake
ENFORCE Publisher's policy gate tracks token consumption per consumer identity at the trust boundary; triggers thresholds and degradation

The usagePolicy object lives in the execution contract — the set of operational terms agreed during federation and enforced at runtime. It is referenced from the Agent Card in the discovery layer:

{
  "identifier": "urn:air:acme.com:finance:invoice-processor",
  "name": "Invoice Processor",
  "cardProvenance": { "..." },
  "contentIntegrity": { "..." },

  "executionContract": {
    "usagePolicyRef": "https://registry.acme.com/contracts/invoice-agent/usage",
    "hasQuotaGovernance": true,
    "degradationModes": ["informational-only", "block"]
  }
}

The executionContract block in the Agent Card is a pointer — it signals that usage terms exist and where to retrieve the full policy. The full usagePolicy object is resolved during the AGREE phase and becomes the runtime enforcement reference.

Proposal

Usage Policy Object (usagePolicy)

Add an optional usagePolicy object to the execution contract that defines consumption limits, threshold notifications, and degradation behavior:

"usagePolicy": {
  "tokenQuota": {
    "limit": 100000,
    "period": "PT24H",
    "scope": "per-consumer"
  },
  "thresholds": [
    { "percent": 50, "action": "notify", "channel": "webhook" },
    { "percent": 80, "action": "notify", "channel": "webhook" },
    { "percent": 100, "action": "degrade", "mode": "informational-only" }
  ],
  "degradedMode": {
    "informational-only": {
      "description": "Agent responds with cached/static information only. No LLM reasoning or tool execution.",
      "responseHeaders": {
        "X-Quota-Status": "degraded",
        "X-Quota-Resets": "<ISO8601>",
        "X-Quota-Remaining": "0"
      }
    },
    "block": {
      "description": "Requests are rejected with 429 status. Consumer must wait for quota reset or negotiate upgrade.",
      "responseHeaders": {
        "X-Quota-Status": "exhausted",
        "X-Quota-Resets": "<ISO8601>",
        "Retry-After": "<seconds>"
      }
    }
  },
  "notificationEndpoint": "https://consumer-registry.com/webhooks/quota",
  "quotaResetPolicy": "period-end",
  "upgradeEndpoint": "https://registry.acme.com/contracts/upgrade"
}

Field Definitions

Field Type Description
tokenQuota.limit integer Maximum tokens consumable per period
tokenQuota.period duration (ISO 8601) Quota reset interval (e.g., PT24H, P30D)
tokenQuota.scope enum Quota applies per-consumer (per federated registry) or per-agent (per individual agent invoked)
thresholds array Ordered list of threshold actions triggered at consumption percentages
thresholds[].percent integer Consumption percentage that triggers this action
thresholds[].action enum notify (alert consumer), degrade (reduce capability), block (reject requests)
thresholds[].channel string Notification delivery method (webhook, header, email)
thresholds[].mode string For degrade action: which degradation mode to activate
degradedMode object Named degradation behaviors — defines what the agent still provides when quota is constrained
notificationEndpoint URI Consumer-provided webhook for threshold alerts
quotaResetPolicy enum period-end (resets at period boundary) or rolling (sliding window)
upgradeEndpoint URI (optional) Where the consumer can request quota increases

Enforcement Semantics

Who enforces:

Threshold behavior:

  • notify — Advisory. Consumer receives a webhook notification but invocations continue normally
  • degrade — Active. Agent switches to the named degradation mode. Invocations still succeed but with reduced capability
  • block — Terminal. Requests are rejected until quota resets or is upgraded

Degradation model:

  • informational-only — Agent responds without invoking its LLM or executing tools. Returns documentation, capability descriptions, cached responses, or FAQ-style answers. The consumer's workflow receives a response (no hard failure) with headers indicating degraded status.
  • Custom modes MAY be defined by publishers for domain-specific degradation (e.g., read-only, summary-only, cached-24h)

Response headers:

  • All responses SHOULD include X-Quota-Remaining and X-Quota-Resets headers regardless of quota status — enabling consumers to implement client-side awareness without waiting for threshold notifications.

Consumer-Side Pre-Check (Optional)

Publishers MAY expose a quota status endpoint:

GET /federation/quota/status?consumer=registry.partner.com

Response:
{
  "consumer": "registry.partner.com",
  "tokenQuota": { "limit": 100000, "used": 72000, "remaining": 28000 },
  "currentPeriod": { "start": "2026-07-08T00:00:00Z", "end": "2026-07-09T00:00:00Z" },
  "status": "active",
  "nextThreshold": { "percent": 80, "action": "notify", "tokensUntil": 8000 }
}

This enables consumers to:

  • Check remaining quota before initiating expensive multi-agent workflows
  • Implement client-side backoff without waiting for rejection
  • Display quota dashboards in their own registry UI

Relationship to Trust State

Usage exhaustion is NOT a trust event — it does not affect mutualTrust.state (defined in #53). A consumer at quota is still trusted; they are simply rate-governed. The trust state machine and usage policy are independent axes:

Trust State Quota Status Outcome
mutual OK ✅ Full access
mutual Degraded ⚠️ Informational responses only
mutual Exhausted (block) 🚫 Rejected until reset
revoked Any ❌ No access regardless of quota

Trust governs whether you can call. Quota governs how much you can call.

Composability

Discovery Signaling

The Agent Card in ai-catalog.json signals quota governance at discovery time so consumers know terms exist before they federate:

{
  "identifier": "urn:air:acme.com:finance:invoice-processor",
  "executionContract": {
    "hasQuotaGovernance": true,
    "quotaSummary": {
      "defaultLimit": 100000,
      "defaultPeriod": "PT24H",
      "degradationModes": ["informational-only", "block"],
      "supportsPreCheck": true
    },
    "usagePolicyRef": "https://registry.acme.com/contracts/invoice-agent/usage"
  }
}

This is intentionally a summary — not the full policy. The full usagePolicy object is negotiated during the AGREE phase, where terms may be customized per consumer (e.g., premium partners get higher quotas).

Discussion Questions

  1. Should usagePolicy quota enforcement be publisher-side only, or should the spec define a normative consumer-side pre-check endpoint (GET /federation/quota/status)?
  2. Should quota be denominated in tokens only, or should the spec support alternative cost units (requests, compute-seconds, monetary value)?
  3. Should there be a standard escalation protocol — e.g., consumer can programmatically request quota increase via upgradeEndpoint, with the publisher's approval flowing through the same mutual trust mechanism?
  4. Should degraded responses carry a machine-readable capability delta (e.g., "these specific capabilities are unavailable in degraded mode") to help consumer LLMs adapt their planning?
  5. How should quota interact with multi-agent chains? If Agent A calls Agent B which calls Agent C across federation boundaries — whose quota is consumed?

Reference Implementation

The MCP Gateway and Registry (Apache 2.0, #40) could implement usagePolicy enforcement at its gateway layer — the gateway already intercepts cross-registry invocations and is the natural policy enforcement point for token accounting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions