> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aethis.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Decision envelope

> Every /decide response carries a reproducibility envelope for audit and replay.

<Note>
  Successful decision responses identify the serving build in `engine_version`.
  Read that field from your response rather than relying on a version copied into a tutorial.
  [What the deployed engine serves](/reference/deployed-contract).
</Note>

Every response from `POST /api/v1/public/decide` (and `POST /rulesets/{id}/explain-failure`) carries a small set of envelope fields that let callers reference, verify, and replay a specific decision — without the server having to echo potentially-PII inputs back.

If you're building anything regulated, audited, or support-ticketable, read this page.

## The fields

| Field | Type | Example | Replay-critical |
| - | - | - | :-: |
| `decision_id` | string | `dec_k3h9s2MnPq_7xZbA` | ✅ |
| `inputs_hash` | string | `sha256:5f4dcc3b...` | ✅ |
| `engine_version` | string | `aethis-core@0.41.1` | ✅ |
| `ruleset_id` + `ruleset_version` *or* `rulebook_id` | string | `uk-fsm-child-eligibility:20260528-244428c1`, `v3` | ✅ |
| `content_digest` | string | `sha256:<hex>` | ✅ (release candidate) |
| `decision_time` | string (ISO-8601 UTC) | `2026-04-17T12:34:56.789Z` | informational\* |

\*`decision_time` is only replay-critical when a rule references wall-clock time.

### `decision_id`

Unique per invocation, format `dec_<16 urlsafe chars>`. **Fresh on every call** — two identical requests get different IDs even when the server serves the response from its decision cache. Use it in bug reports, support tickets, and client-side logs. The server emits a structured log line keyed by `decision_id`, so operators can trace a user-quoted ID back to full context.

### `inputs_hash`

Algorithm-prefixed SHA-256 over the [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) canonical form of `field_values`. Invariant under key reordering, whitespace, and `1` vs `1.0` vs `1e0`. Lets a caller prove "this decision was computed from exactly these inputs" without the server persisting or echoing the values. The `sha256:` prefix is forward-compatibility for when the algorithm rotates — parsers should split on `:` and route by algorithm.

### `engine_version`

Product-prefixed semver, format `aethis-core@<semver>`. Same value for the lifetime of a server process. Different engine versions can produce different outcomes for identical inputs and rule artefacts if DSL semantics or solver behaviour change — reliable replay requires matching the engine version.

### `ruleset_version` / `rulebook_id`

Ruleset calls return `ruleset_id` + `ruleset_version`; rulebook calls return `rulebook_id`.

### `content_digest`

`sha256:<hex>` over the published rule content that produced the decision.

**This, not `ruleset_version`, is what replay pins to.** `ruleset_version` is a
*mutable authoring label* — the `vN` counter, bumped on every publish. A
republish of byte-identical content can advance the label while reusing the
existing content cut, so two decisions with different labels may have run
against identical rules, and matching labels are not by themselves proof of
matching rules. `content_digest` is *immutable content identity*: it changes
whenever the rules change, and only when the rules change.

For a published leaf ruleset the candidate always resolves the caller's slug to
this triple — immutable `ruleset_id`, real `ruleset_version`, `content_digest` —
on both cold and warm cache paths. Composed rulebook (`rulebook_id`) responses
still report `"unknown"` for the composition until resolved member identity
lands.

## How to replay a decision

The envelope is designed for two-party replay: the caller keeps the inputs they sent, the server re-runs the engine when asked.

1. Retain the original `field_values` and the full envelope on the caller side.
   If the call used `inquiry_context`, retain that context too: it selects the
   next question but does not change eligibility facts or the decision.
2. Re-run `POST /decide` with the same `field_values`, `ruleset_id`, and, where
   applicable, `inquiry_context`.
3. Verify:
   * `inputs_hash` matches the retained value → inputs are identical
   * `engine_version` matches → engine build is the same
   * `content_digest` matches → the rule content is byte-identical (the strongest of these checks, and the one to rely on)
   * `ruleset_id` matches → the same published ruleset was resolved
   * `ruleset_version` matches → same authoring label. Necessary, not sufficient: the label can move without the content changing, so never treat it as artefact identity on its own
   * The new `decision` equals the original → decision is reproducible

The new response will have a **different** `decision_id` and `decision_time` — those are per-invocation and deliberately excluded from the replay contract.

## Caching interaction

The server caches responses for identical `(ruleset_id, field_values, flags, inquiry_context)` combinations for up to 10 minutes. When supplied, `inquiry_context` is normalised before it participates in that identity. Per-call envelope fields (`decision_id`, `decision_time`, `inputs_hash`, `engine_version`) are stripped before caching and stamped fresh on every response. **A cache hit is invisible from the envelope's perspective** — the ID is fresh, the hash is computed from the caller's actual inputs, the timestamp is current.

## Example

```json theme={null}
{
  "decision": "eligible",
  "fields_provided": 2,
  "fields_evaluated": 2,
  "decision_id": "dec_k3h9s2MnPq_7xZbA",
  "inputs_hash": "sha256:5f4dcc3b5aa765d61d8327deb882cf99",
  "engine_version": "aethis-core@0.48.0",
  "ruleset_id": "uk-fsm-child-eligibility:20260528-244428c1",
  "slug": "aethis/uk-fsm/child-eligibility",
  "ruleset_version": "v3",
  "content_digest": "sha256:EXAMPLE_DIGEST_0000000000000000000000000000000000000000000000",
  "field_errors": null,
  "decision_time": "2026-04-17T12:34:56.789Z"
}
```

Illustrative — the digest and IDs are placeholders. The field names, and the
`ruleset_version` / `content_digest` keys, are what `api.aethis.ai` returns
today.

## What to log on your side

For audited workloads, retain at minimum:

* `decision_id` — your handle for this decision
* `inputs_hash` — proves the inputs later
* `engine_version` + `ruleset_id` + `content_digest` — pins the artefact. Log `ruleset_version` too for human readability, but resolve any dispute on the digest
* Your own request correlation ID (e.g. application trace ID)

Retain the raw `field_values` separately if your compliance regime requires input-level audit; `inputs_hash` alone is sufficient for reproducibility proof, but not for "what exactly did the user submit" questions.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.