On a growing number of teams, most of the code is written by an agent, and often by several different ones. Claude Code on one repository, Codex on another, Cursor in the editor, Jules picking up issues in the background.
That makes "which agent wrote this?" a question worth answering well. It decides which licences are earning their keep, which workflows are actually working, and what the AI adoption figure in the next board pack means.
The difficulty is that agents do not agree on how to identify themselves. Some sign every pull request. Some follow a naming convention. Some leave nothing on the pull request at all.
So we attribute agent work using four signals, strongest first. Here is each one, what it is good for, and what we learned putting them together.
#1. The Agent Says So
The strongest evidence is the agent's own account. Coding agents connected to the Coderbuds MCP server can report their work as they open a pull request: which tool wrote it, how much of it, and whether a person read the diff before it went up.
No inference beats that, so when an agent has reported a change, its report decides how the change is counted. Everything below exists to cover the work nobody reports, and there is always some.
#2. Signatures the Agent Writes Itself
Plenty of agents sign their work, and a signature is as good as a report for identifying the tool:
- Claude Code adds a "🤖 Generated with Claude Code" footer and a
Co-Authored-By: Claudetrailer - Cursor adds
Co-authored-by: Cursor <[email protected]>to its commits - Copilot, Devin and others commit as recognisable bot accounts
We score these at 100: the tool signing its own work.
One detail worth knowing: git reads trailer keys case-insensitively, and the tools do not agree on capitalisation. Claude Code writes Co-Authored-By; Cursor writes Co-authored-by. Match trailers in any case. Doing so attributed 45 more Cursor pull requests across the teams we measure.
#3. Conventions
Some agents do not sign, but they are consistent about where they work:
- Branch prefixes:
codex/,cursor/,claude/, and Jules'jules-…branches - Title prefixes, like Codex cloud's
[codex] - A link back to the agent task that produced the change
These are strong evidence, but a person can type a branch name too. So they score as High (90) rather than Definitive, and the pull request comment says what the verdict rests on, for example "going by its branch name". A reviewer should know whether they are looking at a signature or a convention.
Conventions only work if you record them. Store the branch for every pull request, not just the ones you happened to fetch in full. Once branch rules could see every branch, and the rules learned Jules' naming, re-running detection over June to September attributed:
- 176 pull requests to Jules
- 61 pull requests to Codex, ten times as many as before
#4. The Session
Some agents leave nothing on the pull request at all. Codex CLI run locally is the common one: no footer, no trailer, ordinary branch names. Reading the diff will not tell you.
But every agent says who it is somewhere else. An MCP client names itself when it connects to a server. Codex connects as codex-mcp-client, which you can confirm in Codex's own source. Claude Code's requests carry a claude-code/… User-Agent.
That becomes evidence as soon as you can tie a session to a pull request. Agents using Coderbuds check the size and scope of a change over MCP moments before they open it. That check records which agent ran it, and it is linked to the pull request that follows. So an agent that signs nothing on the pull request is still identified by the session that prepared it.
It scores 90, like a convention: it is evidence about the session, not the tool signing the change. It is also the signal that makes agents without signatures visible at all.
#What Is Not Evidence
Knowing what to ignore matters as much as knowing what to match.
A tool's name in the text. Search pull requests for the word "codex" and you will mostly find dependency bumps of the @openai/codex package and edits to .codex/ config files. Match the tool's work, not its name.
Release notes. Dependency bumps quote upstream release notes, and those now routinely include the upstream team's own "Generated with Claude Code" line. We do not attribute Dependabot or Renovate pull requests to coding agents at all. Across the teams we measure, that keeps 38 version bumps from being counted as agent work.
Absence. A pull request with no marker is not thereby a person's work. It may well be an agent that signs nothing. We label it unknown, because that is what it is.
#Measure Each Agent Separately
If you compare a detector against agents' own reports, look at the result one tool at a time.
An agent that signs every pull request will agree almost perfectly with a detector that reads signatures. That tells you a great deal about that agent and nothing about one that signs nothing. An aggregate figure describes whichever agent dominates your sample. A per-tool figure tells you where your coverage is thin, which is where the next signal needs to come from.
#The Rules Are Open Source
The detection rules behind signals two, three and four are published as coderbuds/ai-detector: one YAML file per tool, covering footers, trailers, bot authors, branch and title conventions, and now MCP clients.
The rules ship with fixture cases taken from real pull request shapes, including the ones that must not match, like a dependency bump of @openai/codex. A validator runs them in CI, so a new rule has to prove it catches what it should and leaves alone what it should not.
If your team uses an agent we do not cover yet, a rule and two fixtures is the whole contribution.
If you want to know what share of your team's work each agent is doing, built from these four signals and each agent's own reports, that is what Coderbuds does. You can also try the rules against a single pull request with the free AI code detector.