List changes
Returns what a coding run changed, read from the forge it pushed its branch to: the commits on its branch that the base does not have, newest first; the net change of the branch against its base, one entry per file with that file's patch; and its pull request with the reviews it has had, or null while it has none.
GET /v1/agent/coding/{session}/changes
| Address | https://api.hanzo.ai/v1/agent/coding/{session}/changes |
| Method | GET |
| Operation | get_agent_coding_by_session_changes |
| Auth | Authorization: Bearer $HANZO_API_KEY |
Returns what a coding run changed, read from the forge it pushed its branch to: the commits on its branch that the base does not have, newest first; the net change of the branch against its base, one entry per file with that file's patch; and its pull request with the reviews it has had, or null while it has none.
A run whose branch is not on the forge yet — still working, or finished with nothing to change — answers with no commits, no files and no pull request. Every read is made as the caller, so a repository they cannot open on the forge is not found here either, whoever can see the run.
One answer is bounded, and says where it was cut rather than failing: the
newest 250 commits (moreCommits when there are more), the change up to 8 MiB
of diff or 3000 files (moreFiles, the last file marked truncated), and the
first 50 reviews (moreReviews), each body up to 16 KiB and 256 KiB across
them (truncated on a cut one). A caller has at most two of these reads in
flight and is answered 429 past that; two asking for the same change at once
share one read.
Request
1 field.
| Field | In | Type | Required | Description |
|---|---|---|---|---|
session | path | string | yes | Session is the run's handle — the sessionId POST /v1/agent/coding answered with — from the path. |
Response
| Status | Body | Meaning |
|---|---|---|
200 | agent.CodingChanges | ok |
default | problem-details | refused |
200 body — 31 fields.
| Field | In | Type | Always | Description |
|---|---|---|---|---|
base | body | string | — | Base is the branch the run started from: the one it was given, or the repository's default. |
commits | body | agent.CodingCommit[] | — | Commits are the commits on head that base does not have, newest first. |
commits[].author | body | string | — | Author is the commit author's name as git recorded it; a run's own commits are authored by its harness. |
commits[].date | body | string | — | Date is the author date, RFC 3339 in UTC. |
commits[].message | body | string | — | Message is the commit's subject — its first line only. |
commits[].sha | body | string | — | SHA is the full commit hash. |
files | body | agent.CodingFile[] | — | Files is the net change head makes against its merge base with base, one entry per file. |
files[].additions | body | integer (int64) | — | Additions counts the lines the change adds, over the whole file whether or not all of its patch is carried. |
files[].deletions | body | integer (int64) | — | Deletions counts the lines the change removes, the same way. |
files[].from | body | string | — | From is where a renamed file was. |
files[].patch | body | string | — | Patch is the file's unified-diff hunks, from its first "@@". |
files[].path | body | string | — | Path is where the file is on the branch — for a deleted file, where it was. |
files[].status | body | string | — | Status is added, modified, deleted or renamed. |
files[].truncated | body | boolean | — | Truncated marks a patch cut short: at 64 KiB for one file, or past 1 MiB of patch across the change, when later files carry none. |
head | body | string | — | Head is the run's own branch. |
moreCommits | body | boolean | — | MoreCommits says the branch carries more commits than the newest 250 that Commits lists. |
moreFiles | body | boolean | — | MoreFiles says the change is larger than one read answers — past 8 MiB of diff or 3000 files — so Files lists the files before that, and the last of them is marked truncated with the counts of the part read. |
pull | body | agent.CodingPull | — | |
pull.mergeable | body | boolean | — | Mergeable is the forge's verdict that the base takes the branch without conflict. |
pull.moreReviews | body | boolean | — | MoreReviews says it has more reviews than the first 50 that Reviews lists. |
pull.number | body | integer (int64) | — | Number is the pull request's number in its repository. |
pull.reviews | body | agent.CodingReview[] | — | Reviews are its reviews, oldest first: the first 50. |
pull.reviews[].at | body | string | — | At is when it was submitted, RFC 3339 in UTC; empty for one that has not been. |
pull.reviews[].author | body | string | — | Author is the reviewer's forge login. |
pull.reviews[].body | body | string | — | Body is what the reviewer wrote; empty for a bare verdict. |
pull.reviews[].state | body | string | — | State is the verdict: approved, request_changes, comment, pending or request_review. |
pull.reviews[].truncated | body | boolean | — | Truncated marks a Body cut at either bound — or left empty past the second, where the review keeps its author, verdict and time. |
pull.state | body | string | — | State is open, closed or merged. |
pull.title | body | string | — | Title is its title. |
pull.url | body | string | — | URL is where a person reads and merges it. |
repo | body | string | — | Repo is the run's repository on the forge, owner/name. |
Failure carries the platform error shape — see Errors.
Examples
hanzo has no subcommand for this operation — the CLI serves only what cloud's live route table confirms. Use HTTP or an SDK.
import { Configuration, AgentApi } from 'hanzoai';
const api = new AgentApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getAgentCodingBySessionChanges({ session: 'session' });from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import AgentApi
client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = AgentApi(client).get_agent_coding_by_session_changes(session='session')cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)
resp, _, err := client.AgentAPI.GetAgentCodingBySessionChanges(context.Background()).Execute()
if err != nil {
return err
}use hanzo_client::apis::{configuration::Configuration, agent_api};
let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();
let result = agent_api::get_agent_coding_by_session_changes(&cfg, Default::default()).await?;import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.AgentApi;
ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));
var result = new AgentApi(client).getAgentCodingBySessionChanges();curl https://api.hanzo.ai/v1/agent/coding/<session>/changes \
-H "Authorization: Bearer $HANZO_API_KEY"MCP reaches agent through the agent tool, which names its 38 operations with its own verbs — this one among them, under a name only MCP declares. describe explains any of them:
curl -X POST https://api.hanzo.ai/v1/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "describe",
"arguments": {
"op": "list_agents"
}
}
}'