Elevator pitch
What are you proposing to change?ACP v2 should replace the v1
Diff shape’s ambiguous oldText / newText
fields with a structured diff content shape that can represent text patches,
non-text file changes, and file-level operations such as add, delete, modify,
move, and copy.
Every diff should carry structured file-change metadata. Text changes can also
carry renderable git patch text in an optional top-level patch field.
Status quo
How do things work today and what problems does this cause? Why would we change things?ACP v1 represents a diff as a path plus old and new text:
newText: ""cannot distinguish a deleted file from an empty file without an extra flag.- Moves and copies have no direct representation.
- Binary files, symlinks, and directory entries do not have useful
oldTextandnewTextvalues. - Clients have to reconstruct or parse a diff to render changes.
- The protocol cannot express whether a file path was added, deleted, modified, moved, or copied.
What we propose to do about it
What are you proposing to improve the situation?ACP v2 should make
ToolCallContent diffs carry a required changes array and
an optional patch object.
Use patch for changes that have useful renderable patch text:
git_patch. A single git patch can describe several
files, so the patch is top-level context for the whole changes array. Clients
can render the patch text directly for baseline compatibility, and can use
changes to identify affected paths and operations without parsing the patch.
Agents SHOULD provide patch whenever feasible. Clients MUST handle diffs
where patch is omitted or null.
Omit patch when patch text is not useful:
null patch values are equivalent and mean no renderable patch
text was provided.
The initial operation set should be:
adddeletemodifymovecopy
add, delete, and modify use path. move and copy use oldPath and
path. All paths in protocol payloads are absolute.
The optional fileType field should describe the file entry when known:
textbinarydirectorysymlink
mimeType field should carry a MIME type when known. Omitted and
null values for fileType and mimeType mean the value is unknown.
Shiny future
How will things play out once this feature exists?Clients can render text diffs without needing to synthesize patch text, and can show file-level summaries without parsing patch syntax. Agents can report binary updates, symlink changes, deletes, moves, and copies without forcing those cases through text-only fields. The v2 diff surface is also easier for SDKs to model because operations are explicit enum variants rather than inferred states from optional text fields.
Implementation details and plan
Tell me more about your implementation. What is your detailed implementation plan?
- Replace the v2
Diffstruct’s old text fields with a requiredchangesarray. - Add an optional
patchfield withformatanddiff. - Use
git_patchas the ACP-defined patch format, and document that Agents SHOULD provide it whenever feasible. - Add structured
DiffChangeoperation variants for add, delete, modify, move, and copy, with path fields owned by each operation variant. - Add optional
fileTypeandmimeTypefields for non-text and unknown file content. - Preserve custom or future operations where the receiver can safely store, replay, forward, or display a generic summary.
- Update generated schema and v2 protocol docs.
Frequently asked questions
What questions have arisen over the course of authoring this document or during subsequent discussions?
Why use git patch instead of unified diff?
Git patch is broadly supported, renderable as text, and can carry file-level headers for multiple files. ACP can still add future patch formats if another format becomes necessary, but v2 should define one default format first.Why is patch top-level instead of attached to individual changes?
Git patch text can describe several files and several operation kinds at once.
Keeping patch top-level makes it renderable context for the whole diff content
item, while changes remains the structured source for paths and operations.
Should patch text be restricted to some operation variants?
No. Git patches can represent adds, deletes, modifies, moves/renames, copies, and some binary changes. If an Agent has useful patch text for a set of changes, it can includepatch; otherwise it can omit it.
Why is patch optional if Agents SHOULD provide it?
Some changes have no useful patch text, especially same-path binary updates and
symlink target changes. Patch generation can also fail or be unavailable in a
given Agent implementation. Keeping patch optional lets clients rely on
structured changes, while the SHOULD encourages better rendering when patch
text is practical.
What kind of modify does not have a patch?
Mostly in-place non-text updates, such as a binary file update at the same path
or a symlink target change. Text modifications should normally use
patch so clients have renderable text.
Why include both patch text and structured changes?
Patch text gives clients an immediate baseline rendering path. Structured changes give clients operation and path metadata without requiring patch parsing, which matters for summaries, file trees, permissions, and non-text indicators.Revision history
- 2026-07-02: Initial draft