---
title: "Explain policy evaluation for the alignment card"
method: POST
path: "/alignment/agent/{agent_id}/explain"
tags: ["Alignment"]
---

# Explain policy evaluation for the alignment card

`POST /alignment/agent/{agent_id}/explain`

## Request

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

Calls the policy engine in dry-run mode against the agent's composed alignment card and returns a structured trace + care-framed remediations. Optional `enrich: true` runs an LLM pass over the structured remediations to produce long-form prose; off by default. Read-style POST — no state mutation, no Idempotency-Key.

`request_snippet.tool_name` is REQUIRED and is a TOOL IDENTIFIER (`Read`, `Grep`, `Bash`) — the name matched against `capabilities.<name>.tools[]`, never a card action from `autonomy.bounded_actions` (`code_read`, `inference`). A request without it returns **400** with error code `missing_tool_name`: a verdict computed over zero tools would report `pass` having checked nothing (MNE-5820).

This rejection lands on API version `2026-08-17` (ADR-006) and applies to callers sending no `X-Mnemom-Version` header. A caller pinned to `2026-04-15` still receives **200** with the verdict shape, but the response labels the empty check explicitly in `reasoning` and in the first `suggested_remediations` entry — the old verdict is NOT reproduced, because it was produced by matching card-action names against the tool namespace, which is the defect this fixes.

## Path parameters

- `agent_id` string, required

## Request body

- object
  - `turn_id` string: Optional — bind to a specific gateway turn.
  - `request_snippet` object: The tool call to explain. REQUIRED — `request_snippet.tool_name` names the tool a verdict is wanted on, and a request without it is rejected with 400 `missing_tool_name`. A verdict computed over zero tools would report `pass` having checked nothing, so it is not offered (MNE-5820).
    - `tool_name` string: A TOOL IDENTIFIER — the name a runtime invokes (`Read`, `Grep`, `Bash`), matched against `capabilities.<name>.tools[]`. NOT a card action (`code_read`, `inference`, `tool_use`); those live in `autonomy.bounded_actions` and never match here.
    - `tool_args` object
  - `enrich` boolean: When true, runs an LLM pass over the structured remediations. Off by default.

## Response `200`

Policy evaluation trace + remediations.

- object
  - `ok` true, required
  - `resource` 'alignment', required
  - `trace` object, nullable: EvaluationResult from @mnemom/policy-engine. Null for protection in V1.
  - `reasoning` string, required: Care-framed prose summary.
  - `suggested_remediations` object[], required
    - `for` 'violation' | 'warning' | 'card_gap', required
    - `index` integer, required
    - `remediation` string, required
    - `method` string
    - `url` string
  - `enriched` boolean, required: True when the LLM enrichment ran.

## Other responses

- `400`: Bad request
- `401`: Authentication required
- `403`: Forbidden
- `404`: Resource not found
- `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.

---

[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/274b7a6ea182?raw)
