> For the complete documentation index, see [llms.txt](https://cerebral-systems.gitbook.io/cerebral-systems-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cerebral-systems.gitbook.io/cerebral-systems-docs/introduction.md).

# Introduction

### Overview

Warrant is an security action boundary for agents. Agents can plan and reason in any runtime. Before they mutate an external system, they submit a structured action proposal to Warrant.

Warrant is not an agent framework, planner, model router, memory layer, or tool SDK. It owns the security boundary between agent intent and side effects: policy gating, approval routing, actuator execution, and Merkle-rooted audit.

```mermaid
sequenceDiagram
  participant Agent
  participant Warrant
  participant Approver
  participant Actuator
  participant Audit
  Agent->>Warrant: POST /v1/actions
  Warrant->>Warrant: Validate proposal and evaluate tenant policy
  alt allow
    Warrant->>Actuator: Execute registered action
    Warrant->>Audit: Append execution
    Warrant-->>Agent: allow verdict
  else needs_approval
    Warrant->>Audit: Append held verdict
    Warrant-->>Agent: needs_approval verdict
    Approver->>Warrant: POST /v1/actions/{id}/approve
    Warrant->>Actuator: Execute after approval
    Warrant->>Audit: Append approval and execution
  else deny
    Warrant->>Audit: Append denial verdict
    Warrant-->>Agent: deny verdict
  end
```

### Core Concepts

| Concept         | What it means                                                                           |
| --------------- | --------------------------------------------------------------------------------------- |
| Action proposal | The JSON contract an agent submits before a side effect.                                |
| Policy gate     | A pure decision function that returns `allow`, `needs_approval`, or `deny`.             |
| Approval        | A human/operator release step for held proposals.                                       |
| Actuator        | The registered boundary that performs the side effect after policy allows it.           |
| Audit trace     | Append-only action history with Merkle-rooted event integrity.                          |
| Tenant API key  | Agent credential scoped to one tenant runtime and policy.                               |
| Admin key       | Operator credential used to create tenants, issue keys, revoke keys, and update policy. |

### Storage Model

Warrant uses `djangorestframework-api-key` for API-key creation and verification. Full key secrets are returned only when created. Later list calls return safe metadata only:

```json
{
  "key_id": "abcd1234",
  "name": "staging-worker",
  "scope": "agent",
  "tenant_id": "acme-agents",
  "prefix": "abcd1234",
  "revoked": false,
  "created": "2026-06-23T12:00:00+00:00",
  "expires_at": null
}
```

`key_id` is the DRF API Key prefix. Use it for revoke calls.

### Issue A Key

```sh
curl -sS "$WARRANT_URL/v1/tenants/acme-agents/api-keys" \
  -X POST \
  -H "X-Warrant-Admin-Key: $WARRANT_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "worker-2"}'
```

Response:

```json
{
  "tenant_id": "acme-agents",
  "api_key": "abcd1234.full-secret-shown-once"
}
```

### List Keys

```sh
curl -sS "$WARRANT_URL/v1/tenants/acme-agents/api-keys" \
  -H "X-Warrant-Admin-Key: $WARRANT_ADMIN_KEY"
```

The response never includes the full secret or hash.

### Revoke A Key

```sh
curl -sS "$WARRANT_URL/v1/tenants/acme-agents/api-keys/abcd1234/revoke" \
  -X POST \
  -H "X-Warrant-Admin-Key: $WARRANT_ADMIN_KEY"
```

Revoked keys can no longer call action endpoints.

### Agent Client

Agents can call the HTTP API directly or use the thin Python client:

```python
from warrant.client import WarrantClient


warrant = WarrantClient(
    "http://127.0.0.1:8910",
    api_key="<tenant-agent-key>",
)
verdict = warrant.submit_action(proposal)
```

The client only wraps HTTP calls and error handling. It does not embed Warrant into the agent runtime.

### Policies

Tenant policy is data. It defines which target systems and operations an agent may request, when approvals are required, and where held actions route.

```json
{
  "allowed_systems": ["kubernetes"],
  "allowed_operations": {
    "kubernetes": ["restart_service", "scale_deployment"]
  },
  "approval_required_at": "medium",
  "review_route": "ops-approvers"
}
```

### Fields

| Field                  | Meaning                                                                                              |
| ---------------------- | ---------------------------------------------------------------------------------------------------- |
| `allowed_systems`      | Registered actuator names this tenant may target.                                                    |
| `allowed_operations`   | Optional per-system operation allowlist. If a system is omitted, the system allowlist still applies. |
| `approval_required_at` | Minimum risk level that holds for approval: `low`, `medium`, or `high`.                              |
| `review_route`         | Operator group or route returned when approval is needed.                                            |

### Decision Rules

| Result           | When                                                                                                         |
| ---------------- | ------------------------------------------------------------------------------------------------------------ |
| `allow`          | Proposal schema is valid, target is allowed, operation is allowed, and risk is below the approval threshold. |
| `needs_approval` | Proposal is valid and allowed, but risk is at or above the approval threshold.                               |
| `deny`           | Target system or operation is outside tenant policy.                                                         |

Policy evaluation is side-effect free. Actuators only run after `allow` or after a held proposal is approved.

### Update Policy

```sh
curl -sS "$WARRANT_URL/v1/tenants/acme-agents/policy" \
  -X PUT \
  -H "X-Warrant-Admin-Key: $WARRANT_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "allowed_systems": ["kubernetes"],
    "allowed_operations": {"kubernetes": ["restart_service"]},
    "approval_required_at": "low",
    "review_route": "ops-approvers"
  }'
```

Policy updates apply to future proposals. Existing action traces remain available.

### Policy Regression Fixtures

Use `warrant-policy-check` to test policy changes before applying them:

```sh
warrant-policy-check examples/policy-regression.json
```

```mermaid
flowchart TD
  Fixture[policy-regression.json] --> Policy[Policy config]
  Fixture --> Cases[Action proposal cases]
  Policy --> Gate[PolicyGate.evaluate]
  Cases --> Gate
  Gate --> Result{Expected decision?}
  Result -->|yes| Pass[CI pass]
  Result -->|no| Fail[CI fail]
```

Fixture shape:

```json
{
  "name": "acme kubernetes policy",
  "policy": {
    "allowed_systems": ["kubernetes"],
    "allowed_operations": {
      "kubernetes": ["scale_deployment", "restart_service"]
    },
    "approval_required_at": "medium",
    "review_route": "ops-approvers"
  },
  "cases": [
    {
      "name": "medium-risk restart requires approval",
      "proposal": {
        "proposal_id": "policy-test-restart-medium",
        "actor": {"agent_id": "agent-1"},
        "summary": "Restart checkout in staging",
        "action": {
          "target_system": "kubernetes",
          "operation": "restart_service",
          "parameters": {"service": "checkout", "environment": "staging"},
          "rollback_plan": "restart the previous checkout revision"
        },
        "risk": {"level": "medium", "blast_radius": "checkout staging traffic"}
      },
      "expect": {
        "decision": "needs_approval",
        "review_route": "ops-approvers"
      }
    }
  ]
}
```

The command exits non-zero if any case differs from the expected decision, review route, or expected blocking reason.

### Decisions

| Decision         | Agent behavior                                                            |
| ---------------- | ------------------------------------------------------------------------- |
| `allow`          | The proposal passed policy. Warrant may execute the actuator immediately. |
| `needs_approval` | Stop. No side effect runs until approval.                                 |
| `deny`           | Stop. The proposal is outside policy.                                     |

```mermaid
stateDiagram-v2
  [*] --> received
  received --> executed: allow
  received --> pending_approval: needs_approval
  received --> denied: deny
  pending_approval --> approved
  approved --> executed
  executed --> [*]
  denied --> [*]
```

### Approve A Held Action

```sh
curl -sS "$WARRANT_URL/v1/actions/deploy-001/approve" \
  -X POST \
  -H "Authorization: Bearer $WARRANT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"approver": "alice", "note": "bounded staging blast radius"}'
```

Response:

```json
{
  "action_id": "deploy-001",
  "result": {
    "ok": true,
    "detail": {
      "executed": "restart_service",
      "target": "kubernetes",
      "dry_run": true
    }
  },
  "audit_root": "...",
  "trace": [
    {"kind": "proposal_received"},
    {"kind": "verdict"},
    {"kind": "approval"},
    {"kind": "execution"}
  ]
}
```

### Fetch Trace

```sh
curl -sS "$WARRANT_URL/v1/actions/deploy-001" \
  -H "X-Warrant-API-Key: $WARRANT_API_KEY"
```

The trace contains proposal, verdict, approval, execution, audit root, and event leaves for the action.

### Agent Integration Patterns

Warrant should sit at the API boundary. Agents can use any framework as long as all mutating actions go through `POST /v1/actions`.

### Python Client

```python
from warrant.client import WarrantClient


warrant = WarrantClient.from_env()
verdict = warrant.submit_action(proposal)
```

Caller rule:

```python
if verdict["decision"] == "allow":
    return verdict
if verdict["decision"] == "needs_approval":
    return {"status": "held", "review_route": verdict["review_route"]}
return {"status": "denied", "reasons": verdict["blocking_reasons"]}
```

Do not perform the side effect from the agent process after `needs_approval` or `deny`.

### LangChain Tool Boundary

Wrap mutating tools so the tool submits a proposal and only returns the Warrant verdict. The actual side effect belongs behind a registered Warrant actuator.

```python
from langchain_core.tools import tool


@tool
def restart_service(service: str, environment: str) -> dict:
    proposal = {
        "proposal_id": f"restart:{environment}:{service}",
        "actor": {"agent_id": "langchain-worker"},
        "summary": f"Restart {service} in {environment}",
        "action": {
            "target_system": "kubernetes",
            "operation": "restart_service",
            "parameters": {"service": service, "environment": environment},
            "rollback_plan": "restart the previous service revision",
        },
        "risk": {"level": "medium", "blast_radius": f"{environment} {service}"},
    }
    return warrant.submit_action(proposal)
```

### Hermes Or Custom Runner

In a custom dispatcher, classify every mutating command as an action proposal before dispatch:

```python
def dispatch_mutation(command: dict) -> dict:
    proposal = command_to_warrant_proposal(command)
    verdict = warrant.submit_action(proposal)
    if verdict["decision"] != "allow":
        return verdict
    return warrant.get_action(proposal["proposal_id"])
```

For a platform integration, the runner should not call the target system directly. It should receive Warrant's verdict and let Warrant's actuator boundary own the mutation and audit.

### Self-hosting & Operations

Warrant currently runs as a Python HTTP server. It supports a dependency-light smoke mode and a platform mode with tenant config and DRF API Key storage.

### Platform Mode

```sh
PYTHONPATH=src python3 -m warrant.server \
  --host 0.0.0.0 \
  --port 8910 \
  --config examples/platform-config.json \
  --api-key-db /var/lib/warrant/api-keys.sqlite3 \
  --tenant-db /var/lib/warrant/tenants.sqlite3 \
  --bootstrap-admin-key-name bootstrap
```

Flags:

| Flag                         | Meaning                                                        |
| ---------------------------- | -------------------------------------------------------------- |
| `--config`                   | JSON file with tenant policies and mock actuator registration. |
| `--api-key-db`               | SQLite database path for DRF API Key records.                  |
| `--tenant-db`                | SQLite database path for tenant policy records.                |
| `--bootstrap-admin-key-name` | Creates and prints one admin key at startup.                   |
| `--host`, `--port`           | HTTP bind address.                                             |

### Config Shape

```json
{
  "tenants": [
    {
      "tenant_id": "acme-dev",
      "mock_actuators": ["kubernetes"],
      "policy": {
        "allowed_systems": ["kubernetes"],
        "allowed_operations": {
          "kubernetes": ["scale_deployment"]
        },
        "approval_required_at": "medium",
        "review_route": "ops-approvers"
      }
    }
  ]
}
```

API keys are not stored in config. Use the admin API to issue and revoke keys.

With `--tenant-db`, config tenants are bootstrap seeds. Warrant inserts missing tenants into the tenant database and then loads tenants from that database. Admin API tenant creation and policy updates persist there.

### Authentication

| Surface          | Header                                                                              |
| ---------------- | ----------------------------------------------------------------------------------- |
| Agent action API | `Authorization: Bearer <WARRANT_API_KEY>` or `X-Warrant-API-Key: <WARRANT_API_KEY>` |
| Admin API        | `X-Warrant-Admin-Key: <WARRANT_ADMIN_KEY>`                                          |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cerebral-systems.gitbook.io/cerebral-systems-docs/introduction.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
