Version: 0.1.0
Status: RFC
Date: January 2026
Agent Trace is an open specification for tracking AI-generated code. It provides a vendor-neutral format for recording AI contributions alongside human authorship in version-controlled codebases.
- Motivation
- Goals
- Non-Goals
- Terminology
- Architecture Overview
- Core Specification
- Extensibility
- Reference Implementation
- Appendix
As agents write more code, it's important to understand what came from AI versus humans. This attribution is both the models used as well as the related agent conversations. Agent Trace defines an open, interoperable standard for recording this attribution data.
- Interoperability: Any compliant tool can read and write attribution data.
- Granularity: Support attribution for models used at file and line granularity.
- Extensibility: Vendors can add custom metadata without breaking compatibility.
- Human & Agent Readable: Attribution data is readable without special tooling.
- Code Ownership: Agent Trace does not track legal ownership or copyright.
- Training Data Provenance: We don't track what training data influenced AI outputs.
- Quality Assessment: We don't evaluate whether AI contributions are good or bad.
- UI Agnostic: Agent Trace does not require any specific interface.
| Term | Definition |
|---|---|
| Contribution | A unit of code change (addition, modification, or deletion) |
| Contributor | The entity that produced a contribution (human or AI) |
| Trace Record | Metadata describing a contribution's origin |
| Type | Code | Description |
|---|---|---|
| Human | human |
Code authored directly by a human developer |
| AI | ai |
Code generated by AI |
| Mixed | mixed |
Human-edited AI output or AI-edited human code |
| Unknown | unknown |
Origin cannot be determined |
Agent Trace is a data specification, not a product. It defines how to record attribution data. Storage mechanisms are implementation-defined. The spec is unopinionated about where traces live.
The fundamental unit of Agent Trace is the Trace Record:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://agent-trace.dev/schemas/v1/trace-record.json",
"title": "Agent Trace Record",
"type": "object",
"required": ["version", "id", "timestamp", "files"],
"properties": {
"version": {
"type": "string",
"pattern": "^[0-9]+\\.[0-9]+$",
"description": "Agent Trace specification version (e.g., '1.0')"
},
"id": {
"type": "string",
"format": "uuid",
"description": "Unique identifier for this trace record"
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "RFC 3339 timestamp when trace was recorded"
},
"vcs": {
"$ref": "#/$defs/vcs",
"description": "Version control system information for this trace"
},
"tool": {
"$ref": "#/$defs/tool",
"description": "The tool that generated this trace"
},
"files": {
"type": "array",
"items": {
"$ref": "#/$defs/file"
},
"description": "Array of files with attributed ranges"
},
"metadata": {
"type": "object",
"description": "Additional metadata for implementation-specific or vendor-specific data"
}
},
"$defs": {
"vcs": {
"type": "object",
"required": ["type", "revision"],
"properties": {
"type": {
"type": "string",
"enum": ["git", "jj", "hg", "svn"],
"description": "Version control system type"
},
"revision": {
"type": "string",
"description": "Revision identifier (e.g., git commit SHA, jj change ID)"
}
}
},
"tool": {
"type": "object",
"properties": {
"name": { "type": "string" },
"version": { "type": "string" }
}
},
"file": {
"type": "object",
"required": ["path", "conversations"],
"properties": {
"path": {
"type": "string",
"description": "Relative file path from repository root"
},
"conversations": {
"type": "array",
"items": {
"$ref": "#/$defs/conversation"
},
"description": "Array of conversations that contributed to this file"
}
}
},
"contributor": {
"type": "object",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"enum": ["human", "ai", "mixed", "unknown"]
},
"model_id": {
"type": "string",
"maxLength": 250,
"description": "The model's unique identifier following models.dev convention (e.g., 'anthropic/claude-opus-4-5-20251101')"
}
}
},
"conversation": {
"type": "object",
"required": ["ranges"],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "URL to look up the conversation that produced this code"
},
"contributor": {
"$ref": "#/$defs/contributor",
"description": "The contributor for ranges in this conversation (can be overridden per-range)"
},
"ranges": {
"type": "array",
"items": {
"$ref": "#/$defs/range"
},
"description": "Array of line ranges produced by this conversation"
},
"related": {
"type": "array",
"items": {
"type": "object",
"required": ["type", "url"],
"properties": {
"type": { "type": "string" },
"url": { "type": "string", "format": "uri" }
}
},
"description": "Other related resources"
}
}
},
"range": {
"type": "object",
"required": ["start_line", "end_line"],
"properties": {
"start_line": { "type": "integer", "minimum": 1 },
"end_line": { "type": "integer", "minimum": 1 },
"content_hash": {
"type": "string",
"description": "Hash of attributed content for position-independent tracking"
},
"contributor": {
"$ref": "#/$defs/contributor",
"description": "Override contributor for this specific range (e.g., for agent handoffs)"
}
}
}
}
}{
"version": "0.1.0",
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-01-23T14:30:00Z",
"vcs": {
"type": "git",
"revision": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
},
"tool": {
"name": "cursor",
"version": "2.4.0"
},
"files": [
{
"path": "src/utils/parser.ts",
"conversations": [
{
"url": "https://api.cursor.com/v1/conversations/12345",
"contributor": {
"type": "ai",
"model_id": "anthropic/claude-opus-4-5-20251101"
},
"ranges": [
{
"start_line": 42,
"end_line": 67,
"content_hash": "murmur3:9f2e8a1b"
}
],
"related": [
{
"type": "session",
"url": "https://api.cursor.com/v1/sessions/67890"
}
]
}
]
},
{
"path": "src/utils/helpers.ts",
"conversations": [
{
"url": "https://api.cursor.com/v1/conversations/12345",
"contributor": {
"type": "ai",
"model_id": "openai/gpt-4o"
},
"ranges": [
{
"start_line": 10,
"end_line": 25
}
]
}
]
}
],
"metadata": {
"confidence": 0.95,
"dev.cursor": {
"workspace_id": "ws-abc123"
}
}
}Ranges are grouped by conversation, with contributor metadata at the conversation level. This reduces cardinality when one conversation produces many ranges.
Line-level attribution:
{
"files": [
{
"path": "src/utils.ts",
"conversations": [
{
"url": "https://api.example.com/v1/conversations/abc",
"contributor": {
"type": "ai",
"model_id": "anthropic/claude-sonnet-4-20250514"
},
"ranges": [
{ "start_line": 10, "end_line": 25 },
{ "start_line": 30, "end_line": 45 },
{ "start_line": 80, "end_line": 95 }
]
},
{
"url": "https://api.example.com/v1/conversations/def",
"contributor": { "type": "ai", "model_id": "openai/gpt-4o" },
"ranges": [{ "start_line": 50, "end_line": 52 }]
}
]
}
]
}Line numbers are 1-indexed. Ranges reference positions at the recorded revision.
Agent Trace supports multiple version control systems through the vcs field:
// Git
{ "vcs": { "type": "git", "revision": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0" } }
// Jujutsu (using change ID for stability across rebases)
{ "vcs": { "type": "jj", "revision": "kkmpptxz" } }
// Mercurial
{ "vcs": { "type": "hg", "revision": "a1b2c3d4e5f6" } }The revision field format is VCS-specific:
- git: 40-character hex commit SHA
- jj: Change ID (stable across amend/rebase operations)
- hg: Changeset identifier
Line numbers in a trace refer to positions at the recorded revision, not current positions. To query ownership of a specific line of code:
- Use VCS blame to find the revision that last touched line N
- Look up the trace for that revision and file
- Find the range containing line N
For tracking attribution across code movement, use content hashes at the range level:
{
"files": [
{
"path": "src/parser.ts",
"conversations": [
{
"url": "https://api.example.com/v1/conversations/abc",
"contributor": {
"type": "ai",
"model_id": "anthropic/claude-opus-4-5-20251101"
},
"ranges": [
{
"start_line": 10,
"end_line": 25,
"content_hash": "murmur3:9f2e8a1b"
}
]
}
]
}
]
}The hash applies to the specific range, allowing tracking even when code moves within or between files.
Model identifiers follow the models.dev convention:
{
"contributor": {
"type": "ai",
"model_id": "anthropic/claude-opus-4-5-20251101"
}
}Format: provider/model-name
Each conversation has a url field and optional related array for linking to related sub-resources:
{
"files": [
{
"path": "src/api.ts",
"conversations": [
{
"url": "https://api.example.com/v1/conversations/abc123",
"contributor": {
"type": "ai",
"model_id": "anthropic/claude-opus-4-5-20251101"
},
"ranges": [{ "start_line": 10, "end_line": 50 }],
"related": [
{
"type": "session",
"url": "https://api.example.com/v1/sessions/xyz789"
},
{
"type": "prompt",
"url": "https://api.example.com/v1/prompts/def456"
}
]
}
]
}
]
}- Major version: breaking changes to required fields
- Minor version: additive changes (new optional fields)
The metadata field can include implementation or vendor-specific data:
{
"metadata": {
"confidence": 0.95,
"post_processing_tools": ["prettier@3.0.0"],
"dev.cursor": {
"workspace_id": "ws-abc123"
}
}
}Vendors may use reverse-domain notation (e.g., dev.cursor, com.github.copilot) within metadata to avoid key collisions.
A reference implementation is provided in the reference/ directory, demonstrating how to integrate Agent Trace with coding agents. The implementation includes:
trace-store.ts: A storage layer for reading and writing trace recordstrace-hook.ts: Hook integration for automatic trace capture on file changes
The reference is an example for Cursor or Claude Code, but the patterns are applicable to any AI coding agent.
{
"version": "0.1.0",
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-01-25T10:00:00Z",
"files": [
{
"path": "src/app.ts",
"conversations": [
{
"contributor": { "type": "ai" },
"ranges": [{ "start_line": 1, "end_line": 50 }]
}
]
}
]
}| Type | MIME Type |
|---|---|
| Trace Record | application/vnd.agent-trace.record+json |
How should I store the traces?
This spec intentionally does not define how traces are stored. This could be local files, git notes, a database, or anything else.
How should I handle rebases or merge commits?
We expect to see different implementations in open source. This may influence the spec in the future. We are open to feedback.
What happens when agents create scripts to write code?
This is left to the implementation. Code generated this way should still be attributed to the agent. For example, you could snapshot files before and after the script runs, then use git diff to determine what the agent added.
This specification is released under CC BY 4.0.
Thanks to the following partners for helping shape Agent Trace:
This specification is accepting suggestions on GitHub.
