Skip to content

Extension proposal: Autonomy Envelope + liveness-gated authority (bounded delegation that suspends when an agent goes dark) #2323

Open

Description

@atharnouman

Following the extension governance process, this is a Proposal Phase issue: an abstract, the motivation, and an initial technical approach. I am gauging whether maintainers see this as in scope before doing more work in this direction.

Abstract

An A2A extension that lets an agent present, and a counterparty verify, two things the protocol does not carry today:

  1. An Autonomy Envelope: a principal-signed, attenuable statement of what the agent may do unsupervised: permitted actions, resource patterns, a per-transaction cap and a windowed cumulative budget in a declared unit, allowed and denied counterparties, remaining delegation depth, and an expiry.
  2. Liveness-gated validity: the envelope's authority is conditioned on a signed heartbeat. An agent that stops heartbeating (crash, partition, abandonment) loses its authority by protocol, not by someone's cleanup script, and regains it on recovery with the same identity. A heartbeat proves recent use of the agent key, not that the key is uncompromised: a stolen key is contained by the passport's short expiry and the envelope's bounds, and explicit revocation by the principal is a separate mechanism (specified in LAP, not yet implemented).

It binds to A2A rather than replacing anything: declared as an AgentExtension in the Agent Card's capabilities, activated per message through the message's extensions URI list, and carried as a compact JWS that the receiving agent verifies before acting on a task.

Motivation

An Agent Card describes what an agent can do and how a caller authenticates to it (skills, interfaces, security schemes). It does not express what the agent is allowed to do without a human in the loop, on whose authority, within what limits, or whether it is still running. For long-running or overnight interactions between strangers' agents, a counterparty has no standard way to learn: "this agent may spend up to X in this unit with these counterparties, under a responsible principal, and its authority suspends if it goes quiet."

The existing security schemes do not cover this. API keys, OAuth 2, OIDC and mTLS authenticate a caller to a server. OAuth scopes are opaque strings granted by that server; they cannot express budgets, time windows, counterparties, or delegation with provable attenuation (a verifier being able to check that a delegated envelope is a subset of its parent), and none of them has liveness semantics. The gap is a mandate from a principal, bounded and verifiable by a stranger, that decays when the agent goes dark.

Initial technical approach

This draws on an existing open specification, the Living Agents Protocol (LAP), which already has two interoperating implementations; the extension would be a profile of it for A2A.

  • Passport (the carrier). A compact JWS (alg: EdDSA, keys as did:key, claims in RFC 8785 canonical JSON) issued by the principal for the agent: iss = principal, sub = agent key, aud = the receiving agent, short exp, and the envelope inside. Holder-of-key: each message is additionally signed by the agent key over the message's content digest (an RFC 9421 style signature base), so a captured passport authorizes nothing elsewhere and a mutated message fails its digest.
  • Envelope grammar (the algebra). A deliberately closed scope algebra: a versioned registry of actions (no string-prefix inheritance), segment-tokenized resource patterns with terminal-only wildcards, a two-dimensional cap (per-transaction ceiling plus a windowed cumulative budget), counterparty allow/deny sets with effective-set semantics, delegation depth, and a decay window. Subset checking is decidable, so a verifier can confirm that a delegated envelope attenuates its parent, including that the scopes inside one envelope do not replicate the parent's budget. Conservation across separately issued sibling envelopes is not visible to a verifier that sees only one of them: it belongs to the issuer, or to a spend authorizer with an atomic per-bucket ledger, and an A2A profile would have to name which. Both implementations are checked against shared test vectors and a property-based fuzzer whose cross-implementation decision digest fails the build on any disagreement.
  • Liveness. Signed pulses chained to the agent's log head; the envelope carries decay_max_sec. A verifier treats the authority as suspended once the pulse gap exceeds it. Suspension is prospective only: work not yet started is held rather than failed and resumes when a pulse from the same identity returns; work already started completes or rolls back under its interaction contract; and a signed idempotency key on every mutating message keeps resumed work from repeating an external effect, provided the claim is durable and written before the effect; a claim whose executor died after the effect may have happened is indeterminate until reconciled (LIP-4 recovery rule, 2026-10-21). A principal's explicit halt is a separate, immediate act that does reach in-flight work. This is demonstrated with two real processes over sockets: one is killed mid-session, the other's authority suspends, a pending order holds, recovery completes it, and a replay re-verifies every signature.
  • Binding sketch. The Agent Card declares an AgentExtension with a URI for this extension (to be assigned under the governance namespace rules) and params naming the supported proof classes and algorithms. Per message, the sender lists the extension URI in extensions and places the passport JWS and the message signature in message metadata under extension-scoped keys. The receiver verifies the JWS and audience, checks that the requested action, resource and amount are admitted by the envelope, checks liveness, executes, and returns a signed receipt binding the request and response hashes. Nothing in the core protocol changes; agents that do not declare the extension are unaffected.

