Skip to main content
A change-request proposes a new value for another catalog resource and holds that value until someone with write access approves it. It is how a person — or an agent — who can read a resource but not write it suggests a change: propose the new value, others endorse it, and a reviewer with permission to write the target approves it. Approving applies the proposed value to the target in one step. A change-request is created and updated entirely through its own commands — proposing, approving, rejecting, withdrawing, and endorsing. You do not author it with murmur set change-request, and you do not delete it with murmur rm. You read one with murmur get change-request.

Lifecycle

A change-request moves through these states:
StateMeaning
PENDINGProposed and awaiting review. Can be endorsed, approved, rejected, or withdrawn.
APPROVEDA reviewer approved it. The proposed value is being applied to the target; if the apply has not yet completed, it remains here and is retried on the next approve.
APPLIEDThe proposed value is written to the target. Terminal — the endorser list is frozen as a record of who wanted the change.
REJECTEDA reviewer declined it. Terminal.
A PENDING change-request the proposer no longer wants is withdrawn — removed entirely. Withdrawal works only while PENDING; once a change-request is APPROVED or later, the proposer cannot cancel it and must ask a reviewer to reject it. The proposed value applies only if the target has not changed since the change-request was proposed. If the target changed in the meantime, approval fails with a conflict and the change-request stays APPROVED so the conflict can be resolved or the change rejected. Nothing is merged silently.

Fields

Change-requests are managed by the API, not authored by hand. Reading one with murmur get change-request <id> shows these fields:
NameTypeDescription
idstringServer-generated identifier, e.g. cr-a1b2c3. Also the change-request’s catalog name.
targetKindstringThe catalog kind the change-request proposes to change, e.g. recipe.
targetNamestringThe name of the target resource within targetKind.
proposedPayloadobjectThe full proposed value of the target resource — a complete replacement, not a diff. Redacted on read exactly as a direct read of the target would be.
baseVersionintegerThe target resource’s version when the change was proposed. Approval applies only if the target still matches this version. 0 if the target did not exist at propose time.
statusenumLifecycle state: PENDING, APPROVED, APPLIED, or REJECTED.
proposerobjectWho proposed the change. Stamped from the authenticated caller.
approverobjectWho approved or rejected the change. Unset while PENDING.
rationalestringOptional justification supplied by the proposer.
decisionNotestringOptional note supplied by the approver or rejecter.
createdAttimestampWhen the change-request was proposed.
decidedAttimestampWhen the change-request was approved or rejected.
appliedAttimestampWhen the proposed value was written to the target.
appliedGenerationintegerThe target version produced by the apply. Recorded once the change-request is APPLIED.
endorsersarrayThumbs-up signals from members, service profiles, or agents. Each endorser appears at most once. Frozen once the change-request is terminal.
sourceenumWhat generated the change-request. Unset for changes you propose; set for changes the platform generates automatically.

Propose a change

To suggest a change to a catalog resource without writing it directly, read the resource, edit the value, and pipe it to murmur set with --propose. This creates a PENDING change-request and prints its id instead of writing the target.
murmur get recipe default | yq '.script_ref = "v2"' | murmur set recipe default --propose --rationale "bump build script to v2"
cr-a1b2c3
--propose takes the full resource value as the proposed replacement and validates it against the target’s schema immediately — an invalid proposal is rejected at propose time, not at approval. --rationale is optional and records why you are proposing the change. Proposing requires change-request.create and read access to the target ({targetKind}.read). Every org member and every service profile can propose by default.

Read change-requests

List every change-request in your tenant:
murmur get change-request
ID         TARGET           STATUS   ENDORSE  PROPOSER  CREATED
cr-a1b2c3  recipe/default   PENDING  4        alice     2026-06-24T18:02:11Z
cr-9f8e7d  role/developer   APPLIED  1        bob       2026-06-23T09:14:55Z
Read one change-request in full, including its proposed value and rationale:
murmur get change-request cr-a1b2c3
Reading a change-request requires change-request.read (or change-request.list to list) and read access to the target. A caller who cannot read recipes cannot read recipe change-requests, and list results omit change-requests whose target the caller cannot read.

Endorse a change-request

