Building an AI Code Authorship Chain: Agent, Prompt, Model, and Reviewer Provenance
A provenance-record template and recording checklist for capturing the agent, prompt version, model, changed files, reviewer, and merge decision behind every pull request.
An auditor asks one question that git log cannot answer: for this release, who or what wrote each change, which checks ran, who approved it, and could the controls have been bypassed?
An AI code authorship chain answers that question by recording seven structured fields for every pull request: agent identity, prompt or task reference, model and version, instruction file revision, changed file paths, human reviewer, and merge decision including any documented exception. Those fields belong in commit trailers for durability, a typed server-side store for querying, and build attestations for the release link. This article gives you the record template, a placement checklist, and the reviewer handoff routine.
The gap is not laziness. Git records a commit author and email, and an agent inherits whatever identity the person who configured it supplied. A squash merge collapses the branch history and routinely discards the Co-authored-by trailer that was the only breadcrumb. And the three things that actually shaped the diff, the prompt, the instruction files in force, and the model version, live entirely outside the repository.
The Question an Auditor Asks That Git Log Cannot Answer
I have watched this conversation go badly twice. Both times the engineering team produced a clean commit history, a list of required status checks, and a screenshot of branch protection settings. Both times the auditor asked a follow-up the team could not answer: which of these changes were machine-generated, and how do you know?
Commit authorship is a self-asserted string. A coding agent running in CI commits as whatever identity the workflow configured, which might be a bot account, might be a service account shared across three tools, or might be a human engineer whose token the agent is using. None of those tell you which system generated the diff, or which version of that system.
The subtler loss is context. GitHub supplies repository custom instructions to Copilot as context for both code generation and code review [1]. That means the content of those instruction files materially shapes what the agent writes. If the file changed last Tuesday and a questionable pattern landed last Monday, the diff and the current instructions do not line up, and nothing in the repository records which revision was in force at generation time.
So the record has to be created deliberately, at the moment of generation and review, by something other than the contributor whose work is being recorded.
The Seven Fields That Make a Provenance Record Useful
Start with the minimum set that answers real questions. Each field below earns its place because a specific investigation fails without it.
- Agent identity: an enumerated value such as copilot-coding-agent, cursor-composer, or internal-refactor-bot. Comes from the workflow or client that opened the pull request. Without it you cannot scope a population of changes when one tool misbehaves.
- Prompt or task reference: an issue number, task ID, or session ID, plus a hash of the prompt. Comes from the orchestration layer. This is what lets you group sibling pull requests that share a lineage.
- Model and version: claude-sonnet-4.5, gpt-5.1, with the version string, not just the vendor. Behavior changes between versions. When you discover a pattern you dislike, you need to re-check the population of diffs produced by that specific version, and vendor name alone is too coarse to query.
- Instruction file revision: the commit SHA of the instruction files in force at generation time [1]. This is the field most teams skip and most need later.
- Changed file paths: the path list from the diff. You need this to intersect agent activity with CODEOWNERS-protected directories [2] and security-sensitive trees such as auth, payments, and infrastructure.
- Reviewer identity: the human who approved, resolved by the required-review rule, not the person who left a comment [4].
- Merge decision: three distinct states, not a boolean. Approved under normal rules, merged with a documented exception, or merged via a bypass. Collapsing those into "merged: true" destroys the only field a control tester cares about.
Model version and instruction revision are the two fields that turn a static log into something you can investigate with. Everything else describes the change. Those two describe the conditions that produced it.
A Record Template You Can Paste Into a PR Template Today
Here is a filled record. Type the fields so the store is queryable rather than free text: enumerated values for agent and decision, a semantic version for the model, a SHA for the instruction revision.
provenance:
schema_version: 1
agent:
id: copilot-coding-agent # enum
invoked_by: m.okafor
task:
ref: ENG-4417
prompt_sha256: 9f2c7a1e4b8d... # hash, not text
model:
name: claude-sonnet-4.5
version: "20250929"
instructions:
files: [".github/copilot-instructions.md", "services/billing/AGENTS.md"]
revision: 7c41ab9
changed_paths:
- services/billing/invoice_adjustment.py
- services/billing/tests/test_invoice_adjustment.py
review:
required_approvers: ["billing-owners"]
approved_by: ["s.reyes"]
automated_review: advisory
decision:
outcome: approved_normal # approved_normal | exception | bypass
exception_ref: nullIf you cannot run a sidecar service yet, compress the same payload into commit trailers. They survive history, they are cheap, and they are a reasonable first step.
Generated-By: copilot-coding-agent
Model: claude-sonnet-4.5@20250929
Instruction-Revision: 7c41ab9
Task-Ref: ENG-4417
Prompt-SHA256: 9f2c7a1e4b8d
Reviewed-By: s.reyes <sreyes@example.com>
Merge-Decision: approved_normalNote what is deliberately absent: raw prompt text, full context windows, and anything resembling credentials or customer data. Store a hash and a reference to a retained transcript if you have one, governed by your existing data retention policy.
Where This Metadata Should Actually Live
No single location does everything. Commit trailers survive but do not aggregate. A server-side store aggregates but can be edited. Attestations are verifiable but only describe the build.
| Location | Survives squash | Queryable across repos | Tamper resistance | Best for |
|---|---|---|---|---|
| Commit trailers | Yes, if written to the merge commit | Poor, requires log scraping | Low, author-controlled text | Durable baseline every team should start with |
| PR body or template | No, editable after merge | Poor | Very low | Prompting humans to supply missing fields |
| PR labels | N/A, metadata object | Moderate via API | Moderate, permission-gated | Coarse filters such as agent-authored |
| CI job output | No, logs expire | Moderate | Moderate, workflow identity writes it | Trusted capture point for the record |
| Typed server-side store | Yes, independent of git | Strong | Moderate to strong with append-only writes | Investigations and control reporting |
| Build attestation | Yes, signed statement | Via verification tooling | Strong, cryptographically verifiable | Linking the approved PR to the shipped artifact [6][7] |
Build attestations close the last gap. GitHub artifact attestations produce a signed, verifiable statement about how an artifact was built and from which source [6], expressed in the SLSA provenance format [7]. That is what connects an approved pull request to the binary or image that actually reached production.
For the bypass question specifically, the record you need is not in the repository at all. Organization audit logs capture administrative and security setting events, including changes to protective settings [8], which is how a control tester checks whether a gate was weakened rather than merely satisfied.
Layer them: trailers for durability, a typed store for query, attestations for the release link, audit log export for control integrity.
Stop Recording Provenance in Places That Erase It
Three failure patterns show up repeatedly.
The first is treating the agent vendor's dashboard or chat transcript as the record. It is convenient and it is not yours. Retention windows change, sessions are purged, and the export format is not under your control. Capture the fields you need into your own store at the time of the pull request.
The second is writing provenance only into the PR description. Contributors edit descriptions after merge, and the edit history is not something most teams can produce on demand in a form an auditor will accept.
The third is the most consequential: treating an automated review comment as evidence of approval. GitHub documents Copilot code review as a reviewer that can be requested on a pull request and that takes repository custom instructions into account [3], while required reviews and required status checks are configured separately through branch protection or rulesets [4][5]. Comments from an automated reviewer and required human approvals are independent mechanisms. Your record must keep them in separate fields, which is exactly why the template above has both automated_review: advisory and approved_by.
How Reviewers Use the Record During Handoff
An agent opens eleven pull requests overnight. The on-call reviewer arrives to a queue with no indication of which ones share a prompt lineage, which touch owned paths, and which were generated against instructions that have since changed.
A provenance summary at the top of the review changes the reviewer's job. Instead of re-reading each diff cold and reconstructing intent, the reviewer sees what context the agent had and spends attention on what the agent could not know.
Use this routine:
1. Confirm agent identity and model version against your approved list. An unexpected value is itself a finding.
2. Compare the instruction revision to current main. If they differ, read the diff of the instruction files before reading the code diff.
3. Intersect changed paths with owned and sensitive directories so you know whether a required owner approval applies [2][4].
4. Search for sibling pull requests sharing the task ref or prompt hash. Review them together or not at all.
5. Record the decision with a reason, selecting approved, exception, or rejected, and naming the rule involved.
Here is the case that sold the routine to one platform team I worked with. A reviewer saw a repository-wide retry wrapper reintroduced in a payments service, a pattern the team had rejected months earlier after a duplicate-charge incident. The provenance record showed the instruction revision predated the directory-scoped rule that banned it. The reviewer did not just reject the pull request. They moved the ban from a decision record into a path-specific instruction file so the next agent run would read it [1].
That is the discipline worth keeping: when a rule gets overridden in review, either the rule is stale and gets edited, or the exception gets documented. Either way the instruction file stays trustworthy, which is the point of our broader argument in this breakdown of the organizational context gap in AI coding assistants.
Mapping the Chain to SSDF, the AI RMF, and OWASP LLM Risks
You do not need a bespoke framework for agent-authored code. NIST SP 800-218 organizes secure development into practice groups covering preparing the organization, protecting software, producing well-secured software, and responding to vulnerabilities [9], and those practices apply identically whether a human or an agent wrote the change. Map each step of your agent workflow, task intake through release, onto a practice and name an owner.
The NIST AI Risk Management Framework, with its generative AI profile, gives you the govern, map, measure, manage structure for documenting the AI-specific layer [10]. Keep that documentation filed alongside your SSDF evidence rather than in a separate AI policy nobody reads.
The OWASP Top 10 for Large Language Model Applications is why provenance matters operationally rather than only for audit [11]. Issue text, code comments, dependency metadata, and fetched web pages are untrusted input that can carry injected instructions. If an injection lands, your provenance record becomes the blast-radius query: which pull requests used that agent, that model version, and that instruction revision, within that window. Without the record, the honest answer is "we would need to review every merge from the last quarter."
CISA's Secure by Design material covers the product-level expectations leadership increasingly fields from customers and regulators [12], and a working authorship chain is a concrete answer to those questionnaires rather than a policy assertion.
Where Connectory Fits Once the Chain Exists
A provenance chain only helps if something stores it as typed records and enforces its use. That is the attachment point for three Connectory components, and the order matters.
Genie holds policies, decisions, ownership, constraints, and evidence as typed server-side records. Instruction revisions and exception decisions stay queryable across repositories instead of sitting in markdown files that drift per repo. This is the layer described in more detail on the institutional memory page.
SlopBuster reviews pull requests against repository and organizational context and contributes its review signal into the record. It stays advisory. Required human approvals remain the merge gate, because mixing those two is the failure described earlier. Guardian handles the other side: enforcing merge gates and recorded exceptions with an audit trail, which is precisely the decision field in the template.
Two boundaries worth stating plainly. Provenance fidelity depends on what your agents actually emit; no store can reconstruct a prompt or model version the agent never reported, so expect partial records from tools with thin telemetry. And judge the result on delivery outcomes using DORA throughput and stability framing [13], not on how many provenance records you accumulated.
Frequently Asked Questions
Does git already capture this if we require signed commits?
Signing proves which key produced a commit. It does not identify the generating system, the model version, or the instructions in force. Signing and provenance answer different questions and you want both.
Should we store the full prompt?
Generally no. Store a hash and a task reference. Raw prompts accumulate customer data and occasionally secrets in a system that was never privacy-reviewed.
Does an AI review comment satisfy our review control?
No. Automated review comments and required approvals are configured and enforced separately [3][4]. Record them as separate fields and keep required owner approval on sensitive paths.
What if our agent does not report its model version?
Record the orchestrator version and the tool configuration you do control, mark the model field as unreported, and track the share of records with gaps. That gap list is a useful procurement conversation.
How long should we retain these records?
Align retention with your existing audit evidence period rather than inventing a new one, and name an owner for the store. Our notes on SOC 2 engineering controls cover how that mapping usually lands.
What to Do Next
Pick one repository where agents already open pull requests. Add the YAML provenance block to its pull request template, then write the same fields from a CI step so the record is produced by a workflow identity rather than the contributor. Expect this to take an afternoon, not a quarter.
Then start tracking one signal this week: the share of merged pull requests carrying a complete provenance record, broken out by agent. That number tells you which tools are opaque before an incident forces you to find out.
Finally, run the auditor's question against last month's release. Name the agent, the model version, the instruction revision, the approver, and whether any gate was bypassed. If you can answer for every change, you have a chain. If you cannot, you now know exactly which field is missing.
References
[1] GitHub Docs, "Add repository custom instructions for GitHub Copilot," 2025. https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions
[2] GitHub Docs, "About code owners," 2025. https://docs.github.com/en/repositories/managing-your-repos-settings-and-features/customizing-your-repository/about-code-owners
[3] GitHub Docs, "Using GitHub Copilot code review," 2025. https://docs.github.com/en/copilot/how-tos/use-copilot-agents/request-a-code-review/use-code-review
[4] GitHub Docs, "About protected branches," 2025. https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches
[5] GitHub Docs, "About rulesets," 2025. https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets
[6] GitHub Docs, "Using artifact attestations to establish provenance for builds," 2025. https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds
[7] SLSA, "Provenance specification v1.0," 2025. https://slsa.dev/spec/v1.0/provenance
[8] GitHub Docs, "Reviewing the audit log for your organization," 2025. https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/reviewing-the-audit-log-for-your-organization
[9] NIST, "SP 800-218: Secure Software Development Framework (SSDF) Version 1.1," 2022. https://csrc.nist.gov/pubs/sp/800/218/final
[10] NIST, "AI Risk Management Framework," 2025. https://www.nist.gov/itl/ai-risk-management-framework
[11] OWASP, "Top 10 for Large Language Model Applications," 2025. https://owasp.org/www-project-top-10-for-large-language-model-applications/
[12] CISA, "Secure by Design," 2025. https://www.cisa.gov/securebydesign
[13] DORA, "DevOps Research and Assessment," 2025. https://dora.dev/