Skip to content
Open the portal
Compliance & legal

The decision record, explained

Compliance & legal12 min read

A decision record is one JSON document. It is small, it is signed, and it is meant to be read by a person under pressure: a complaints handler, an auditor, a lawyer. This page reads one from top to bottom.

A supervisory authority, a court or an internal audit asks the same things about an automated decision. The record has a place for each.

Question Where the answer is
What was decided, and about whom? subject and the outcome event
Which system decided it? agent
What information did it see? input and retrieval events, as fingerprints
Which model, and what did it say? model_call events: provider, model, fingerprints of prompt and answer
What did it look up or do along the way? tool_call events
Which rule applied? policy_eval events: policy id, version, result
Did a person allow it, and were they entitled to? approval events and the human actors with their role and identity provider
What action was taken, and when? action events
Where did this record come from, how sure are we, and who holds it? provenance, assurance, custody

Subject is the person or thing the decision affected, as a type and an id: order 48213, applicant 72819, claim 8843. Everything in Stratl is filed under subjects, so “every decision about this applicant” is one screen. A subject may have a display name for readers.

Agent is the software that decided: an id such as claims-triage, and optionally a human-readable name, a version and an owner. The version matters: it is how you later say “this was the September release”.

Actors are everyone who took part. The agent is always one. Humans appear when they approved, reviewed or requested something, with their id (usually an email), their role (support_lead, medical_director, credit_officer) and the identity provider that vouched for them (okta, anthropic). “A person approved it” is weak; “priya@example.com, support lead, signed in through Okta, approved it at 14:32” is evidence.

Events are the body of the record: numbered facts, in order, each with a timestamp. There are exactly eight types. A source uses the ones it can see; a record with only a model call and an outcome is still valid, and a framework pack will say what is missing.

Type What it means What it carries
input Something arrived: a ticket, a form, a claim file A fingerprint of it
retrieval The system looked documents up The source, and a fingerprint per document
model_call A model was asked something Provider, model, version, fingerprints of the prompt, the answer and the settings, token counts
tool_call The system called a tool or another system Tool name, fingerprints of the arguments and the result, whether it succeeded
policy_eval A written rule was applied Policy id, version, result, and the rule that fired
approval A person was asked, or not Whether one was required, who answered, with what authority, what they decided, through which identity provider
action Something was done in the world Name, target, when it executed, the result, a fingerprint of the parameters
outcome How it ended for the subject Status, whether it was adverse, a category, the effect on the subject

What Stratl adds: provenance, assurance, custody, integrity

Section titled “What Stratl adds: provenance, assurance, custody, integrity”

Provenance says where the record came from: the source (sdk-python, otel, langfuse, anthropic-compliance), the source’s own record ids (a trace id, a session id), the connector version and when it was ingested.

Assurance says how the events were captured, and Stratl never raises it. Observed means a tracer or SDK watched them happen. Attested means a system vouched for them. Enforced means the action could not have happened without passing through the recording step; Stratl’s own workflow records are enforced, because the notice could not have been sent without that endpoint.

Custody says who holds the storage and the signing key, stratl or customer, in which region, and where the public key can be fetched.

Integrity is added when the record is written: the canonicalisation and hash algorithm, the record hash, the previous record’s hash and this record’s position in the chain, the signature and the key id. This block is not part of what is hashed; everything above it is.

Some records in your stream are about Stratl’s own actions on your evidence. They look like any other record and verify the same way. They are filed under the same subject as the decision they concern, with the agent named for the workflow.

Prefix Written when Agent
DEC-WF- A notice is approved, sent or withdrawn; a reconsideration is recorded; a legal hold is placed or lifted stratl-notices, stratl-retention
DEC-RC- A human reconsideration of a decision stratl-notices
DEC-KEY- The workspace’s signing key was used: one action event per use, sealed at each checkpoint stratl-custody
DEC-CT- Custody moved to the customer’s own cloud, carrying the fingerprint of the dual-signed transfer statement stratl-custody

This is the golden fixture the three implementations must hash identically. Comments are not part of the record.

{
"srf_version": "0.1",
"decision_id": "DEC-01J8ZK3Q9W7X2P4M6N8R0T1V3Y", // ULID, prefixed DEC-
"subject": { "type": "order", "id": "48213" },
"agent": { "id": "support-bot", "name": "Support Agent", "version": "2026.09.1" },
"actors": [
{ "kind": "agent", "id": "support-bot" },
{ "kind": "human", "id": "priya@example.com", "identity_provider": "okta", "role": "support_lead" }
],
"events": [
{ "seq": 1, "type": "input", "at": "2026-09-17T14:31:02.000Z", "hash": "sha256:5e88…42d8" },
{ "seq": 2, "type": "model_call", "at": "2026-09-17T14:31:04.000Z", "provider": "openai", "model": "gpt-5",
"version": "0611", "input_hash": "sha256:5e88…42d8", "output_hash": "sha256:2c26…e7ae" },
{ "seq": 3, "type": "tool_call", "at": "2026-09-17T14:31:06.000Z", "name": "orders.read",
"args_hash": "sha256:fcde…8fb9", "result_hash": "sha256:9f86…0a08", "status": "ok" },
{ "seq": 4, "type": "policy_eval", "at": "2026-09-17T14:31:11.000Z",
"policy_id": "refunds_above_100_require_approval", "version": "7", "result": "human_required" },
{ "seq": 5, "type": "approval", "at": "2026-09-17T14:32:00.000Z", "required": true,
"requested_at": "2026-09-17T14:31:42.000Z", "approver": "priya@example.com",
"identity_provider": "okta", "authority": "support_lead", "decision": "approved" },
{ "seq": 6, "type": "action", "at": "2026-09-17T14:32:02.000Z", "name": "refunds.issue", "target": "order/48213",
"params_hash": "sha256:a665…7ae3", "executed_at": "2026-09-17T14:32:02.000Z", "result": "executed" },
{ "seq": 7, "type": "outcome", "at": "2026-09-17T14:32:03.000Z", "status": "completed", "adverse": false, "category": "refund" }
],
"provenance": { "source": "sdk-python", "source_type": "sdk", "connector_version": "0.1.0", "ingested_at": "2026-09-17T14:32:03.500Z" },
"assurance": "observed",
"custody": { "storage": "customer", "key": "customer", "region": "eu-west-1" },
"retention": { "policy_id": "eu-ai-act-6m", "legal_hold": false }, // what the source declared, optional
"integrity": { // added by the service, not hashed
"canonicalization": "RFC8785", "hash_alg": "sha256",
"record_hash": "4a030b51358fd8e7d67ef9bac89f5642baef997e7d62f73780e1e123f6b98d34"
}
}