Endorsing adds your thumbs-up to a PENDING or APPROVED change-request — an advisory signal of demand that aggregates onto one proposal. It never approves or applies the change, and approval never depends on the endorsement count.
murmur cr endorse cr-a1b2c3
Endorsed change-request cr-a1b2c3 (5 endorsements)
Remove your endorsement with unendorse:
murmur cr unendorse cr-a1b2c3
Endorsing is idempotent: endorsing twice leaves one endorsement, and un-endorsing when you have not endorsed does nothing. Endorsing requires change-request.endorse and read access to the target. Agents can participate in the same signal through MCP tools — find_change_requests discovers open proposals so an agent endorses an equivalent one instead of filing a duplicate, and endorse_change_request / unendorse_change_request toggle its thumbs-up. Unlike org members and service profiles, agent runtimes hold no change-request permissions by default; an agent uses these tools only where the tenant grants change-request.read, change-request.list, and change-request.endorse to its agent runtimes.

Approve, reject, or withdraw

A reviewer with permission to write the target drives the change-request to a terminal state with murmur change-request (alias murmur cr).
murmur change-request approve <id> [--note TEXT]    Approve and apply a change-request
murmur change-request reject  <id> [--note TEXT]    Reject a change-request
murmur change-request withdraw <id>                 Withdraw your own pending change-request
murmur change-request endorse  <id>                 Add your thumbs-up
murmur change-request unendorse <id>                Remove your thumbs-up

Approve

Approving records the approval and writes the proposed value to the target in one step:
murmur cr approve cr-a1b2c3 --note "looks good, rolling out"
Approved change-request cr-a1b2c3 (APPLIED); applied generation 7
Approval requires the same permission as writing the target directly: {targetKind}.create if the target did not exist when the change was proposed, otherwise {targetKind}.edit. --note records an optional decision note.

Reject

murmur cr reject cr-a1b2c3 --note "superseded by cr-9f8e7d"
Rejecting requires the same target-write permission as approving.

Withdraw

The proposer removes their own PENDING change-request:
murmur cr withdraw cr-a1b2c3
Only the proposer can withdraw, and only while the change-request is PENDING.

Targets you cannot propose against

A change-request carries the full proposed value of its target, so kinds whose value cannot be meaningfully reviewed cannot be targets:
KindReason
secret, user-secret, token, share-linkTheir values are write-only and suppressed on read — a proposed value could never be reviewed.
integrationMints a one-time signing key when written; routing it through a change-request would drop the key.
change-requestA change-request cannot target another change-request.
Platform builtins (resources whose name begins with murmur-) also cannot be the target of a change-request.

Errors

CodeMeaningWhat to do
INVALID_ARGUMENT{kind} resources cannot be the target of a change-requestChoose a target kind that supports change-requests. See Targets you cannot propose against.
INVALID_ARGUMENT{kind} "{name}" is a platform resource and cannot be changedPlatform builtins (murmur-*) are immutable. Propose against a resource you own.
INVALID_ARGUMENTunknown resource kind "{kind}"Use a valid catalog kind. See Catalog resources.
INVALID_ARGUMENTtarget_name is requiredProvide the name of the resource you are proposing to change.
INVALID_ARGUMENTtarget_name "{name}" does not match payload name "{name}"Make the name field in the proposed value match the target name.
INVALID_ARGUMENTunmarshal proposed {kind}: …Fix the proposed value so it parses as a valid {kind} resource.
NOT_FOUNDchange-request "{id}" not foundCheck the id with murmur get change-request.
FAILED_PRECONDITIONtarget {kind} "{name}" changed since base version {n}The target changed after the proposal. Re-propose against the current value, or reject the change-request.
FAILED_PRECONDITIONchange-request is already applied / change-request is rejectedThe change-request is terminal — it cannot be approved, rejected, endorsed, or withdrawn.
FAILED_PRECONDITIONonly a pending change-request can be withdrawnReject the change-request instead of withdrawing it.
PERMISSION_DENIED(proposer-only withdraw)Only the proposer may withdraw a change-request.
PERMISSION_DENIED(missing permission)Proposing needs change-request.create; endorsing needs change-request.endorse; approving and rejecting need write access to the target. See Authorization.