Suggest a change, and test it
This guide suggests new settings or new instructions for what a project runs, checks them against the version it runs on the project's test cases, and pins them for the project through its release gate, or adds them as the project's Latest.
A suggested change is new content for one data block, in what one
project runs: new settings values, or new instructions. You make it. Kindgi
builds it on the agent version the project runs: it publishes the block
version and makes the agent version that pins it. Then it checks the new
version and the one it's built on, on the same test cases. The new versions
serve nothing until you pin the suggested change, and a pinned suggested
change is a pin like any other, which kindgi agents unpin removes.
A deploy makes suggested changes too, for its new code: A deploy's suggested changes says how.
Before you start
Section titled “Before you start”- An agent that keeps its instructions or settings as data blocks, as Change a prompt or a setting without a deploy shows.
- Corrections of the agent's runs in the project, as
Correct some runs shows. The
runtime keeps a test set for each agent: its corrections are its cases,
with the cases added by hand. A project's test set is its cases from that
project, and a suggested change is checked on it. Without cases, making
one is refused with
409 suggested-change-nothing-to-check. - A version of the agent that the project runs. A suggested change is
built on it. To pin one, the project needs a pinned version, its own or
one that covers it, as
Pin a version shows. Where the agent runs nothing, making one is refused with
409 nothing-runs-in-scope. - The order's first environment, for a project in an environment order.
In a later environment, making one is refused with
409 environment-takes-promotions: the new version reaches the later environments when a build is promoted. - A deployed runtime that keeps a project's test set. One that doesn't
refuses a suggested change with
501 suggested-change-check-unsupported. Underkindgi dev, one is for the whole workspace, as Underkindgi devshows. publishon the agent to make, check and withdraw, andpinto pin or add as Latest. For an agent that several projects serve, it'swriteon the project where its versions are made, andadminin the suggested change's project to pin or add as Latest.
Make one
Section titled “Make one”A suggested change says what to change, for which project, and why:
pnpm exec kindgi suggested-changes create --agent=acme.rank.scorer --project=<project-id> \ --block=acme.rank.weights --values='{"recency":0.2,"fit":0.8}' \ --why="Fit matters more than recency for acme rankings"- What it changes:
--agentand--projectname the agent and the project it's for. It's built on the version the project runs.--blocknames a block that version pins.--valuesgives a settings block's new values, and--templatethe agent's new instructions. Either takes a file as@<file>. - Why:
--whysays what the change should fix, and why. Its first line starts the suggested change'stitle. Each--fixes=<correction-id>names a correction it fixes, kept in itsfixes. Repeat it for several. Each must be a correction in the project: an unknown id, or another project's, is refused (validation-failed), and nothing is made.
It publishes the block version, makes the agent version that pins it, and
starts the check. It prints the suggested change, checking:
{ "id": "3bca94f1-61a4-48b5-a3d7-f3664e466613", "agentId": "acme.rank.scorer", "projectId": "aa0cf701-a8f7-40e5-b5d9-bec1a1cb1723", "title": "Fit matters more than recency for acme rankings: acme.rank.weights v1.0.0 → v1.0.1", "madeBy": { "kind": "person", "userId": "62e1ffe2-30f4-4dff-948e-ae774107a7db" }, "builtOn": { "version": "1.0.0" }, "version": "1.0.1", "changes": [ { "kind": "block", "blockId": "acme.rank.weights", "from": "1.0.0", "to": "1.0.1" } ], "why": "Fit matters more than recency for acme rankings", "fixes": [], "correctionCount": 0, "check": { "status": "running", "testSetId": "agent.acme.rank.scorer.aa0cf701-a8f7-40e5-b5d9-bec1a1cb1723", "now": { "testRunId": "941582fc-9e32-41bb-b148-767712664c6b" }, "with": { "testRunId": "aefcafd1-53df-480e-b01d-05ae55724507" }, "startedAt": "2026-10-09T13:24:24.401Z" }, "status": "checking", "createdAt": "2026-10-09T13:24:23.787Z", "updatedAt": "2026-10-09T13:24:24.512Z"}builtOn.versionis the agent version the project ran when it was made, or when it was last rebuilt (builtOn.rebuiltAt), andversionthe agent version it made.changes[].fromis the block version thatbuiltOnpins, andtothe one it published.fixesnames the corrections it fixes, the first 100 at most, andcorrectionCountsays how many in all. A person's change names 100 at most, so its count is the length offixes. One an Improve run wrote can fix more. An older runtime leavescorrectionCountout, and there the length offixesis the count.- The content is checked as publishing that block version would be, and content equal to what the version pins is refused.
- The same change on the same version for the same project returns the
suggested change made before, unless it was withdrawn, with the header
X-Suggested-Change-Deduped: true. That one isn't checked again. - If its check can't start, the suggested change is still made. The error
names it in
suggestedChangeId, and it'scheck-faileduntil you check it again.
Through the API, it's POST /v1/suggested-changes with agentId,
projectId, block, values or template, why and fixes. It answers
201.
Its check
Section titled “Its check”The check runs the suggested change's version (with) and the version it's
built on (now) on the same cases: the project's test set for the agent,
frozen as a version when the check starts. Each side is a run on the test
cases, which kindgi test-runs show <test-run-id> shows case by case.
The suggested change is checking while either run is queued or running,
then:
ready: both finished, andchecksays how each did;check-failed: either failed or was cancelled.
get shows it:
pnpm exec kindgi suggested-changes get <suggested-change-id>{ "id": "3bca94f1-61a4-48b5-a3d7-f3664e466613", … "changes": [ { "kind": "block", "blockId": "acme.rank.weights", "from": "1.0.0", "to": "1.0.1", "before": { "values": { "fit": 0.5, "recency": 0.5 } }, "after": { "values": { "fit": 0.8, "recency": 0.2 } } } ], … "check": { "status": "done", "testSetId": "agent.acme.rank.scorer.aa0cf701-a8f7-40e5-b5d9-bec1a1cb1723", "testSetVersion": "1.0.4", "now": { "testRunId": "941582fc-9e32-41bb-b148-767712664c6b", "passing": 23, "of": 27, "costPerConversation": "0.0031" }, "with": { "testRunId": "aefcafd1-53df-480e-b01d-05ae55724507", "passing": 25, "of": 27, "costPerConversation": "0.0031" }, "newlyFailing": ["46b82ad4-1c2a-45f8-a593-a9c912964fd3"], "startedAt": "2026-10-09T13:24:24.401Z" }, "status": "ready", …}passingofof: the corrections each version passed, of those it was checked on. With repetitions, a correction counts as passed when every repetition passed it. Here the change passes 25 of 27, and the version it's built on 23.newlyFailing: the correctionsnowpasses andwithfails, by id. Here the change fixed three corrections and broke one.costPerConversation: what a side's replays cost in model calls per case, in US dollars. It's absent when the runtime reported no cost.getadds the block's content before and after the change.- A correction in
fixesits author has replaced since (by correcting the run again):fixeskeeps the id it names, and the CLI'sgetnames the live one that replaced it on stderr, for example<fixed-id> (in fixes) was replaced by <live-id>, now open.When the runtime answers an error for one, its line says it couldn't be checked, and why.
ready says the check finished, not that the change is better. The release
gate decides when you pin it.
Check it again
Section titled “Check it again”A check counts the corrections in the test set when it started. Check the suggested change again so that corrections made since count:
pnpm exec kindgi suggested-changes check <suggested-change-id> --wait- The project's test set is frozen again, as a new version when its cases changed, and both versions run on it. Nothing new is published: it's the same version.
- The new check replaces the one before on the suggested change. The runs of the one before stay as they were.
- When its project now runs another version than the one it's built on, it's rebuilt on that version first, and the check runs on the new version.
--waitwaits for the check, at most 30 minutes, and prints the suggested change. Without it, it prints the suggested change,checking.- Checking again is allowed when it's
readyorcheck-failed, and needspublishon the agent. Through the API, it'sPOST /v1/suggested-changes/{suggestedChangeId}/check, with no body, and it answers202.
Pin it
Section titled “Pin it”Pinning it pins the suggested change's version for its project, through the
project's release gate, with its check's run (with) as the run on the test
cases:
pnpm exec kindgi suggested-changes pin <suggested-change-id> --reason="Fit first: 25 of 27 against 23."--reason is kept with the request to pin it.
Gate a pin describes the release
gate. Pinning is allowed when the suggested change is ready, whatever its
check says: the release gate decides. Then:
- it's
pinned: its version runs in the project, andpinnedsays which version, who pinned it and when; - it's
waiting-for-second-person: the release gate passed, and a reviewer decides the approval inapprovalId, withkindgi approvals complete. Approved, it'spinned; - or the release gate refused it, with
422 gate-failed, listing every check.
{ "id": "3bca94f1-61a4-48b5-a3d7-f3664e466613", … "status": "pinned", "pinned": { "version": "1.0.1", "by": { "kind": "user", "id": "62e1ffe2-30f4-4dff-948e-ae774107a7db" }, "at": "2026-10-09T13:31:02.118Z" }, …}A pin that doesn't go through leaves the suggested change ready, with a
note that says why: gate-refused, rejected by the second person,
expired when nobody decided the approval in time, or superseded when the
project's version or its release gate changed before the approval.
pinChangeId names that request in the agent's pin history. You can ask
again.
- A project that runs its Latest
takes no pin unless you ask to take it off Latest: the request is refused
with
409 pin-stops-latest. Add it as Latest instead, or sendstopFollowingLatest: trueto pin it (kindgi suggested-changes pin --stop-following-latest), and the project runs the pinned version from then on. - A project that runs another version than the one the suggested change is built on takes no pin of it either: it's rebuilt first.
- A suggested change an Improve run made, rather
than a person, always waits for a reviewer, even where the project's
release gate asks for no approval. While another reviewer could approve
it, someone other than whoever asked to pin it must, even where the
release gate's
approvalssets"separateApprover": false. - Unpinning, or pinning another version, moves the project off it, as
Unpin shows. The suggested change
stays
pinned. - Pinning needs
pinon the agent. Through the API, it'sPOST /v1/suggested-changes/{suggestedChangeId}/pin, which answers201when it's pinned and202when it waits for a second person.
Add it as Latest
Section titled “Add it as Latest”A project that runs its Latest takes a suggested change as its Latest instead: from then on, the project runs the suggested change's version, until its Latest moves again. There's no release gate here: a project on Latest takes each new Latest as it comes.
pnpm exec kindgi suggested-changes add-as-latest <suggested-change-id> --reason="Fit first for acme."--reasonis kept on itsaddedAsLatest.- Through the API, it's
POST /v1/suggested-changes/{suggestedChangeId}/add-as-latest, with an optionalreason, and it answers200. From your app, it'ssuggestedChanges.addAsLatestin the TypeScript client, andsuggested_changes.add_as_latestin the Python client. - It's allowed when the suggested change is
ready, and needspinon the agent. For an agent that several projects serve, it'sadminin the suggested change's project. - Then it's
added-as-latest, and itsaddedAsLatestsays which version, who added it, when, and thereason. - A project that runs a pin takes a pin instead: adding it is refused
with
409 suggested-change-project-pinned. Pin it. - A project whose Latest moved since the suggested change was built takes it once it's rebuilt.
Bring the pack up to it
Section titled “Bring the pack up to it”Once it's pinned or added as Latest, the project runs a block version your
pack's blocks/ folder doesn't have yet, and the pack's next deploy still
carries the old one. Bring the block's file up to it through a pull request
on the pack's repository:
pnpm exec kindgi suggested-changes pull <suggested-change-id> --pr- It's allowed when the suggested change is
ready,waiting-for-second-person,pinnedoradded-as-latest. One stillchecking, one whose check failed, one that's withdrawn, and a deploy's are refused, each saying why. - It writes the block's version and content into its file, and into the template file beside it, as Keep them in the pack lays them out: only when it's newer than the file's. A file that holds a newer version than the one the suggested change is built on, or a version with edits that aren't in the runtime's copy of it, is refused, so it never drops what was changed since. So is a file at a version the runtime doesn't have: whether it holds edits can't be told.
- It makes a branch,
kindgi/<block>-<version>, from the one checked out, commits the block files alone, pushes the branch toorigin(or the only remote), and opens the pull request withgh. It stays on the new branch, and says how to go back. Withoutgh, it prints where to open one (its URL, when the remote gives one), and the lines that mark what it fixes once it's open. - The pull request says where the suggested change came from, its test-set numbers, the files, and a link to the suggested change with its check in the console. It never says the suggested change's why, nor a correction's words.
- The corrections it fixes that are still
openare thenbeing-fixed, linked to the pull request, which needspublishon the agent, orwritein the correction's project for an agent that several projects serve. One it can't mark is named, with the line to run once it can be, and the pull request stands. - Before it writes anything, it's refused when the pack isn't in git, its
block files have changes that aren't committed (or git can't say),
HEADis detached, git has nouser.name, there's no remote to push to, or the branch is there already, in the pack's repository or on the remote. - Without
--pr, it only writes the files, for you to commit.--projectrefuses a suggested change for another project.
If the project moves first
Section titled “If the project moves first”A suggested change is built on the version its project runs when it's made. When the project moves to another version first, because another suggested change was pinned or added as Latest, or the project was pinned another way, the suggested change is rebuilt on the version the project runs now:
- Its block change is made again on that version. A prompt keeps its wording. Settings keep the values the suggested change changed, and take every other value from the version the project runs now.
- That's a new version, and its check starts again: it's
checking. builtOn.versionis the version it's built on now, andbuiltOn.rebuiltAtsays when it was rebuilt.
{ "id": "8d2f3c07-5b8e-4c1d-9a3e-2f6b7c1d0e94", … "builtOn": { "version": "1.0.1", "rebuiltAt": "2026-10-09T13:31:03.204Z" }, "version": "1.0.3", "status": "checking", …}When a suggested change is pinned without waiting for a second person, or
added as Latest, the project's other suggested changes for the agent that
are ready or check-failed are rebuilt on its version at once. Any other one is rebuilt when it's checked
again, pinned or added as Latest:
- Pinning it, or adding it as Latest, is refused with
409 suggested-change-out-of-date, and its rebuild starts.details.rebuildingistrue. Ask again once it'sready. - When the version the project runs already has the change, or doesn't use
its block, it isn't rebuilt:
details.rebuildingisfalse, and it stays as it was. Withdraw it.
A deploy's suggested changes
Section titled “A deploy's suggested changes”A deploy that registers a new agent version makes a suggested change for it in each project that runs a pinned other version of the agent. A project on Latest runs the new version at once, and gets none. With environment orders, the version reaches the next project when the deployment is promoted into it, and the suggested change is made then. A promotion that pins the version there makes none.
madeByisdeploy, with the deployment and who deployed or promoted it.- Its one change is the code:
kindiscode, with the deployment and its image digest. - Its version is the deploy's version, and it's never rebuilt. When the
project moves to another version first, pinning it is refused with
409 suggested-change-out-of-date, anddetails.rebuildingisfalse. Withdraw it.
Its check runs its version on the project's test set, as any other
suggested change's does. What the project runs isn't run again: now is
the newest finished run of that version on the same frozen cases, when there
is one. When there's none, the check has no now, and its note says so:
{ "id": "5e1a7c3b-2d4f-4b8e-9c61-0a7f3e2d1b58", … "madeBy": { "kind": "deploy", "deploymentId": "c41f8e2a-7b3d-4e19-a6c5-2d8f0b9e7a13", "by": { "kind": "user", "id": "user-1" } }, "builtOn": { "version": "1.0.0" }, "version": "1.1.0", "changes": [ { "kind": "code", "deploymentId": "c41f8e2a-7b3d-4e19-a6c5-2d8f0b9e7a13", "imageDigest": "sha256:9f2c…" } ], "status": "ready", "note": { "kind": "not-running", "version": "1.0.0" }, …}When the project's test set has no cases yet, it's made without a check:
it's check-failed, and check checks it once the set has cases. A deploy
never fails because a suggested change couldn't be made.
Withdraw it
Section titled “Withdraw it”A withdrawal closes a suggested change while it's checking,
check-failed or ready. Not while a second person decides its pin: they
reject it instead.
pnpm exec kindgi suggested-changes withdraw <suggested-change-id> --reason="Superseded by a better draft"It prints the suggested change, now withdrawn, and its withdrawn says
who, why and when. --reason is required, and withdrawing needs publish on
the agent. Its versions stay published, and serve nothing.
An older suggested change made for a workspace, an org or a segment can only be
withdrawn: checking or pinning it is refused with
409 suggested-change-not-for-a-project. Its projectId is the project its
version was made in, when that's known.
Under kindgi dev
Section titled “Under kindgi dev”Under kindgi dev, the pack's files are what runs. There, a suggested
change is for the whole workspace, whether an
Improve run made it or you did. It's checked in the
default project, where kindgi dev places the pack's agents and their runs,
on that project's corrections and test set. Pinning it
goes through the release gate and waits for your approval, since
kindgi dev registers you as a reviewer; open it from the suggested change's
page. Approved, it writes its changed prompt or settings into the pack's
files. kindgi dev reloads them, and the pin waits for that. The
next runs use the new version, and the pin's test runs check the default
project and mark what it fixes there, as on a deployed runtime.
- Adding one as Latest is refused with
409 registry-read-only: the pack's files are what runs, and there's no Latest. Pin it. - A block's file edited since the suggested change was made, even at the
same version, refuses the pin with
409 pin-superseded, naming the file, and nothing is written. Run Improve again on the files as they are now. - One built on a version that no longer runs is rebuilt on what runs
now and checked again, as on a deployed runtime, when you check it again
or pin it. Until that check is ready, a pin is
409 suggested-change-out-of-date. - Undoing a pin is a pin of the version before, as on a deployed
runtime: it writes the files back as they were right before the pin, and
its test runs reopen what that version fails. An unpin is refused with
409 registry-read-only. Commit the files before you pin, sogit diffshows what a pin changed. - Files git hasn't committed are named before a pin writes over them:
the files it would write that are changed, staged, untracked or ignored,
or in a repository inside the pack's, such as a submodule.
kindgi agents pin,kindgi suggested-changes pinandkindgi agents pin --checksay so on stderr, and the pin's dialog shows them under "Files git hasn't committed". When the pack isn't in a git repository, they say that instead. The pin check (POST /v1/agents/{agentId}/pinned/check) answers the files asuncommittedFiles, paths in the pack's folder, ornotInGit: true. It's a warning: the pin still goes, and stdout,--jsontoo, is its answer as before. Nothing is said when the pin writes nothing, or when git can't say, as when it isn't installed or doesn't answer in time. To keep those changes in git, commit the files before the pin writes them: before you pin, or, while the pin waits for your approval, before you approve it. A pin that wrote over them keeps them as they were right before it: pin the version before to bring them back. - A block's file edited by hand without a new version, at a version a
pin wrote or wrote over, refuses the next pin the same way:
kindgi devkeeps each of those versions as it was, for a pin of the version before to bring back. Give a block a new version whenever you edit it by hand.
Or change the block's file yourself, as Keep them in the pack shows.
Find them
Section titled “Find them”pnpm exec kindgi suggested-changes list --agent=acme.rank.scorer --project=<project-id> --tablepnpm exec kindgi suggested-changes get <suggested-change-id>--agentand--projectlist one agent's suggested changes, and one project's.--statuskeeps one status. It applies after the page is read, so a page can hold fewer than--limit.--cursorreads the next page, fromnextCursor.--tableprints a table with the columns ID, AGENT (the agent and the version it's built on), PROJECT, CHANGE (the block and the version it changes, or the deploy whose code it is), STATUS, CHECK and CREATED. CHECK says how its version did, then the version it's built on:25/27 (now 23/27). Before either has a score, it shows the check'sstatus.getshows the block's content before and after, the check and the pin.
Through the API, GET /v1/suggested-changes also filters by madeBy: who or
what made it, one of improve-run, person, service, deploy or
offer.
Suggested changes are authorized on their agent: read to see one. For an
agent that several projects serve, it's read on the agent or on any of its
projects. A suggested change you can't read answers 404, as one that
doesn't exist.
| Status | What it means |
|---|---|
checking |
Its check's runs are queued or running. |
check-failed |
Its check failed or was cancelled, or never started (check.status is not-started). |
ready |
Its check finished: check says how each version did. A pin that didn't go through leaves it here, with a note. |
waiting-for-second-person |
Asked to pin it; the release gate passed, and the approval in approvalId is open. |
pinned |
Its version was pinned for its project. |
added-as-latest |
Its version was added as its project's Latest. |
withdrawn |
Withdrawn. |
From your app, the clients have the same calls: suggestedChanges.create,
list, get, check, pin, addAsLatest and withdraw.