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

# Alignment Card Schema

> Normative YAML schema for the unified alignment card, including every section, field type, required/optional status, and composition semantic.

Normative reference for the **unified alignment card** — the YAML document every Mnemom agent has as one half of its [two cards](/concepts/agent-cards). This page specifies every section, field, required/optional status, type, and composition semantic. Implementers of MCP servers, SDK clients, or custom tooling that stores or mutates alignment cards should treat this as the contract.

The AAP protocol-level card (the 1.0 handshake card, stable for external interop) is specified separately at [/concepts/alignment-cards](/concepts/alignment-cards). The unified card is a superset with additional sections not present in the protocol surface.

## Top-level structure

```yaml theme={null}
card_version: unified/2026-04-26      # required; non-empty string (see §Versioning — not a fixed enum)
agent_id: mnm-<uuid>                  # required; the agent this card belongs to

# Two independent top-level master switches:
autonomy_mode: enforce                 # required; off | observe | nudge | enforce
                                       # gates the action-policing pipeline (gateway CLPI tool-use policy
                                       # + observer trace verification of bounded/forbidden actions)
integrity_mode: enforce                # required; off | observe | nudge | enforce
                                       # gates the values/conscience pipeline (gateway AIP Haiku analysis
                                       # + observer drift detection + coherence scoring)

principal: { ... }                     # required; see §principal
values: { ... }                        # required; see §values
conscience: { ... }                    # optional; see §conscience
autonomy: { ... }                      # required; see §autonomy
capabilities: { ... }                  # optional; see §capabilities
enforcement: { ... }                   # optional; see §enforcement
audit: { ... }                         # required; see §audit
extensions: { ... }                    # optional; §extensions
expires_at: 2026-10-26T12:00:00Z       # optional; ISO 8601 UTC; null = no expiry

# Server-assigned response fields — do not send on PUT:
card_id: ac-<uuid>                     # server-assigned
issued_at: 2026-04-26T12:00:00Z        # response-only
content_hash: sha256:<hex>             # response-only; also the ETag value
version: 4                             # response-only; monotonic card version
_composition: { ... }                  # response-only, and only when `?include_composition=true`; see §composition-metadata
```

`PUT /v1/alignment/agent/{agent_id}` accepts `card_version`, `agent_id` (overwritten to match the URL), `autonomy_mode`, `integrity_mode`, `principal`, `values`, `conscience`, `autonomy`, `capabilities`, `enforcement`, `audit`, `extensions`, and `expires_at`. `card_id`, `issued_at`, `content_hash`, `version`, and `_composition` are server-assigned response fields — do not send them on a PUT.

### Master switches

