# Saying what the agent did, in the commit and the review

> Get an agent's change ready for review, say in the pull request what the agent did and what you checked, and attribute it in a commit trailer with no sign-off the agent cannot give.

Page: https://schubergphilis.github.io/ai-training/coding-with-agents/attribution-and-review-norms/
License: CC BY-SA 4.0, https://creativecommons.org/licenses/by-sa/4.0/

An agent fixed a bug in the nightly sales import, the tests pass, and you
are about to open a pull request. A reviewer reads what you send this
week and decides how closely to look. Someone who reads the history a
year from now wants to know who made the change and who checked it. In
this lesson we write the commit message and the pull request for both
readers. The first half covers the team's review agreements, and the
second half covers how the commit says that an agent helped, and what
only a person may add to it.

The [lesson on saying that AI helped](https://schubergphilis.github.io/ai-training/safety/saying-ai-helped/) gave a
disclosure line three parts: what the AI did, what the person checked, and
who is accountable. A pull request needs the same three parts, and a
commit holds them in a form that tools can read.

## Before you ask for a review

Review norms are the agreements a team makes on how agent-assisted
changes are reviewed. Teams write them down in different words. These
are the points most of them share.

**The author reads every line first.** You asked for the change, and you
are its first reviewer. The steps are the ones from
[reviewing the diff](https://schubergphilis.github.io/ai-training/coding-with-agents/reviewing-the-diff/). When you
request a review, you tell the reviewer that you understand the change
and think it is right. If they find a line you never read, they learn
that your request meant less than that.

**The description says what the agent did and what you verified.** Name
the part the agent wrote, the checks you ran yourself, and what you
didn't check. "The agent ran the tests" reports what the agent said. "I ran
the tests, and the new one fails on `main` and passes here" reports what
you saw.

**The reviewer reads the diff.** The description tells the reviewer where
to look, and the diff is what gets merged. A description written by an
agent can describe the change it meant to make and not the one it made.
An agent's change goes through the same gates as any other change: the
CI run and a reviewer's approval. "The agent tested it" doesn't replace
either, because the agent's tests are part of the change under review.

**The change is small enough to read.** An agent writes code much faster
than a person can review it. A diff that's too large to read gets
skimmed or blocked. Split it before you ask. Put a mechanical rename in
its own pull request, and keep each change to one purpose. A tidy-up the
agent made on the side belongs in a separate pull request, or at least
in the description.

Your team may have its own list, often in the project's agent
instructions file or in `CONTRIBUTING`. Where the two differ, follow the
team's list. When you disagree with one of its rules, propose a change
to the file and keep to the rule until the team agrees.

#### Checkpoint: A 3000-line agent diff

You asked an agent to add a monthly report to a service. The branch it
produced also renames the logging calls in forty files, "for
consistency". The diff has about 3000 changed lines and CI passes. What
do you do before anyone reviews it?

- Open the pull request as it is, with the note "agent-generated, CI is green" so the reviewer knows what to expect.
- Merge it yourself. CI passed, the agent ran the tests, and a review of 3000 lines would take a colleague a whole day.
- Split it into a rename pull request and a report pull request, read both, and say in each what the agent did and what you checked.
- Ask two reviewers to take half of the files each, so the review of the 3000 lines is shared and goes faster.

#### Pitfall: The agent wrote that part

A reviewer asked why a new function caught every exception and returned
an empty list. The author replied: "The agent wrote that, I didn't touch
it." The reply tells the reviewer that nobody read the function, and it
leaves the question open. The tool can't answer for the change, so the
person who opened the pull request answers for all of it. Reply as the
author: "I missed that. It should fail loudly, and I'll fix it and add a
test."

## Saying it in the commit

Attribution means recording in the change itself that an agent
contributed, next to the person who directed and checked the work. In a
commit it goes in a **trailer**. Git reads trailers from the last
paragraph of a commit message, after a blank line, as lines in the form
`Key: value` (git-interpret-trailers, Git reference documentation). Tools read them from
there, so a line in the middle of the body that looks like a trailer is
only text.

Several forms are in use. GitHub shows a commit as written by more than
one person when the message ends with a `Co-authored-by: name <email>`
line for each of them (Creating a commit with multiple authors, GitHub documentation).
The Linux kernel asks for an `Assisted-by` tag that names the AI help, in
a format its guideline gives (AI Coding Assistants, The Linux kernel documentation). Claude Code adds
a `Co-Authored-By` trailer to its commits by default. Its
`attribution.commit` setting changes that trailer to the one the project
asks for, and an empty value removes it (All settings, Claude Code documentation).
Whichever agent you use, check the form the project asks for, and read the
trailer block of each commit before you push it.

The commit's author is still you. Git records an author for every commit,
the identity of the person who made it unless someone sets another one
(git-commit, Git reference documentation). The trailer adds the agent. It doesn't take your
name off.

The fixture for this lesson is in the course repository under
`site/examples/coding-with-agents/attribution-and-review-norms/`. The
agent wrote `commit-message.txt`, and `trailers.py` runs
`git interpret-trailers --parse` on it, which prints only the lines git
reads as trailers.

#### Checkpoint: Which lines are trailers?

This is the agent's commit message:

```text
fix: read quoted amounts in the nightly import

The importer split "1,250.00" into two fields. It now reads each row
with the csv module, so a quoted amount stays one field.
Assisted-by: Claude:claude-sonnet-4-6
I also tidied up the date parsing while I was in the file.

Signed-off-by: Coding Agent <agent@example.com>
```

Before you run it, write down what the script prints for this message.
Then copy the directory and run it to check.

```sh
python3 trailers.py
```

The only trailer git finds is the one line the agent must not write. The
`Assisted-by` line is in the body, so a tool that counts agent-assisted
commits misses this one.

## The sign-off only a person gives

The `Signed-off-by` trailer is older than coding agents. `git commit -s`
adds one with the committer's name, and the git documentation says that
what it means depends on the project. In the Linux kernel and Git
projects, and in others that adopted it, it certifies the Developer
Certificate of Origin (DCO) (git-commit, Git reference documentation). The DCO is a short
statement in four parts. In our words: I made the contribution, in whole
or in part, and have the right to submit it under the project's license,
or it is based on earlier open-source work I may submit, or someone who
certified one of these gave it to me and I didn't change it. And I agree
that the contribution and my sign-off are kept on public record (Developer Certificate of Origin, version 1.1, developercertificate.org).

Each part is a statement about a person's rights and knowledge, and an
agent has neither. The Linux kernel guideline says it directly: an AI
agent must not add a `Signed-off-by` tag. The person who submits the
change reads the code, makes sure its license fits the project, signs off in
their own name and answers for the result (AI Coding Assistants, The Linux kernel documentation).
Sign off yourself only after you have read the change, because the
sign-off says you know where the code came from.

This course's own repository is a worked example. The last commit on
`main` when this lesson was written ended like this:

```text
Co-Authored-By: lsimons-bot <bot@leosimons.com>
Assisted-by: Claude:claude-opus-5-5
```

The `Co-Authored-By` line names a bot account, and the `Assisted-by`
line names the agent and the model. The commit's author is the
maintainer, and the message has no sign-off.

#### Checkpoint: Which trailer block?

Ana's project requires a DCO sign-off on every commit and asks for an
`Assisted-by` trailer when AI helped. An agent wrote the change, and Ana
read every line and ran the tests. Which trailer block does the commit
end with?

- `Signed-off-by: Ana Costa <ana@example.com>` and nothing else, since she read the diff and is the author of record.
- `Assisted-by: Claude:claude-sonnet-4-6` and `Signed-off-by: Claude <agent@example.com>`, since the agent wrote the code.
- `Assisted-by: Claude:claude-sonnet-4-6` and `Signed-off-by: Ana Costa <ana@example.com>`, added after she read it.
- `Assisted-by: Claude:claude-sonnet-4-6` alone, since a person signing off on code she did not type would be dishonest.

## Exercise

Rewrite the agent's commit message and pull request description from the
fixture directory, `commit-message.txt` and `pr-description.md`. The
pull request says only that "the agent fixed the bug" and that the agent
ran the tests. Write both as you would send them, in a copy of the
directory. Then run `python3 trailers.py` with your message file as its
argument to see which trailers git finds.

Take out the agent's sign-off. If your project asks for a sign-off, write
your own `Signed-off-by` line in the file, the line `git commit -s` would
add. In real work, add it only once you have read the change.
Decide what to do with the date-parsing tidy-up: take it out of this
change, or name it in both texts.

A good result: the message says what changed and why, and ends with one
trailer paragraph that `trailers.py` prints in full, `Assisted-by` in the
form this lesson used or the form your team uses. The pull request says
what the agent wrote, what you ran yourself and what you saw, and what
you didn't check. A reviewer could tell from it where to look hardest.

Reflect: which sentence in your pull request would you have left out if
this exercise had not asked for it, and what would the reviewer have
assumed without it?

Stretch: Look at the last ten commits in a repository your team uses with agents. Count how many name the agent in a trailer, and how many say so only in the body or not at all.

## Recap

1. Before you ask for review, read every line yourself and split a change that's too large to read. The pull request says what the agent did and what you checked, and the change goes through the same review and CI gates as any other.
2. Reviewers read the diff, and the description tells them where to look. Answer for the whole change as its author, including the parts the agent wrote.
3. Put the attribution in a trailer in the last paragraph of the commit message (git-interpret-trailers, Git reference documentation), in the form the project asks for, such as `Assisted-by` or `Co-authored-by`.
4. In a project that uses the Developer Certificate of Origin, a `Signed-off-by` line certifies it, and only a person can give that. An agent never signs off, and you sign off only after you have read the change (AI Coding Assistants, The Linux kernel documentation).

#### Habit

Before you push a commit that an agent wrote, read the last paragraph of
its message. It should name the agent the way your team asks, and it
shouldn't contain a sign-off that you didn't give.

## References

- git-interpret-trailers, Git reference documentation, https://git-scm.com/docs/git-interpret-trailers
- Creating a commit with multiple authors, GitHub documentation, https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors
- AI Coding Assistants, The Linux kernel documentation, https://docs.kernel.org/process/coding-assistants.html
- All settings, Claude Code documentation, https://code.claude.com/docs/en/settings-reference
- git-commit, Git reference documentation, https://git-scm.com/docs/git-commit
- Developer Certificate of Origin, version 1.1, developercertificate.org, https://developercertificate.org/
