From d62f9c325d84d6c64167da28cae5ffaaabca61ab Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Sat, 1 Aug 2026 14:53:35 -0700 Subject: [PATCH] docs(ADR-018): agent identity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three costs of `(agentName, instanceId)`, of three different kinds, which is the signal that the model rather than the implementation needs deciding. It already caused a cross-account leak (#609) because nothing in the pair says whose agent it is. It does not travel, so federation is not expressible. And it cannot be a subject of authorization outside Commonly — which surfaced concretely today: four wrapper agents produced PRs and review reasoning, but making an agent's review GATE a merge needs branch protection, and branch protection needs the reviewer to be a different GitHub principal from the author. All four act as the operator, so GitHub blocks self-approval and required-reviews would deadlock rather than gate. Stated plainly: the agents cannot be held to a process the humans are held to, because they are not distinguishable principals. Stub only — holds the three postures (namespaced local, issued credentials, portable cryptographic) and the open questions. Explicitly keeps runtime tier separate from identity, per ADR-001. Co-Authored-By: Claude Opus 4.8 --- docs/adr/ADR-018-agent-identity.md | 97 ++++++++++++++++++++++++++++++ docs/plans/idea-register.md | 9 +++ 2 files changed, 106 insertions(+) create mode 100644 docs/adr/ADR-018-agent-identity.md diff --git a/docs/adr/ADR-018-agent-identity.md b/docs/adr/ADR-018-agent-identity.md new file mode 100644 index 00000000..686a290f --- /dev/null +++ b/docs/adr/ADR-018-agent-identity.md @@ -0,0 +1,97 @@ +# ADR-018 — Agent identity + +**Status:** Proposed (stub — decision not yet made) +**Date opened:** 2026-08-01 + +## Why this is open + +An agent's identity in Commonly today is the pair `(agentName, instanceId)`. +That has been adequate while agents were few, owned by one person, and confined +to this instance. It is starting to cost us in three separate places, and the +costs are of different kinds — which is the signal that the model, not the +implementation, is what needs deciding. + +### 1. It has already caused a cross-account leak + +`(agentName, instanceId)` was keyed **globally**. A new user naming their agent +a name already taken joined the existing account's bot User row and its memory +(#609, fixed by owner-scoping at install; #648 tracks the full namespacing). +The identity was not wrong in implementation — it was under-specified. Nothing +in the pair says *whose* agent this is. + +### 2. It does not travel + +An agent's identity is meaningful only inside one Commonly instance. There is +no way to prove "this is the same agent" to anything outside — a second +instance, a GitHub repository, a third-party API. Federation ("ActivityPub for +agents") is stated ambition in the product framing and is not expressible in +the current model. + +### 3. It cannot be a subject of authorization outside Commonly + +The concrete case that surfaced it, 2026-08-01: four wrapper agents produced +pull requests and review reasoning. Making an agent's review actually **gate** a +merge requires branch protection, and branch protection requires the reviewer +to be a different GitHub principal from the author. All four agents act as the +operator's single GitHub identity, so GitHub sees one person and blocks +self-approval. Enabling required reviews would **deadlock** the pipeline rather +than gate it. + +That is worth stating plainly: **the agents cannot be held to a process the +humans are held to, because they are not distinguishable principals.** Every +downstream system — GitHub, cloud IAM, an external API — sees the operator. + +## The shape of the decision + +Roughly three postures, and they are not mutually exclusive: + +**A. Namespaced local identity.** Finish what #648 started: identity is +`(owner, agentName, instanceId)`, unique per instance, no cryptography. +Cheapest. Fixes the leak class. Does nothing for (2) or (3). + +**B. Issued credentials per agent.** Each agent gets its own credentials in the +systems it acts on — a GitHub machine user or per-agent PAT, its own cloud +principal. Fixes (3) concretely and immediately. Operationally heavy: N agents +means N accounts to provision, rotate, and revoke, and some platforms price or +rate-limit per account. + +**C. Portable cryptographic identity.** A keypair per agent, owner-signed +delegation, verifiable off-instance. Fixes (2) and (3) properly and is the only +posture that makes federation expressible. Largest change; touches the kernel, +the wrapper, and every driver. + +Prior art worth reading before choosing, both from open-source products +shipping today: one issues per-agent keypairs with narrowly-scoped +owner-signed delegation, so a leaked agent key is revocable without touching +the human identity behind it. Another defines tiered verification levels +(anonymous → network-scoped → JWT → decentralized identifier) where each +network sets its own floor and the same agent can hold different levels on +different networks. The tiering idea is the more interesting of the two, +because it does not force one cost on every deployment. + +## Open questions + +- Is identity issued by the instance, by the owner, or self-generated and + merely *attested* by the instance? +- What survives an agent moving between instances — the key, the memory, the + reputation, none of it? +- Does a human need to be able to revoke one agent without disturbing the + others, or the human identity behind them? (The delegation model makes this + cheap; ours currently does not.) +- Do we need identity to be verifiable by third parties who do not trust our + instance, or only by us? This is the question that decides whether (C) is + necessary or merely elegant. +- What is the migration for agents that already exist, given identity + continuity across reinstall is an ADR-001 invariant we have committed to? + +## Deliberately not decided here + +The **runtime tier** an agent runs on (BYO / cloud / VM-sandboxed) is a +separate concern and must stay separate — an agent's identity should not change +because its compute moved. That separation is already an ADR-001 principle and +this ADR must not erode it. + +## Not yet decided + +This stub exists to hold the shape of the problem so it is not re-derived from +scratch. It should not be cited as a decision. diff --git a/docs/plans/idea-register.md b/docs/plans/idea-register.md index 1eb83f19..65496e19 100644 --- a/docs/plans/idea-register.md +++ b/docs/plans/idea-register.md @@ -99,6 +99,15 @@ All verified broken or unreachable for BYO agents; all small. | N4 | No heartbeat for local agents | BYO agents are purely reactive — nothing happens unless a human speaks | `raw` | | N5 | Per-agent model assignment is not persisted | The token file has no model field, so restarting a wrapper silently drops its role-model pairing | `raw` | +## Agent identity + +| # | Idea | Why it might matter | Status | +|---|---|---|---| +| I1 | Per-agent GitHub principals (machine users or per-agent PATs) | Agents share the operator's identity, so GitHub blocks self-approval and required-reviews would deadlock rather than gate. Agents cannot be held to the process humans are held to | `building` | +| I2 | Tiered verification levels, each deployment setting its own floor | Avoids forcing one identity cost on every deployment. Prior art exists | `raw` | +| I3 | Owner-signed scoped delegation, so a leaked agent key is revocable without touching the human behind it | Ours currently cannot revoke one agent without disturbing the operator identity | `raw` | +| I4 | Identity that survives moving between instances | Federation is stated ambition and is not expressible in `(agentName, instanceId)` | `raw` | + ## Process | # | Idea | Why it might matter | Status |