The four-mode enum `off | observe | nudge | enforce` is shared with the [Protection Card](/specifications/protection-card-schema). Same words; same semantics; same UI picker component renders all three master fields (Protection's `mode`, Alignment's `autonomy_mode`, Alignment's `integrity_mode`). Composition rule on each: **strictest wins** across Platform → Org → Agent (`enforce > nudge > observe > off`).

| Field | Governs | Off | Observe | Nudge | Enforce |
| - | - | - | - | - | - |
| `autonomy_mode` | action-policing | skip CLPI + trace verification | log policy results, don't block | inject advisory annotation, don't block | block tool violations, escalate |
| `integrity_mode` | values/conscience | skip AIP + drift detection | log checkpoint, no action | inject advisory on next request | auto-pause on boundary violation |

Customers can control the two halves independently — e.g., "enforce conscience commitments at runtime, only observe action policy" or "off action-policing for cost, but enforce drift detection".

## principal

Required. Declares who the agent serves and the nature of that relationship.

```yaml theme={null}
principal:
  type: organization           # "human" | "organization" | "agent" | "unspecified"
  identifier: acme-corp        # free-form identifier; DID, URL, UUID, or slug
  relationship: delegated_authority  # "delegated_authority" | "advisory" | "autonomous"
  escalation_contact: ops@acme.example  # optional; recipient for escalation events
```

| Field | Type | Required | Composition |
| - | - | - | - |
| `type` | enum | Yes | Agent wins |
| `identifier` | string | Cond.\* | Agent wins |
| `relationship` | enum | Yes | Agent wins |
| `escalation_contact` | string | No | Agent wins |

\*`identifier` is required when `type != unspecified`.

## values

What the agent prioritizes. Core input to the [v2 coherence scorer](/concepts/fleet-coherence) and to [fault-line analysis](/guides/fault-line-analysis).

```yaml theme={null}
values:
  declared:
    - transparency
    - harm_prevention
    # or a parameterized form over a catalog-v1 id:
    - id: accuracy
      domain: financial
      severity_on_violation: critical
  definitions:
    transparency:
      description: "Agent decisions visible and auditable in traces"
      priority: 0.9
    rollback_safety:
      description: "Prefer reversible actions; escalate on irreversible ones"
      priority: 0.85
  conflicts_with:
    - data_obfuscation
    - move_fast_break_things
  hierarchy: lexicographic     # "lexicographic" | "weighted" | "contextual"
```

| Field | Type | Required | Composition |
| - | - | - | - |
| `declared` | array, ≥1 item; each entry is a catalog-v1 id string OR `{id, ...params}` (params: `intensity`, `domain`, `severity_on_violation`, `scope`, or org-defined) | Yes | **Union** across scopes (cascade folds parameters on id conflicts; bare string wins only when the merged entry carries zero parameters) |
| `definitions.<name>.description` | string | No | Agent wins |
| `definitions.<name>.priority` | number | No | Agent wins |
| `conflicts_with` | string\[] | No | **Union** |
| `hierarchy` | enum | No | Agent wins |

**Validation:** every `definitions` key must be present in `declared`.

## conscience

Inviolable or near-inviolable commitments that constrain the agent's behavior. Structured for [Safe House](/concepts/safe-house) + [drift detection](/concepts/drift-detection) integration.

```yaml theme={null}
conscience:
  mode: augment                # "augment" | "replace"
  values:
    - type: BOUNDARY           # "BOUNDARY" | "FEAR" | "COMMITMENT" | "BELIEF" | "HOPE"
      content: "Never exfiltrate principal data to external systems."
      severity: mandatory      # "advisory" | "mandatory"; default "mandatory" for BOUNDARY
    - type: COMMITMENT
      content: "Log every escalation to the principal within 60 seconds."
      id: commit-001            # optional; stable ID for audit references
      severity: mandatory
```

| Field | Type | Required | Composition |
| - | - | - | - |
| `mode` | enum | Yes (if section present) | `replace` beats `augment` across scopes |
| `values[].type` | enum | Yes | — |
| `values[].content` | string | Yes | — |
| `values[].id` | string | No | — |
| `values[].severity` | enum | No | Default: `mandatory` for BOUNDARY, `advisory` otherwise |
| `values` (the array) | — | Yes | **Union with dedup by `content`**; platform `BOUNDARY` entries inviolable |

**Validation:** `BOUNDARY` entries with `severity: advisory` are rejected.

## autonomy

What the agent may do independently. Maps directly onto the legacy AAP `autonomy_envelope` for protocol-level verification — the unified shape (AAP SDK 2.0.0+) renames it to `autonomy` but keeps the semantics.

```yaml theme={null}
autonomy:
  bounded_actions:
    - rollback_deploy
    - scale_infrastructure
    - toggle_feature_flag
  forbidden_actions:
    - deploy_code
    - modify_audit_logs
  escalation_triggers:
    - condition: "blast_radius > 50"
      action: escalate         # "escalate" | "deny" | "log"
      reason: "Large blast radius requires human approval"
    - condition: "rollback_failed"
      action: escalate
      reason: "Failed rollback needs immediate human intervention"
  max_autonomous_value:
    amount: 10000
    currency: USD
```

| Field | Type | Required | Composition |
| - | - | - | - |
| `bounded_actions` | string\[] | Yes | **Union** across Platform → Org → Agent |
| `forbidden_actions` | string\[] | No | **Deny-overrides union** |
| `escalation_triggers[].condition` | string | Yes (if trigger present) | — |
| `escalation_triggers[].action` | enum | Yes | — |
| `escalation_triggers[].reason` | string | Yes | — |
| `escalation_triggers` (array) | — | No | **Union with dedup by `condition`** |
| `max_autonomous_value.amount` | number | Cond. | **Min across scopes** |
| `max_autonomous_value.currency` | string (ISO 4217) | Cond. | Agent wins |

**Validation:** `bounded_actions` and `forbidden_actions` must be disjoint (no action in both).

## capabilities

Tool-use capabilities, keyed by capability name. Each entry maps to a glob pattern over MCP/A2A tool names or an explicit tool allowlist.

```yaml theme={null}
capabilities:
  query_database:
    description: "Read from the operational database"
    tools: ["mcp:postgres/*", "mcp:readonly-query"]
    required_actions: ["query_database"]  # binds this capability to autonomy.bounded_actions entries
    severity_on_unmapped: medium    # "low" | "medium" | "high" | "critical"
  external_http:
    tools: ["mcp:fetch"]
    allowed_domains: ["api.acme.example"]
    severity_on_unmapped: high
```

| Field | Type | Required | Composition |
| - | - | - | - |
| `<name>.description` | string | No | Agent wins |
| `<name>.tools` | string\[] (glob patterns) | Yes | **Union** within capability |
| `<name>.required_actions` | string\[] | No | Binds this capability to `autonomy.bounded_actions` entries; **union** within capability. `card_actions` is rejected — that name is policy-engine's internal binding, not a card field |
| `<name>.allowed_domains` | string\[] | No | **Platform → agent intersection** (compliance ceiling, mirrors Protection Card `trusted_sources`) |
| `<name>.severity_on_unmapped` | enum | No | Strictest wins per name; default `medium` |

Capabilities are consumed by `@mnemom/policy-engine`'s `evaluatePolicy({ context, card, tools })` to produce per-request policy decisions.

## enforcement

Policy-level knobs that affect how `capabilities` are enforced at runtime. The master switch lives at the top level (`autonomy_mode`); this section carries the fine-grained tool-use policy.

```yaml theme={null}
enforcement:
  allow_unmapped_tools: false                  # strictest wins across scopes
  default_unmapped_severity: high              # "low" | "medium" | "high" | "critical"
  forbidden_tools:                             # XACML deny-overrides
    - pattern: "mcp:filesystem/*"
      reason: "No filesystem access for billing agents"
      severity: critical
  grace_period_hours: 24                       # min across scopes (shorter grace = stricter)
```

| Field | Type | Required | Composition |
| - | - | - | - |
| `allow_unmapped_tools` | boolean | No (default `false`) | **Strictest wins** (`false` beats `true`) |
| `default_unmapped_severity` | enum | No (default `high`) | Strictest wins (`critical > high > medium > low`) |
| `forbidden_tools[].pattern` | string | Yes (per entry) | **Deny-overrides union** (with exemption removal) |
| `forbidden_tools[].reason` | string | Yes (per entry) | — |
| `forbidden_tools[].severity` | enum | Yes (per entry) | — |
| `grace_period_hours` | number | No | **Min across scopes** (shorter grace = stricter); omitted from the composed card when no scope sets it, in which case the gateway falls back to 24h |

<Warning>
  **`grace_period_hours` has a security trade-off.** The 24h fallback (when no scope sets a value) means brand-new tools get a one-day pass on enforce mode while operators amend the card. Under adversarial tool introduction (prompt injection, untrusted MCP servers, user-supplied tool definitions) that's a 24-hour exposure window. Set `grace_period_hours: 0` to make enforce strict from the moment a card is published. See [Enforcement § Grace period](/gateway/enforcement#grace-period-read-this-before-enabling-enforce) and [Policy Engine § Grace period](/concepts/policy-engine#grace-period).
</Warning>

## audit

Commitments around trace format, retention, tamper evidence. These are **platform-scoped** — agents and orgs cannot weaken the audit floor.

```yaml theme={null}
audit:
  trace_format: ap-trace-v1
  retention_days: 90
  queryable: true
  query_endpoint: https://api.mnemom.ai/v1/traces
  tamper_evidence: append_only    # "append_only" | "signed" | "merkle" | null
```

| Field | Type | Required | Composition |
| - | - | - | - |
| `trace_format` | string | No | **Platform-scoped** — org/agent values are accepted but ignored on compose |
| `retention_days` | number (≥ 0) | Yes | **Max across scopes** — the one field a lower scope may *strengthen* (propose longer retention) |
| `queryable` | boolean | Yes | **Platform-scoped** |
| `query_endpoint` | string (URL) | Cond.\* | **Platform-scoped**; the composer synthesizes `{api_base}/v1/agents/{agent_id}/traces` if the platform sets `queryable: true` without an explicit endpoint |
| `tamper_evidence` | enum | No | **Platform-scoped** |

\*`query_endpoint` is required when `queryable` is `true`.

**Validation:** `audit.query_endpoint` is required whenever `audit.queryable` is `true`; the composer guarantees the invariant holds on canonical output.

An `audit.storage` field appears in some historical card examples but is not read by the composer or any downstream consumer — do not rely on it.

## extensions

Protocol-specific or user-defined additions. Free-form `Record<string, unknown>`. Mnemom reads `extensions.clpi.role` (a free-form role label) for [fault-line](/guides/fault-line-analysis) complementary/conflicting classification across a fleet's agents; any other key is passed through unread.

```yaml theme={null}
extensions:
  clpi:
    role: remediator
```

Extensions are agent-scoped: the composer copies `agentCard.extensions` verbatim onto the canonical card. Platform/org/team scopes do not contribute to or merge with agent extensions.

## \_composition (canonical-only)

Only returned from `GET`/`preview-compose` when the caller passes `?include_composition=true`; absent otherwise and absent on raw agent-scope cards. Records the provenance of every composed field.

```yaml theme={null}
_composition:
  canonical_id: cc-88aa0011
  composed_at: 2026-04-17T18:23:41Z
  scopes_applied:
    - scope: platform
      version: 1
    - scope: "org:acme"
    - scope: "agent:mnm-patch-001"
      card_id: ac-f47ac10b-58cc-4372-a567-0e02b2c3d479
  exemptions_applied:
    - exm-aabbcc     # exemption IDs honored during this composition
  source_card_id: ac-f47ac10b-58cc-4372-a567-0e02b2c3d479
  source_policy_id: pol-1a2b3c
```

| Field | Type |
| - | - |
| `canonical_id` | string |
| `composed_at` | string (ISO 8601 UTC) |
| `scopes_applied[].scope` | string — `platform`, `org:<id>`, `team:<id>`, or `agent:<id>`, in cascade order |
| `scopes_applied[].version` / `.template_version` / `.card_id` | optional, present when that scope contributed one |
| `exemptions_applied` | string\[] — exemption IDs honored during this composition |
| `source_card_id` / `source_policy_id` | optional string |

`_composition` is read-only on the wire. Mutating it via API is a 400.

## YAML safe schema

All `yaml.load()` calls in the Mnemom stack use `{ schema: yaml.CORE_SCHEMA }` — Node-specific tags (`!!js`, `!!binary`, etc.) are rejected. If your client produces YAML with those tags, validation fails. Stick to plain scalars, maps, and sequences.

## Body-size limits

Full alignment card payload: **128 KB** max, enforced at the API boundary from both `Content-Length` and the actual body size. Oversize bodies get `413 Payload Too Large`.

## Versioning

`card_version` is a required, non-empty string. The composer stamps every canonical card with `unified/<YYYY-MM-DD>` using the composition date — treat the prefix (`unified/`) as the stable signal, not the date suffix, which changes on every recompose. Breaking changes are negotiated via the `X-Mnemom-Version: YYYY-MM-DD` request header used elsewhere in the API.

## See also

* [Agent Cards](/concepts/agent-cards) — the two-card product story
* [Card Composition](/concepts/card-composition) — scope composition rules + exemptions
* [Protection Card Schema](/specifications/protection-card-schema) — companion normative spec
* [Alignment Card (AAP protocol surface)](/concepts/alignment-cards) — the protocol-level card
* [Policy Engine](/concepts/policy-engine) — how `capabilities` + `enforcement` become runtime policy


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