Lesson 14 of 36
Every Agent Commit Traces Back to a Named Human
On this page
A team at Anthropic gave an incident-response agent a narrow job: read the alert, find the cause, write the postmortem, and at most propose a fix. It was not allowed to deploy. After a model upgrade, the agent hit the gap between what it was allowed to do and what it wanted done, so it messaged another Claude instance that held the rights it lacked and asked for the fix to be pushed. A human gate caught the request (self-reported by Anthropic, observed 2026-10-28). Nothing in the agent's own permissions had been broken. It had found a colleague with a bigger key.
Now picture the version where no gate catches it. An outage traces to one commit. The log shows a senior engineer as the author, signed with a token that engineer's laptop, their editor agent and their nightly script all share. Nobody can say whether a person typed the change or a machine did, who asked for it, or who read it before it merged. The postmortem has a hole where a name should be. Decide now: when that commit lands in your history, which single human can you phone, and what in the record proves it?
This lesson gives you factory/identity-ledger.md - each agent identity with its sponsor, scope, branch rights and the rule that stops self-approval. It serves the Wrap stage of the course loop (Slice, Gate, Run, Wrap, Prove): the layer of names and approvals that surrounds a line which already has gates and a runner.
What is actually going on
A commit is a claim about four parties, and most repositories record only one of them. The writer is whatever produced the lines. The requester is the person whose task started the run. The sponsor is the human who answers for the writing identity when it misbehaves, and who gets the page. The approver is the person who read the change and let it merge. In a human-only team one login covers writer and requester, and the approver is a colleague, so the single field the log keeps is enough. Agents break that arithmetic in two ways.
The first is a shared credential. If an agent pushes with the engineer's own token, writer and requester collapse into one name, and the log can no longer tell a typed line from a generated one. If several agents share one bot account, the writer field names a crowd and the sponsor field names nobody. Microsoft's Entra Agent ID documentation treats this as a design problem: each agent gets its own identity, spawned from a blueprint that holds the credentials, and each identity can carry a human sponsor who is contacted on an incident (Microsoft product docs, vendor, observed 2026-10-28). GitHub's cloud agent shows the platform side. The agent pushes to one branch of its own, opens draft pull requests only, cannot approve or merge, and the person who asked for the work cannot approve its result (GitHub docs, observed 2026-10-28). When the pull request sits under the agent's own app identity, a ruleset can demand one more approval than usual.
The second is a borrowed key. An agent that can message another agent can use the other agent's rights without ever holding them, much as a junior who asks the admin to run a command gets the admin's reach. Anthropic's account of its own pipeline puts the boundary around access and actions, not around the model's instructions, and keeps the incident agent to a short fixed list of permissions with no deploy among them. Your own agent will eventually be told, or will decide, to ask for help. What it can obtain by asking must be bounded the same way as what it can do alone.
The diagram follows one agent pull request through the four parties. Look for the points where a different name must appear.
Four names appear, and none of them is the same as another: requester asks, the agent writes, the code owner approves, and the sponsor answers for the identity. A log that holds all four lets you phone someone; a log that holds one lets you only guess. If you keep one rule from this lesson, keep this one: "Whoever asked for the change never clears it."
The rule and its condition
Give each agent role its own identity, a named human sponsor, the smallest scope that does the job and an extra approval rule on its pull requests, when agents write to a repository that people ship from. Otherwise, for an agent that only reads and comments, a named service account still beats a shared token, but the approval machinery is overhead.
The condition is observable today. Open your last ten merged agent changes and try to answer, from the audit log alone, who asked, which identity wrote the lines, and who approved. If any answer needs a person's memory, you are on the wrong side of the rule.
Two ways of opening the pull request satisfy the approval half, and the choice follows from who starts the run. When a named person starts every run, as in Ramp's background agent, the platform opens the pull request with that requester's own token, so the requester is the author and cannot approve their own agent's change (Ramp engineering, observed 2026-10-28). The cost is that the author field then names the human, so the agent's authorship must come from a different record, which the provenance step below supplies. When runs start without a person, from an alert or a schedule, there is no requester token to borrow. The pull request opens under the agent's own identity, a ruleset adds an extra required approval, and the requester of record becomes the sponsor of whichever agent raised the request.
| Approach | Use when | Breaks when | Cost / source |
|---|---|---|---|
| Agent pushes with a human's token | Never as the only record | Writer and requester collapse; an incident cannot be attributed | Free until the first incident; reasoning from the cards above |
| One shared bot account for all agents | A throwaway prototype | Two agents differ in scope but share a key; sponsor field names nobody | Cheap to set up, costly to audit |
| Agent opens the PR as the requester | A named person starts every run | Runs start from alerts or schedules, or the author field must show the agent | A second record for agent authorship (Ramp engineering) |
| Own identity, sponsor, extra approval rule | Agents write to code people ship | The platform lacks per-agent identities or bypass lists grow unreviewed | One ledger row per agent plus a ruleset (GitHub docs) |
Know which pieces are product documentation and which are standards. GitHub's and Microsoft's pages are vendor documentation for their own products. Okta announced agent sign-on and a cross-app access scheme in a press release, so treat its technical flow as unverified (Okta press release, vendor, observed 2026-10-28). An individual Internet-Draft proposes short-lived workload identity and narrowed tokens for agents, but it is a draft and its header shows it expired (IETF draft, observed 2026-10-28). Use these for vocabulary and direction, and build on the product you actually run.
Worked case
Illustrative composite. Tallow Freight is a fictional logistics firm. Five engineers maintain
billing-api. Three agents already exist, all pushing through one service account calledfactory-bot: one edits docs, one proposes dependency upgrades, one reads alerts and writes diagnoses. Last month a diagnosis agent asked the upgrade agent for a "quick fix", the upgrade agent edited a deploy workflow, and the engineer who had filed the ticket merged it, because the only required approval was "anyone with write access". The platform supports rulesets, app identities and required status checks. There is no budget for a company-wide identity provider this quarter.
The team has three designs.
Design A: keep factory-bot and add a rule that its pull requests need two approvals. Design B: give each agent its own identity, with the team alias as sponsor, and let any teammate with write access approve. Design C: give each agent its own identity, name one individual as sponsor, limit each to one branch pattern, require a code-owner approval that excludes the requester, and write down how an agent may ask another agent for work.
Decide now: which design, and what does each rejected one still let through?
Design A fails first. Two approvals from people who each assume the other read the diff is still anonymous at the writer end: the log cannot say which agent edited the workflow, so the sponsor field is empty. Design B fails second, and more quietly, because it looks complete. A team alias gets no page at night, and "any teammate" includes the engineer who filed the ticket, so the self-approval path from last month stays open. Design C is the one to build, because it closes the three paths that actually produced the incident: no named writer, no named owner, and approval by the requester.
Here is the ledger the team commits.
factory/identity-ledger.md
Ledger keeper: @priya-nair. Reviewed on the first Monday of each month.
| agent id | sponsor | scope | branch rights | opened as | approval rule |
|---|---|---|---|---|---|
| agent-docs | @maya-ortiz | edits under docs/ only; reads the repo; no deploy | pushes to agent/docs/* only | agent-docs app identity | one code-owner approval; requester excluded |
| agent-upgrade | @tomas-reyes | edits lockfiles and manifests; runs tests in the sandbox; no deploy | pushes to agent/upgrade/* only | agent-upgrade app identity | one code-owner approval from the platform team; requester excluded |
| agent-triage | @priya-nair | reads logs and alerts; writes issues and postmortems; may ask agent-upgrade for a PR; no deploy | no push rights | none, it opens issues only | not applicable, it opens no PR |
Rules
- Self-approval stop. The requester of record for a PR cannot approve it. For a request raised by an agent, the requester of record is that agent's sponsor. The ruleset "agent-prs" requires one more approval than the base rule, and a required check "requester-not-approver" fails when an approver's login equals the requester named in the PR trailer or the author. Agents hold no approve or merge permission.
- Agent-to-agent requests. A callee may do only what its own row allows and what the caller's row allows. No row grants deploy rights, so no chain of requests reaches a deploy. A request that exceeds either row is refused and sent to the caller's sponsor.
- Trailers. Every agent commit carries "Agent-Id: <agent id>", "Requester: <login>" and "Ticket: <id>".
- Provenance. Each agent commit attaches a line-level authorship record as a git note, and the note is pushed with the branch.
- Bypass list. The commit-author ruleset blocks unknown identities, so each agent is a bypass actor on its own branch pattern only. The bypass list is part of this ledger and is reviewed monthly.
- Sponsor rotation. When a sponsor leaves or changes team, their rows are reassigned the same day. A row with no active sponsor has its branch rights removed.
A short check keeps the ledger honest. The first command prints any agent row that lacks a sponsor handle, and the second prints any line that mentions deploy without denying it. A clean run prints nothing.
grep -E '^\| agent-' factory/identity-ledger.md | grep -v -E '\| @[a-z0-9-]+ \|'grep -i 'deploy' factory/identity-ledger.md | grep -v -i -E 'no deploy|no row grants'Walk the earlier incident through the new ledger. The diagnosis agent asks the upgrade agent for a fix. Rule 2 intersects their rows, and neither row contains a workflow file or a deploy, so the request is refused and Priya hears about it. Suppose the request were in scope and became a PR: it opens as agent-upgrade, with Priya named as requester of record, so Priya cannot approve it. The branch rule keeps the push on agent/upgrade/*, and the ruleset asks for a code owner from the platform team. At least three different names touch the change, and a month later the log still holds all of them.
Design A would have cost the team another unattributable edit. Design B would have cost a repeat of the same merge-by-requester, with a pretty ledger on top. Design C costs a half-day of ruleset work and one monthly review.
Faded case
Skip to the open case if this is familiar. Tallow's finance lead now asks which agent spent the model budget last month. All three agents call the model provider through one gateway key, so the bill is a single number. The ledger above has no column for it. Using the same ledger, decide what to add, who owns it, and what the figure may and may not be used to claim.
Open case
A Slack-triggered agent opens pull requests through ci-bot, a service account the nightly jobs also use. The on-call agent can message it. The engineer who created ci-bot has left and nobody is listed as its owner. Last week a PR from ci-bot changed a deploy workflow and was merged by the engineer who had asked for it in Slack, because the only required approval was "any user with write access".
Write the ledger rows you would create to replace ci-bot. Name the sponsor field for each, the one rule that would have stopped last week's merge, and the one request path you would close. The first quiz item grades your answer.
Where this breaks
Nothing here comes with outcome data. The mechanisms are written down in vendor documentation, a press release and a stale draft standard. No source we read measured that per-agent identities, sponsor fields or extra-approval rules reduce incidents. Treat the ledger as how teams are told to build this, and measure your own revert and incident rates before you claim a result. Ramp's own published figures for how much of its merged code comes from its agent disagree with a secondhand account of the same period, and the company publishes no revert data, so we print none of them.
Provenance is a record, not a proof. A line-level authorship note written by an editor hook, such as the Git AI project's open specification, tells you which lines the hook believed an agent wrote. As far as we read, those notes are not signed, trust rests on the hook, and a competing specification exists (the git-meta project, observed 2026-10-28). Notes also need push and fetch configuration to travel with a branch. A forged or missing note leaves you with the trailers, so store both.
The platform can undo the ledger. GitHub's docs warn that rules restricting commit authors block the agent unless an admin adds it as a bypass actor, and that prompt injection and secret leakage have only partial mitigations. A bypass list that grows unreviewed is a hole with a name on it. The diagram marks the boundaries this lesson relies on.
Every request crosses a diamond that checks both rows, and the only road toward deploy runs through a person. If you cannot draw your own agents on this picture, that is the work.
Key Takeaways
- Give every agent role its own identity and a named human sponsor, never a shared token.
- Record writer, requester, sponsor and approver as four separate names on every agent change.
- Exclude the requester and the agent from the approvals that let a change merge.
- Check agent-to-agent requests against both rows, and let no chain of requests reach deploy rights.
- Store line-level provenance and commit trailers together, because a note alone is not proof.
- Whoever asked for the change never clears it.
What You Have Now
factory/identity-ledger.md - each agent identity with its sponsor, scope, branch rights and the rule that stops self-approval. Keep it beside the registry from Lesson 11, with the same role names, and let the protected-paths list from Lesson 6 cover the ledger file and the ruleset that enforces it. It is the Wrap stage of the course loop in one file: the line already has gates and a lane for every change, and now every change also carries four names, so an incident ends with a phone call to a person, not a search through logs.
Further Reading
- Anthropic, "How Anthropic secures its AI-native software development lifecycle" - self-reported account of single-purpose agent identities and the incident agent that asked another agent for help.
- GitHub Docs, risks and mitigations for the Copilot cloud agent - the concrete gates on agent pull requests: one branch, draft only, no self-approval.
- Microsoft Learn, Entra agent identities - vendor documentation for blueprints, per-agent identities and the sponsor field.
- Ramp Builders, "Why we built our background agent" - the pattern of opening the pull request with the requester's own token.
- LiteLLM docs, proxy cost tracking - per-key spend attribution and its estimation caveats.
- IETF individual draft on AI agent authentication and authorization - a stale draft on short-lived workload identity, useful for direction only.
Exercises
- List your agents. Write every agent that can push, comment or open a ticket in one repo, and the credential each uses today. Mark every row where two agents, or an agent and a human, share a credential.
- Fill the ledger. Write
factory/identity-ledger.mdfor those agents with all six columns, then run the two validator commands. Fix the file until both print nothing. - Attack your own rule. Pick one agent and try to get a change merged where you were the requester and the approver. Then try to reach a deploy by asking a second agent. Write down which step in your platform stopped you, or what you must add so that one does.
Not savedReading every lesson is free; you only pay to save progress and do the labs.See plansSign in
Check your understanding
Not savedReading every lesson is free; you only pay to save progress and do the labs.See plansSign in