Dispatch

Callbacks — trigger.complete / trigger.reverse

Two REST endpoints (not MCP tools) that your handler calls to report execution outcome and any subsequent reversal. Calling back is what writes the ledger entry, trains trust, and lets the substrate compute its next decision.

Why call back at all?

A 200 OK from your handler tells Cortex the dispatch was received. The callback tells Cortex the action was actually executed — with what external reference, in what channel, at what time. This is what closes the loop and writes the ledger entry; it's also what trains trust over time. A handler that always returns 200 but never calls back will, after the configured success-window, have its trust pair flagged.

POST /v1/triggers/{trigger_id}/complete

Reports successful execution (or an explicit user decision in ask mode).

httptrigger.complete request
POST https://mcp.cortex.jakeselby.com/v1/triggers/{trigger_id}/complete
Authorization: Bearer <principal_token>
Content-Type: application/json
Idempotency-Key: cb_01HXP9...

{
  "outcome":      "executed",
  "external_ref": "slack_msg_123",
  "external_url": "https://your-app.com/messages/123",
  "executed_at":  "2026-05-27T14:32:10Z",
  "notes":        "Optional human notes; appended to ledger entry."
}

Outcome values

ValueMeaningTrust impact
executedAction executed successfully on your side (act / notify_after modes).Reinforces the pair's graduation streak.
approvedUser approved the action in your app's UI (ask mode); you then executed it.Reinforces the pair.
rejectedUser explicitly rejected the proposal (ask mode).Demotes trust for the (action × counterparty) pair.
deferredUser chose “not now”; no action taken, but no negative signal.Neutral; the same envelope may re-dispatch later.

Response

jsontrigger.complete response
{
  "ok": true,
  "ledger_entry_id": "led_01HXP9COMM",
  "trust_delta": { "action_class": "communicate", "counterparty_id": "entity_01HXSARAH", "change": "reinforce" }
}

POST /v1/triggers/{trigger_id}/reverse

Reports that the executed action was undone — either by the user inside the reversal window, or by your app for an operational reason (delivery bounce, recipient deletion, opt-out).

httptrigger.reverse request
POST https://mcp.cortex.jakeselby.com/v1/triggers/{trigger_id}/reverse
Authorization: Bearer <principal_token>
Content-Type: application/json
Idempotency-Key: cbr_01HXP9...

{
  "reason":      "user_undo",
  "reason_text": "User clicked Undo within 60 minutes",
  "reversed_at": "2026-05-27T14:35:00Z"
}

Reason values

ValueMeaningTrust impact
user_undoUser clicked Undo / Reverse in your UI within the reversal window.Demotes the pair. Repeated user_undo within a short window can drop trust by two levels.
user_correctionUser corrected the action (different recipient, different content) after execution.Demotes the pair; logs the correction against the rule that fired.
operationalReversal for operational reason (bounce, opt-out, channel error). Not user intent.Neutral for trust; appended to ledger for audit.

Idempotency

Both callbacks accept an optional Idempotency-Key header. If your handler retries a callback after a network error, set the same key to ensure the substrate treats it as a no-op rather than recording the outcome twice.

Errors

CodeMeaning
signature_invalidYour callback is itself authenticated, not signed (you use the principal bearer token). But Cortex can return this if you attempt to callback a trigger that was dispatched to a different handler.
invalid_decision_idThe trigger id does not exist or was not dispatched to your handler.
already_decidedThis trigger was already resolved (callback already recorded).
decision_expiredThe trigger's expires_at has passed. Reversal is still accepted within the broader reversal window; complete is not.

See the full error catalog for resolution steps.