Skip to content

approval.resolved

A decision came back. More than yes or no: it carries a scope, optional edited input, and a reason.

Direction: Chips → Harness
Sent by: a person or a harness
Requires a run: yes
Schema: approval.resolved.json

Every event also carries the envelope.

Field Required Type Description
v yes 1 Protocol major version.
type yes "approval.resolved"
id yes string The event’s own id. Stable across a retry of the same event.
ts yes string When it happened, by Chips’ clock. Stamped on the way in; a value the sender writes is replaced.
workspace_id yes string A workspace identifier: ws_ followed by a ULID.
space_id no string The space, when the event belongs to one.
run_id no string The run, when the event belongs to one.
seq no number Assigned by the server on append, monotonic per workspace. Absent on the way in.
idempotency_key no string Required on every client-originated write. Sending the same key twice is a no-op.
actor yes object The participant an event is attributed to.
actor.kind yes "person" | "harness" | "agent" | "system" Whether a person, a harness, one of a harness’s agents or Chips itself acted.
actor.id yes string The participant id, or system for Chips.
actor.harness_id no string For an agent: the harness it speaks through, whose budget and runs are the agent’s (ADR 0087). Filled in by Chips.
approval_id yes string A approval identifier: apr_ followed by a ULID.
decision yes "approved" | "edited" | "denied" | "expired" expired means nobody answered and the fallback applied.
scope no "once" | "session" | "always" How far the answer reaches. always becomes a policy rule.
everywhere no boolean With always: the rule is the harness’s in every space, not only this one (ADR 0239). An owner or an admin only.
updated_input no unknown The edited action input, when the decision is edited.
reason no string Why. The harness gets to read this.
resolved_by yes string The participant who answered, or system on expiry — a harness when it settles its own ask, answered in its own tools. Filled in by Chips from the credential that sent it; a value the sender writes is replaced.
resolved_at yes string When it was answered. Stamped by Chips.
resolved_elsewhere no boolean True on the surfaces that did not answer first. First answer wins.
approvers no string[] Who could answer it, as ids, as they stood when it was decided. Written by Chips from the approval so that somebody named outside the room is sent the decision as well as the ask (ADR 0042); a value the sender writes is replaced.
{
"v": 1,
"type": "approval.resolved",
"id": "evt_01K4ZQPX000000000000000076",
"ts": "2026-09-02T14:22:18.004Z",
"workspace_id": "ws_01K4ZQPX000000000000000001",
"space_id": "spc_01K4ZQPX000000000000000002",
"actor": {
"kind": "system",
"id": "system"
},
"run_id": "run_01K4ZQPX000000000000000005",
"approval_id": "apr_01K4ZQPX000000000000000006",
"decision": "approved",
"scope": "once",
"reason": "Looks right. Send it.",
"resolved_by": "usr_01K4ZQPX000000000000000003",
"resolved_at": "2026-09-02T14:30:12.881Z",
"resolved_elsewhere": false
}