decisions

Record a decision on an intent from outside the editor conversation — a call made in a PR review, a Slack thread, or by an agent mid-build. Appends to the intent's decision audit trail (what was chosen, what was ruled out, why, and what would reopen it).

Rate-limited by the 'general' bucket (300/h sliding window, keyed user:<userId> or ip:<ip>). The append is an optimistic-concurrency compare-and-swap fenced on the intent's updated_at (up to 3 attempts), so two agents posting simultaneously cannot overwrite each other's decision; a persistently lost race returns 409. Appends beyond the 100-decision cap are rejected with 409 rather than silently discarded by the sanitizer. The merged set is sanitized (malformed legacy rows dropped) before persisting. The server assigns id (UUID) and resolvedAt (epoch ms). evidenceIds are validated against the workspace's evidence_items and non-resolving ids are dropped; the field is omitted when none resolve. Emits the server-side 'decision_recorded' analytics event with source 'api'.

post/api/v1/intents/{id}/decisions

Path parameters

idstring required

id path parameter.

Query parameters

workspace_idstring

Required ONLY for cookie-session auth; identifies the target workspace. Ignored for API-key auth.

Request body

choicestring required

What was chosen. Non-empty after trim, max 500 chars.

reasonstring required

Why — the evidence or reasoning behind the call. Non-empty after trim, max 1000 chars.

ruledOutstring

The alternative that was ruled out. Non-empty after trim, max 500 chars.

reopenTriggerstring

What new evidence or change would reopen this decision. Non-empty after trim, max 500 chars.

evidenceIdsstring[]

Evidence item UUIDs backing the decision (max 20). Ids are verified against the workspace's evidence_items; ids that don't resolve are silently dropped so a caller cannot fabricate provenance.

Response

Created — returns { intentId, decision, decisionCount }

object required

Changes