---
title: "Live goal state of one Mnemom Agent session"
method: GET
path: "/agent/sessions/{conversationId}"
tags: ["Code"]
---

# Live goal state of one Mnemom Agent session

`GET /agent/sessions/{conversationId}`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/agent/sessions/{conversationId}`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Mnemom-Api-Key`
  - API key in cookie `mnemom_session`

Backs `mnemom agent show`. Resolves the org like `GET /v1/code/entitlement` (explicit `org_id` else the caller's primary org), requires membership, and confirms `agent_id` belongs to that org — an unknown agent and an agent in another org are the SAME 404 `agent_not_found`, so existence never leaks across tenants. Then relays the gateway's state for `conversationId` verbatim: the sealed goal contract (`sealed`, with the gateway's `hash` — the only sealed hash; a locally computed one differs because the gateway normalises absent arrays), the latest alignment verdict, the turn counter, the guardrail ceilings/state, the seal lifecycle (`seal`), the last-50 verdict trail (`verdict_trail`) and the judging counts (`unjudged_turns`/`memoised_turns`). `null`/`[]` sections mean the gateway holds nothing for that conversation (absence is data, never a 404); the same is true of a session sealed before these fields existed on an older gateway. 503 `gateway_unavailable` when the gateway is unset or unreachable.

## Path parameters

- `conversationId` string, required

## Query parameters

- `agent_id` string, required
- `org_id` string

## Response `200`

The session's live goal state. Every gateway-owned section is nullable — a session that never sealed a goal contract returns `sealed: null`, `verdict: null`, `turn: null`, `guardrails: null`.

- object
  - `conversation_id` string, required
  - `agent` object, required
    - `id` string, required
    - `name` string, nullable, required
  - `org_id` string, required
  - `sealed` object, nullable, required: What the gateway sealed for this conversation.
    - `contract` unknown, required
    - `hash` string, required: The gateway's sealed hash — the canonical one.
    - `sealed_at` string, date-time, required
    - `version` integer: The contract version (1 for the original seal; an owner update bumps it). Absent on a seal stored before this field existed.
    - `seal_reason` 'first' | 'after_expiry': Why this seal was made. Absent on a seal stored before this field existed.
    - `expired_hash` string: The lapsed seal's hash, set only on an `after_expiry` seal.
    - `updated_from` string: The previous version's hash, set only on an explicit owner update (never on a seal).
  - `verdict` object, nullable, required: The latest goal-alignment verdict.
    - `turn` integer, required
    - `verdict` string, required
    - `reason` string, required
    - `at` string, required
    - `streak_start` integer
  - `turn` integer, nullable, required: Turns the gateway has counted for this conversation.
  - `guardrails` object, nullable, required
    - `ceilings` object, required: The guardrail ceilings the contract sealed.
      - `max_turns` integer, nullable
      - `budget_usd` number, nullable
      - `stall_turns` integer, nullable
      - `time_limit_s` integer, nullable: Wall-clock ceiling in seconds, measured from when the contract was first sealed (an update does not restart the clock). `null` when the sealed contract set no time limit.
    - `state` object, nullable, required: Current guardrail counters (turns, spend, stall, crossed flags).
      - `turns` integer
      - `spend_usd` number
      - `stall_run` integer
      - `fired` object: Which ceilings have crossed (each fires at most once).
        - `turns` boolean
        - `budget` boolean
        - `stall` boolean
        - `time` boolean: The wall-clock ceiling crossed.
  - `seal` union, required: The seal's lifecycle. `live`: a sealed contract currently governs. `expired`: the prior seal lapsed (24h idle) and the next engaged request will seal afresh. `null` normally means no seal has ever been made for this conversation, but the API also returns `null` if the gateway sent a seal payload out of contract (an unknown `state`, or a required subfield missing/mistyped) — a malformed seal is dropped rather than relayed half-trusted, since `mode` (nudge vs enforce) is conformance-relevant. The two cases are distinguished in the API's own logs (`component: "agent-session", event: "seal_dropped"`), not in this field.
    - object
      - `state` 'live', required
      - `version` integer, required
      - `hash` string, required
      - `sealed_at` string, date-time, required
      - `reason` 'first' | 'after_expiry' | 'null', nullable, required
      - `expired_hash` string, nullable, required
      - `updated_from_hash` string, nullable, required
      - `mode` 'nudge' | 'enforce', required: Whether a crossed ceiling only nudges (`nudge`) or refuses the next request (`enforce`).
    - object
      - `state` 'expired', required
      - `version` integer, required
      - `hash` string, required
      - `sealed_at` string, date-time, required
  - `verdict_trail` object[], required: The last 50 verdicts, oldest first; empty when none judged yet. Under `enforce`, a request refused at a ceiling (429, not counted as a turn) is on the trail too, as a `refused` entry whose `turn` is the turn it would have been.
    - `request_id` string, nullable, required
    - `turn` integer, required
    - `verdict` 'aligned' | 'drifting' | 'violation' | 'refused', required: The judge's verdict, or `refused` for an enforce-mode ceiling refusal (never a judge verdict, never the session's latest `verdict`).
    - `ceilings` string[]: Only on a `refused` entry: the ceilings the refusal named.
    - `reason` string, required
    - `fence_breach` boolean, nullable, required: A conclusive mechanical fence check; `null` means the contract has no fences or the verdict predates the check.
    - `at` string, required
  - `unjudged_turns` integer, nullable, required: Assistant turns under the current seal with no verdict (a cut-off/aborted response, a judge that failed or never ran, a non-streamed final turn). `null` when no judge ledger counts under the current seal.
  - `memoised_turns` integer, nullable, required: Turns the judge memo graded without re-running the judge — inherited from a prior turn judged aligned under the same contract version with a matching tool-call shape and text. `null` alongside `unjudged_turns`.

## Other responses

- `400`: `agent_id` is missing (`agent_id_required`).
- `401`: Authentication required
- `403`: Forbidden
- `404`: No org for the caller (`not_found`), or the agent does not exist / is not in the resolved org (`agent_not_found` — deliberately the same answer for both).
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `503`: The agent lookup failed (retryable), or the Mnemom gateway is unset or unreachable (`gateway_unavailable`, with `details.reason`).

## Changes

- **2026-10-20** `e13923bd55ef`: 1 warning, 1 info
  - added the new `refused` enum value to the `verdict_trail/items/verdict` response property for the response status `200`
  - added the optional property `verdict_trail/items/ceilings` to the response with the `200` status

[Operation history](https://skmtc.dev/mnemom/apis/mnemom-api/changes/agent/sessions/:conversationId/get.md)

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/e13923bd55ef?raw)