I would write this up in the extension specification format if there is appetite.

Status, honestly

Independent v0 draft by one author; no consortium. Everything referenced above exists and runs: a zero-dependency Node library and a Python port proven byte-identical against shared vectors, a ten-check conformance challenge for independent implementations, a 15-minute tutorial binding the same mechanism to an MCP server, registration of agent genesis records in Sigstore's public transparency log, and a written threat model that says what is not defended. Open problems are documented rather than hidden: key custody, principal proofing, and the single-writer (clone) problem.

Ask

Is this a direction the maintainers would consider sponsoring as an experimental extension under the governance process? If it is better placed as an independent extension outside the organization, or simply out of scope, that answer is just as useful and saves me from writing the wrong thing.


Edited 16 October 2026 after the review in the first comment: liveness now covers unavailability rather than key compromise, budget conservation is claimed per envelope rather than across separately issued siblings, and suspension is described as prospective only. Nothing else changed.

Edit 2026-10-21: the idempotency clause narrowed per the recovery case raised by @haot3x below; the rule is in LIP-4 and the extension draft v0.3.

Activity

  1. jarrettdustinqq commented on Oct 8, 2026

    @jarrettdustinqq

    Two security-boundary corrections look necessary before this is represented as an experimental A2A extension:

    1. A pulse proves recent key use, not absence of hijack. The abstract groups “hijack” with crash/abandonment and says authority returns when the same identity pulses. But LAP v0.4.10 says a compromised agent key acts inside its envelope until exp, and cloned keys can fork state. A hijacker holding that key can emit valid pulses. The extension’s formal claim should therefore be limited to liveness/unavailability suspension; hijack recovery needs a separate principal revocation/key-rotation/expiry path, with a negative test showing that a pulse cannot override revocation.

    2. Static attenuation cannot prevent aggregate sibling-budget replication. The issue says a verifier can confirm that sibling delegations do not replicate a budget. LIP-3 §6 instead states that static verification covers one child at a time and separately issued siblings require issuer-side accounting. To make the stronger A2A claim enforceable, the binding must choose an enforcement locus: an online authorizer/shared atomic per-bucket ledger, or non-overlapping budget partitions with serialized issuance, plus concurrency and replay tests. Otherwise the claim should be narrowed to per-envelope attenuation.

    There is also an in-flight semantic mismatch: this issue says missed pulses hold work and later resume it, while the founding document says passive suspension is prospective-only and already-started work completes or rolls back per its interaction contract; explicit FORCE_HALT is distinct. The A2A profile should choose one rule and specify phase/reconciliation behavior so a resumed task cannot duplicate an external effect.

    These are scope/claim corrections, not objections to the extension route. I reviewed tagged LAP v0.4.10 (63a7680) and the A2A proposal process. AI-assisted review; I verified the cited text and current thread state before posting.

  2. atharnouman commented on Oct 15, 2026

    @atharnouman
    Author

    Thank you. This is the review the proposal needed, and all three points hold. I checked each one against the cited v0.4.10 text and have edited the issue to narrow the three claims (edit note at the end).

    1. Hijack. Agreed. A pulse proves recent use of the agent key and nothing more, so a hijacker holding the key keeps pulsing. The claim is now limited to unavailability: crash, partition, abandonment. Today a stolen key is contained only by the passport's short exp and the envelope's bounds (THREAT-MODEL §6). The principal's explicit revocation (FORCE_HALT, founding document §4, L5 item (e)) is specified but not implemented; when it is, it will ship with the negative test you describe: a valid pulse after revocation must not restore authority.

    2. Sibling budgets. Agreed. Verification is per envelope: inside one child envelope, the scope set must conserve the parent's budget (LIP-3 §6), so five narrow scopes cannot each carry the full cap. Two separately issued siblings are invisible to a verifier that sees only one of them; conservation across them is the issuer's duty, or a spend authorizer's with an atomic per-bucket ledger (founding document §8). The issue now claims per-envelope attenuation only. If the extension goes ahead, the A2A profile would name its enforcement locus explicitly, and non-overlapping partitions with serialized issuance is a lighter option worth specifying next to the authorizer ledger.

    3. In-flight semantics. Agreed. The issue text contradicted the founding document, and the founding document is the rule: suspension is prospective only. Work not yet started is held and resumes on recovery, work already started completes or rolls back under its interaction contract, and FORCE_HALT is the act that reaches in-flight work. The demo was consistent, since its held order had not started; the issue's wording was not. Against duplicate external effects on resumption, the profile would require a signed idempotency key on every mutating message, claimed atomically before execution with three states (reserved, in flight, completed with the stored receipt), plus re-verification before each settlement phase (L5 item (f)). The MCP binding of the same mechanism already implements the idempotency claim, and its tests cover a replayed key returning the stored receipt without executing twice.

    If you see other places where the proposal claims more than the specification delivers, I would rather hear it now than after a sponsor reads it.

  3. haot3x commented on Oct 20, 2026

    @haot3x

    One recovery case beyond the held-before-start demo: an external effect completes, then the process dies before storing its receipt. Should the A2A binding keep that key indeterminate until reconciliation rather than retry automatically? I checked the documented process-local cache boundary here; a durable claim still needs an explicit recovery rule.

  4. atharnouman commented on Oct 21, 2026

    @atharnouman
    Author

    @haot3x Yes. Thank you for the probe; it reproduces exactly the documented process-local limit, and your question is the one the specification did not answer.

    The rule now written into LIP-4 and the extension draft (v0.3): the reservation is written durably before the external effect, the completion after it. A claim whose executor died between the two is indeterminate. An indeterminate key is refused (LAP_ERR_REPLAY, with a reason that names reconciliation), never re-executed, and never released by the passage of time. It resolves only by reconciliation against the effect's system of record: completed with the reconciled result, and a receipt minted over it, if the effect happened; released if it verifiably did not, after which the same key executes fresh. Where the effect cannot be queried, the decision belongs to the deployment, a compensating action or a person, and is never inferred from a missing receipt. The client side matters as much: a client refused as indeterminate must not mint a new key for the same intent.

    Both reference caches now carry the state (mark_indeterminate / release, with tests), the Python middleware refuses an indeterminate key with that reason, and the issue text above is narrowed: the key prevents repetition only when the claim is durable and written before the effect (edit note at the end). Detecting a dead executor is the durable backend's job, now a stated MUST (a lease the executor renews).

    One question back: in the case you had in mind, is the effect queryable afterwards (an id the system of record returns), or not? The non-queryable case is where an A2A profile would need a stated default, and I would rather state yours than invent one.

    (Written with Claude's help; the rule and the tests are mine to answer for.)

  5. haot3x commented on Oct 21, 2026

    @haot3x

    In the probe, yes—the fsynced temporary file lets us check whether the simulated effect happened; it is not a real payment. For a real service, I would query its system of record using a stable operation ID. If that is unavailable, my default would be to keep the intent indeterminate, with no automatic retry or new key, until explicit reconciliation or compensation. The v0.3 rule fits that case.

  6. atharnouman commented on Oct 22, 2026

    @atharnouman
    Author

    @haot3x Thanks. Your default is now the rule's default, and the one thing it added is in both drafts: the reservation should record a stable identifier for the effect at its system of record (the idempotency key where the system accepts one, otherwise the identifier it returns, written as soon as it is known), so that reconciliation has something to query; without one the claim stays indeterminate until a person or a compensating action resolves it. No automatic retry, no new key. LIP-4: https://github.com/atharnouman/living-agents-protocol/blob/main/output/lip/LIP-4-micro-core-draft.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions