---
title: "Get this layer's protection manifest"
method: GET
path: "/protection/agent/{agent_id}"
tags: ["Protection"]
---

# Get this layer's protection manifest

`GET /protection/agent/{agent_id}`

## Request

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

Returns the agent-scope protection spec as authored. Response is content-negotiated — YAML by default, or JSON with `Accept: application/json`. Pass `?include_composition=true` to include the `_composition` metadata block describing which scopes were merged. Pass `?include=sources` (see ADR-053) for the scope-resolution envelope — the contributing layers plus the composed result; the envelope shape is scope-specific (the four-scope `{teams[], agent}` body is the agent variant consumed by the dashboard editor). ETag is computed from `content_hash` (cards-as-primitive Phase 1); `If-None-Match` returns 304. For the composed view across scopes, use the `/effective` sub-resource (Wave 2).

## Path parameters

- `agent_id` string, required

## Query parameters

- `include_composition` boolean
- `include` 'sources'

## Headers

- `Accept` 'text/yaml' | 'application/yaml' | 'application/json'

## Response `200`

Protection manifest at this scope.

- union
  - UnifiedProtectionCard: Unified protection card (ADR-037). Safe House thresholds + trusted-source policy for a single agent. Shape matches src/composition/types.ts::UnifiedProtectionCard (canonical) and what the runtime validator at src/composition/validate.ts accepts. The customer-facing docs at /concepts/protection-card and /specifications/protection-card-schema document this same shape.
    - `card_version` string, required
    - `content_version` string: Optional. Which default content the card carries, e.g. `mnemom-agent-default/2.1.0` (semver within a lineage). Distinct from `card_version`, the schema version. New agents are born with it; composition carries the agent card's value onto the canonical card.
    - `card_id` string
    - `agent_id` string, required
    - `issued_at` string, date-time
    - `expires_at` string, date-time, nullable
    - `mode` 'off' | 'observe' | 'nudge' | 'enforce', required: Strictest-wins composition: enforce > nudge > observe > off.
    - `thresholds` object, required: Score bands. Must satisfy warn <= quarantine <= block; each value in [0, 1].
      - `warn` number, required
      - `quarantine` number, required
      - `block` number, required
    - `screen_surfaces` object, required: Which request surfaces Safe House inspects. Composed across scopes by OR-per-field (any scope requiring inspection wins).
      - `incoming` boolean, required: The user/principal prompt entering the agent.
      - `outgoing` boolean, required: The agent's response leaving the agent.
      - `tool_calls` boolean, required: Tool-use invocations the agent makes.
      - `tool_responses` boolean, required: Responses to tool calls returning to the agent.
    - `trusted_sources` object, required: Sources for which detectors short-circuit (each match logged in the trace). Composed as platform->agent intersection (compliance ceiling) with org+agent union inside that ceiling — an agent cannot widen trust beyond what the platform allows.
      - `domains` string[], required: DNS names or host:port entries.
      - `agent_ids` string[], required: Mnemom agent IDs (mnm-* / smolt-* prefixed).
      - `ip_ranges` string[], required: IPv4 or IPv6 CIDR ranges.
    - `protected_surface` object: Org-declared protected surface policy (MNE-830). Strengthen-only UNION across platform → org → team → agent: each scope may add entries; none may remove. The composer always emits this block; callers omit it to inherit the composed floor. See ADR-037 §protected_surface.
      - `assets` object[]: Protected assets. Intrinsic identity = `${kind}:${selector}` (normalized). Composer merges by identity, keeping the strictest entry per scope.
        - `kind` string, required: Asset kind (e.g. `row`, `field`, `resource`, `table`).
        - `selector` string, required: Asset selector (e.g. `customer:critical-0000`, `replica_dsn`).
        - `label` string: Human-facing display label (optional).
        - `reason` string: Why this asset is protected (optional).
        - `source_scope` string: Composer-assigned provenance (`platform`, `org:<id>`, `team:<id>`, `agent:<id>`). Server-assigned — do not send on a PUT.
      - `forbidden_operations` object[]: Operations that are unconditionally forbidden. Intrinsic identity = normalized `pattern`. Composer unions across scopes; on identity collision, severity → max.
        - `pattern` string, required: Operation pattern (e.g. `TRUNCATE`, `unscoped UPDATE/DELETE`, `exfiltrate:pii`).
        - `applies_to` string[]: Asset identities (`${kind}:${selector}`) this operation applies to. Empty/absent means GLOBAL.
        - `severity` 'low' | 'medium' | 'high' | 'critical': Severity level. Composer merges to strictest across scopes.
        - `reason` string: Why this operation is forbidden (optional).
        - `source_scope` string: Composer-assigned provenance. Server-assigned — do not send on a PUT.
      - `escalation_required` object[]: Operations that require escalation before proceeding. Same intrinsic-identity + union rules as forbidden_operations (minus severity).
        - `pattern` string, required: Operation pattern requiring escalation.
        - `applies_to` string[]: Asset identities this escalation applies to. Empty/absent = GLOBAL.
        - `reason` string: Why escalation is required (optional).
        - `source_scope` string: Composer-assigned provenance. Server-assigned — do not send on a PUT.
    - `review` object: Review-hold policy (Safe House Review, Slice 2a — MNE-920 design). gate_on is the minimum verdict band per surface that escalates to a review-hold. Composition is strictest-wins; on_timeout defaults to 'reject' (fail-closed). reviewer.kind 'endpoint' is designed for MNE-1650 and not consumed yet.
      - `enabled` boolean, required
      - `gate_on` object
        - `incoming` 'off' | 'warn' | 'quarantine' | 'block'
        - `outgoing` 'off' | 'warn' | 'quarantine' | 'block'
        - `tool_calls` 'off' | 'warn' | 'quarantine' | 'block'
        - `tool_responses` 'off' | 'warn' | 'quarantine' | 'block'
        - `integrity` 'off' | 'review_needed' | 'boundary_violation'
      - `sla_seconds` number
      - `on_timeout` 'reject' | 'release'
      - `notify` object
        - `sse` boolean
        - `webhooks` boolean
      - `reviewer` object
        - `kind` 'builtin_opus' | 'endpoint', required
        - `endpoint_url` string, uri
      - `quarantine_notice` string
    - `extensions` object: Free-form extension slot for non-canonical fields. Ignored by the composer; preserved on read for tooling that needs an audit-tail metadata bag.
    - `_composition` CompositionMetadata: System-managed block describing which scope sources merged into the canonical card. Only returned when `?include_composition=true`.
      - `canonical_id` string
      - `composed_at` string, date-time
      - `scopes_applied` object[]
        - `scope` string: `platform`, `org:<id>`, or `agent:<id>`.
        - `version` integer
        - `template_version` integer
        - `card_id` string
      - `exemptions_applied` string[]
      - `source_card_id` string
      - `source_policy_id` string
    - `content_hash` string: Response-only: content hash of the composed card (`sha256:<hex>`), injected by the GET/PUT response. Server-assigned — do not send on a PUT.
    - `version` integer: Response-only: monotonic card version, injected by the GET/PUT response. Server-assigned — do not send on a PUT.
  - ProtectionCardSourcesEnvelope: Four-scope sources envelope returned by `GET /v1/agents/{agent_id}/protection-card?include=sources`. Identical shape to `AlignmentCardSourcesEnvelope`.
    - `platform` CardSourceScope, required: One slice of a sources envelope. `card_json` carries the raw template at that scope (full UnifiedAlignment/Protection card, the org/team template, or the platform-defaults object). `available: false` means no card is configured at this scope.
      - `card_json` object, nullable, required
      - `available` boolean, required
    - `org` OrgCardSourceScope, required: One slice of a sources envelope. `card_json` carries the raw template at that scope (full UnifiedAlignment/Protection card, the org/team template, or the platform-defaults object). `available: false` means no card is configured at this scope.
      - `card_json` object, nullable, required
      - `available` boolean, required
      - `org_id` string, nullable
      - `org_name` string, nullable
    - `teams` TeamCardSourceScope[], required
      - `card_json` object, nullable, required
      - `available` boolean, required
      - `team_id` string, required
      - `team_name` string, nullable
    - `agent` CardSourceScope, required: One slice of a sources envelope. `card_json` carries the raw template at that scope (full UnifiedAlignment/Protection card, the org/team template, or the platform-defaults object). `available: false` means no card is configured at this scope.
      - `card_json` object, nullable, required
      - `available` boolean, required
    - `composed` CardSourceScope, required: One slice of a sources envelope. `card_json` carries the raw template at that scope (full UnifiedAlignment/Protection card, the org/team template, or the platform-defaults object). `available: false` means no card is configured at this scope.
      - `card_json` object, nullable, required
      - `available` boolean, required
    - `composed_stale` boolean, required
    - `my_role` 'super_admin' | 'org_owner' | 'org_admin' | 'team_admin' | 'org_member' | 'org_viewer' | 'org_auditor' | 'null', nullable, required: The caller's effective role on the resource. Computed server-side per ADR-053; frontends derive `canEdit` exclusively from this field. `team_admin` only appears on team-scope responses. `null` means the caller has no role on this resource (the request still authenticated, but no role applies — e.g. an org-scope response read by an unrelated user).

## Other responses

- `304`: Not Modified — the client's `If-None-Match` matches the current ETag.
- `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)
