Decision Effect
Definition
A Decision Effect is an automated downstream action the platform takes after a decision is sealed — i.e. after an Edition is attested. When a commander approves a containment order, the platform should not merely record the decision; it should act on it — create follow-up WorkflowTasks, notify external systems, or dispatch agents. The DecisionEffect object is the unit that captures that a sealed decision produced an outbound action and what happened to it, without prescribing how the action is transported.
Attestation is the firewall. Decision Effects belong to the execution layer (DES "Layer C"): they exist only because a
human attested an Edition (Layer B), and they are derived from the effects[] configuration on that Edition's
decision template. Without Decision Effects, attestation is a dead end — the human decides, but nothing happens
automatically. Decision Effects are the first feature that consumes the attestation + provenance infrastructure to do
something with a decision.
- #REQ.triggered-by-attestation — A DecisionEffect is created when an Edition is attested, driven by the
decision template's
effects[]configuration. No attestation → no effect. - #REQ.records-not-transports — The DecisionEffect records that an outbound action was produced and what happened to it (status, acknowledgments, hashes). It does not define the transport: no endpoint URLs, webhook configs, retry policies, routing instructions, or agent communication protocols live on the object.
This spec describes the Effect as a domain object — its trigger, lifecycle, dispatch, and types. It is
distinct from the WorkflowTask lifecycle: WorkflowTasks (product.task) are deliberation-phase work items that produce
evidence and decisions; Decision Effects are post-attestation actions that execute sealed decisions. See
§related for the boundary.
Lifecycle
status: pending → acknowledged → {completed | failed | timed_out}, with a cancelled exit before completion.
pending ──ack──▶ acknowledged ──complete──▶ completed
│ │
│ └──fail──▶ failed
│
└──timeout──▶ timed_out ──▶ Signal (escalation)
| Status | Meaning |
|---|---|
pending |
Effect created, awaiting acknowledgment from the target |
acknowledged |
Target confirmed receipt |
completed |
Target confirmed successful execution |
failed |
Target reported failure (with failure_reason) |
timed_out |
deadline elapsed without completed/failed — generates an escalation Signal |
cancelled |
Effect withdrawn before completion |
- #REQ.lifecycle-states — The Decision Effect lifecycle is
pending → acknowledged → completed, withfailed,timed_out, andcancelledas terminal exits. Transitions are validated, not orchestrated. - #REQ.transitions-logged — Every status transition is appended to the investigation's append-only event ledger as an effect event (see §journey). Status is descriptive and auditable, never silently mutated.
Trigger → Dispatch → Outcome
The Decision Effect moves through three phases:
- Trigger. An Edition is attested. Cortex reads the decision template's
effects[], evaluates each entry's optionalcondition, and for each match creates a DecisionEffect doc (status: pending,created_byactor.type: system,correlation_idlinking to theeffect_createdledger event). The originatingattestedevent is the provenance anchor. - Dispatch. The EffectDispatcher persists the Decision Effect and hands it to the handler matching its
effect_type. The first handler isagent_dispatch, which calls an external MCP endpoint (outbound MCP). Dispatch does not block Edition creation — Decision Effects are evaluated post-attestation and run asynchronously. -
Outcome. The target acknowledges, completes, or fails; or the
deadlineelapses and the effect times out. Each outcome is recorded on the object and emitted as a ledger event. Atimed_outeffect raises an escalation Signal that re-enters the OODA flow. -
#REQ.dispatch-nonblocking — Decision Effect evaluation and dispatch happen post-attestation and MUST NOT block or fail Edition creation. A failing Decision Effect is recorded as
failed/timed_out, never rolled back onto the Edition.
Decision Effect types
effect_type |
Description | Pack-config equivalents |
|---|---|---|
external_dispatch |
Action sent to an external system (billing, logistics, CRM, regulatory, core banking). Dispatched via a handler such as agent_dispatch (outbound MCP). |
external_routing, webhook |
notification |
Informational notice (email, webhook, message) to a recipient/subscriber — no completion expected. | notification |
human_process |
Action assigned to a person or team outside the decision system — bridges back to a new WorkflowTask (Layer A) via create_task(). |
task_creation |
- #REQ.effect-types — The Decision Effect type taxonomy is
external_dispatch | notification | human_process. The pack-level config vocabulary (external_routing,webhook,notification,task_creation) maps onto these three DES types; the object stores the DESeffect_type. - #REQ.agent-dispatch-handler — At least one handler (
agent_dispatch) dispatches anexternal_dispatcheffect to an external agent over MCP (outbound). Handlers are pluggable pereffect_type;agent_dispatchis the first. - #REQ.notification-no-completion — A
notificationeffect expects no completion acknowledgment; it reaches a terminal state on send and does not block on a target confirming execution. - #REQ.human-process-creates-task — A
human_processDecision Effect (packtask_creation) creates a new WorkflowTask viacreate_task()withactor.type: systemandorigin_event_idpointing at theattestedevent. This is the one-way bridge from the execution layer back into the deliberation layer.
Journey through the code
The Decision Effect's path through cortex (cortex#279–cortex#283):
- Persist (
2.1, cortex#279). ADecisionEffectpersistent object with Elasticsearch CRUD — ideff_+ suffix, stored alongside the other intelligence objects. - State machine (
2.2, cortex#280). The effect lifecycle state machine validates transitions per §lifecycle; illegal transitions are rejected. - Ledger events (
2.3, cortex#281). Each effect transition appends an event to the investigation's append-only event ledger (effect_created, and the per-transition follow-ons), so the effect's whole history is replayable from the ledger. - Dispatcher wiring (
2.4, cortex#282). The EffectDispatcher is wired to persist effects on creation and update them as outcomes arrive — the bridge between the decision template'seffects[]and the stored object. - Outbound handler (
2.5, cortex#283). Theagent_dispatchhandler performs the first outbound MCP call to an external agent endpoint.
Decision Effects are surfaced in decision lineage: the get_decision_lineage tool/output includes the Decision Effects an
attested Edition produced, so the decision and its downstream actions are inspectable together.
- #REQ.lineage-visibility — Decision Effects produced by an attested Edition MUST be visible in
get_decision_lineageoutput, alongside the Edition and its provenance. - #REQ.es-persistence — DecisionEffect is a persistent object with Elasticsearch CRUD, identified by an
eff_id; it is not ephemeral dispatch state.
Data shape
Required: schema_version, effect_id (eff_ prefix), edition_id (the attested Edition that produced it),
insight_id (the investigation that produced the Edition), effect_type (see §types), target
(implementation-defined target system/process), payload_hash (SHA-256 of the effect payload at creation),
status (see §lifecycle), created_at, created_by.
Optional: action (human-readable label), payload_summary, deadline (ISO 8601), correlation_id (event id
linking to the effect_created ledger entry), completed_at, failure_reason (when failed),
external_reference (id returned by the external system).
- #REQ.payload-hash —
payload_hashis computed from the effect payload at creation time. If the action is later disputed, the hash proves what was sent.
Invariants
- #REQ.requires-attested-edition — A Decision Effect MUST reference an attested Edition via
edition_id. Unattested decisions cannot generate Decision Effects — the Edition (Layer B) is the firewall between deliberation and execution. - #REQ.one-way-firewall — Decision Effects flow one way: Decision Effects can create WorkflowTasks (
human_process→create_task()); WorkflowTasks cannot create Decision Effects. Nothing crosses from the deliberation layer to the execution layer except through an attested Edition. - #REQ.timeout-raises-signal — When a Decision Effect's
deadlinepasses withoutcompletedorfailed, the system records aneffect_timeoutevent and generates asignal_type: effect_timeout,severity: highSignal. That Signal enters the standard OODA flow as adecision_driveninvestigation referencing the original Edition; the chain is traceable viacorrelation_id. This is the self-healing escalation loop for stuck effects. - #REQ.append-only-ledger — Effect events are append-only on the investigation ledger; the object's status is descriptive of (not a substitute for) that audit trail.
Done-when
The behavior EPIC #12 (Decision Effects System, Connor Epoch 2) delivers is complete when:
- #REQ.done-effects-on-attest — Attesting an Edition whose decision template carries
effects[]creates DecisionEffect docs in Elasticsearch. - #REQ.done-validated-and-logged — Effect status transitions are validated and logged as ledger events.
- #REQ.done-one-handler — At least one handler (
agent_dispatch) successfully calls an external MCP endpoint. - #REQ.done-lineage — Effects are visible in
get_decision_lineageoutput.
Prerequisite infrastructure (Connor epochs): Epoch 0 MCP subscribe and Epoch 1 MCP agent + block provenance metadata must be in place — effects are the first feature that uses that infrastructure to act after a decision.
Related products
product.task— the deliberation-phase counterpart. A WorkflowTask produces evidence and decisions (Layer A); a Decision Effect executes a sealed decision (Layer C). They are distinct objects with distinct lifecycles. The only link is the one-wayhuman_processbridge: a Decision Effect MAY create a WorkflowTask; a WorkflowTask never creates a Decision Effect.component.cortex.task-and-effect— cortex's component contract for both objects. It owns the WorkflowTask lifecycle and carries the pack-level Decision Effect declaration syntax and dispatch implementation guidance (#effect,#effect.declaration,#effect.mapping,#effect.one-way). The authoritative Decision Effect schema it points at iscomponent.cortex.decision-evidence#effect.product.edition— the attested Edition is the trigger and the firewall; a Decision Effect references it viaedition_idand cannot exist without it.component.sentinel.alerting— thenotification/escalation surface. Effect timeouts raise Signals that feed decision-intelligence alerting; sentinel is a co-owner of the notification side of effect outcomes.
Open questions
- Handler registry.
agent_dispatchis the first handler; the registration mechanism for additionalexternal_dispatch/notificationhandlers (and whether handlers are pack-declared or code-registered) is not yet specified. - Federated verification. When both originating and target systems are DES-compliant, an acknowledgment MAY
carry cross-system hash references (
external_reference,external_ledger_ref,completion_hash) pointing at the target's own sealed Edition. The federation protocol for this is informative only and not yet pinned. cancelledtrigger. The lifecycle admitscancelledbefore completion, but who may cancel an in-flight effect, and under what authorization, is unspecified.
Required by: platform.relay
Realized by: component.conduit.effect-engine