---
title: "Update a guardrail"
method: PATCH
path: "/v1/projects/{project_id}/guardrails/{guardrail_id}"
tags: ["Guardrails"]
---

# Update a guardrail

`PATCH /v1/projects/{project_id}/guardrails/{guardrail_id}`

## Request

- Base URL: `https://api.naturali.ai`
- URL: `https://api.naturali.ai/v1/projects/{project_id}/guardrails/{guardrail_id}`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.naturali.ai/authorize`, token URL `https://api.naturali.ai/token`, scopes: `mcp:access`)

Updates an existing guardrail. A `document` write that actually changes the policy increments `version` and archives the new document as a GuardrailVersion; metadata-only edits (name / description / context), and re-writing the document the guardrail already holds, leave the version untouched.

## Path parameters

- `guardrail_id` string, required

## Headers

- `If-Match` string

## Request body

- UpdateGuardrailRequest
  - `name` string
  - `description` string, nullable
  - `document` GuardrailDocument: The action-class document. `class` maps a call to an action class; `guard` gates class-B autonomy. Both are single JSON Logic expressions over the `args.*` / `context.*` / `runtime.*` namespaces.
    - `class` union, required: A class literal (`A` / `B` / `C` / `D`) or a JSON Logic expression returning one. An invalid result resolves to `default_class`.
      - 'A' | 'B' | 'C' | 'D'
      - object
    - `default_class` 'A' | 'B' | 'C' | 'D': Applied when the `class` expression returns anything other than a valid class. Defaults to `C` (fail-closed).
    - `guard` object: A single JSON Logic expression; when the call classifies as `B` it must evaluate truthy to execute autonomously. Compose multiple conditions with `{ "and": [...] }`.
    - `escalate` boolean: When `true`, a failing guard routes to approval instead of tripping fail-closed.
    - `expires_in` integer: Default approval window in seconds for a class-C approval this guardrail files. Omitted → the platform's 24h default. When several guardrails apply, the governing (strictest-matching) one's value is used.
  - `context_tool_id` string, nullable
  - `context_mode` 'merge' | 'replace' | 'null', nullable
  - `version_label` string: Optional tag for the config version this write archives (e.g. `pre-tightening`). Annotates the version only — it is not stored on the guardrail and is not part of the config, so labelling a change is never itself a change. Ignored when the write changes no policy, since no version is created.
  - `expected_version` integer, nullable: The version the caller believes the resource holds. When the resource is at any other version the write is refused with `409 VERSION_CONFLICT` and nothing is written; `meta.current_version` on that response names the version in force. Omit it to write unconditionally. Omitting it does not make the write unordered: two writes that reach the server together are still serialized, and the one whose version was taken first is refused the same way. What the field adds is refusing a write whose author read the resource some time ago and has not seen what happened since. The `If-Match` header carries the same precondition for a client that prefers the HTTP spelling. Sending both with different versions is `400 VALIDATION_FAILED`.

## Response `200`

Guardrail updated

- Guardrail
  - `id` string: Public ID of the guardrail
  - `project_id` string: Public ID of the owning project
  - `name` string: Human-readable name
  - `description` string, nullable: Optional description
  - `version` integer: Incremented on every document write; prior versions are archived
  - `document` GuardrailDocument: The action-class document. `class` maps a call to an action class; `guard` gates class-B autonomy. Both are single JSON Logic expressions over the `args.*` / `context.*` / `runtime.*` namespaces.
    - `class` union, required: A class literal (`A` / `B` / `C` / `D`) or a JSON Logic expression returning one. An invalid result resolves to `default_class`.
      - 'A' | 'B' | 'C' | 'D'
      - object
    - `default_class` 'A' | 'B' | 'C' | 'D': Applied when the `class` expression returns anything other than a valid class. Defaults to `C` (fail-closed).
    - `guard` object: A single JSON Logic expression; when the call classifies as `B` it must evaluate truthy to execute autonomously. Compose multiple conditions with `{ "and": [...] }`.
    - `escalate` boolean: When `true`, a failing guard routes to approval instead of tripping fail-closed.
    - `expires_in` integer: Default approval window in seconds for a class-C approval this guardrail files. Omitted → the platform's 24h default. When several guardrails apply, the governing (strictest-matching) one's value is used.
  - `context_tool_id` string, nullable: Optional tool the platform calls at evaluation time to fetch fresh guardrail context.
  - `context_mode` 'merge' | 'replace' | 'null', nullable: How tool-fetched context combines with the caller-supplied context.
  - `created_at` string, date-time
  - `updated_at` string, date-time

## Other responses

- `400`: Bad Request — invalid document or variable reference
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `409`: The resource has moved past the version this write read (`VERSION_CONFLICT`): a stated `expected_version` or `If-Match` no longer matches, or a concurrent write took the version first. `meta.current_version` names the version in force. Nothing is written.

---

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