> For the complete documentation index, see [llms.txt](https://docs.brain.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.brain.fi/api-reference/governance-api.md).

# Governance API

Review registered agents, change agent lifecycle state, and build audit-derived governance reports for compliance workflows.

{% hint style="info" %}
These governance routes are staging-only and BFF-only today. They use `X-Platform-Service-Auth` with the `governance:read` scope, not an end-user bearer token.
{% endhint %}

| Operation                         | Endpoint                                 |
| --------------------------------- | ---------------------------------------- |
| List registered agents            | `GET /v1/governance/agents`              |
| Get one registered agent          | `GET /v1/governance/agents/{agent_id}`   |
| Pause, resume, or revoke an agent | `PATCH /v1/governance/agents/{agent_id}` |
| Build a governance report         | `GET /v1/governance/reports`             |
| Create a report snapshot          | `POST /v1/governance/reports/snapshot`   |
| Get a report snapshot             | `GET /v1/governance/reports/{report_id}` |

No external agent creation endpoint is exposed. Agents continue to be created through existing provisioning flows. The policy check catalog is not exposed in this cycle because it is deferred pending a future security and legal review.

### Authentication

All Governance API routes require the platform service header:

```http
X-Platform-Service-Auth: <secret-with-governance-read>
```

The platform credential must carry `governance:read`.

### List Registered Agents

```http
GET /v1/governance/agents
X-Platform-Service-Auth: <secret-with-governance-read>
```

Query parameters:

| Parameter   | Required | Notes                                                                   |
| ----------- | -------- | ----------------------------------------------------------------------- |
| `tenant_id` | Yes      | Tenant whose agent registry should be listed.                           |
| `status`    | No       | `active`, `pending`, `quarantined`, or `revoked`.                       |
| `owner`     | No       | Phase 1 tenant owner alias. A non-matching value returns an empty list. |
| `limit`     | No       | Default `100`, maximum `500`.                                           |
| `cursor`    | No       | Cursor returned by the previous page.                                   |

```json
{
  "agents": [
    {
      "id": "agent_example",
      "tenant_id": "tnt_example",
      "kind": "internal",
      "role": "finance_ops",
      "display_name": "Finance Ops Agent",
      "status": "active",
      "scopes": null,
      "scope_hash": "abcdef",
      "onchain_address": null,
      "registered_tx": null,
      "registered_at": "2026-07-22T00:00:00.000Z",
      "created_at": "2026-07-22T00:00:00.000Z"
    }
  ],
  "next_cursor": null
}
```

`scopes` is `null` in Phase 1 because the registry stores `scope_hash`, not the original scope list.

### Get One Registered Agent

```http
GET /v1/governance/agents/agent_example
X-Platform-Service-Auth: <secret-with-governance-read>
```

```json
{
  "agent": {
    "id": "agent_example",
    "tenant_id": "tnt_example",
    "kind": "internal",
    "role": "finance_ops",
    "display_name": "Finance Ops Agent",
    "status": "active",
    "scopes": null,
    "scope_hash": "abcdef",
    "onchain_address": null,
    "registered_tx": null,
    "registered_at": "2026-07-22T00:00:00.000Z",
    "created_at": "2026-07-22T00:00:00.000Z",
    "lifecycle_events": [
      {
        "audit_event_id": "evt_example",
        "actor": "user_admin",
        "action": "governance.agent.lifecycle_changed",
        "policy_decision_id": null,
        "policy_check_id": null,
        "outcome": null,
        "created_at": "2026-07-22T00:00:00.000Z",
        "inputs": { "agent_id": "agent_example", "transition": "pause" },
        "outputs": { "after_state": "quarantined" }
      }
    ]
  }
}
```

### Change Agent Lifecycle

```http
PATCH /v1/governance/agents/agent_example
X-Platform-Service-Auth: <secret-with-governance-read>
Content-Type: application/json

{
  "tenant_id": "tnt_example",
  "transition": "pause",
  "reason": "review requested",
  "actor": "user_admin"
}
```

`transition` is one of `pause`, `resume`, or `revoke`. The route writes `governance.agent.lifecycle_changed` to the existing audit event store with the actor and reason.

```json
{
  "agent": {
    "id": "agent_example",
    "tenant_id": "tnt_example",
    "kind": "internal",
    "role": "finance_ops",
    "display_name": "Finance Ops Agent",
    "status": "quarantined",
    "scopes": null,
    "scope_hash": "abcdef",
    "onchain_address": null,
    "registered_tx": null,
    "registered_at": "2026-07-22T00:00:00.000Z",
    "created_at": "2026-07-22T00:00:00.000Z"
  }
}
```

### Build A Governance Report

```http
GET /v1/governance/reports
X-Platform-Service-Auth: <secret-with-governance-read>
```

Query parameters:

| Parameter      | Required | Notes                                         |
| -------------- | -------- | --------------------------------------------- |
| `tenant_id`    | Yes      | Tenant whose audit events should be reported. |
| `period_start` | Yes      | Inclusive report start timestamp.             |
| `period_end`   | Yes      | Exclusive report end timestamp.               |
| `agent_id`     | No       | Filters policy-relevant events to one agent.  |
| `format`       | No       | `json` by default, or `csv`.                  |

Reports include policy-relevant audit events in the requested period. Historical rows are joined to `policy_decisions` when `policy_decision_id` is present. `policy_decision_id` is not populated on all historical audit events, so rows without a native outcome or resolvable policy decision are returned with `decision_data_status` set to `unavailable` rather than omitted.

```json
{
  "tenant_id": "tnt_example",
  "period_start": "2026-07-01T00:00:00.000Z",
  "period_end": "2026-08-01T00:00:00.000Z",
  "summary": {
    "totals": {
      "proposed": 2,
      "approved": 1,
      "blocked": 0,
      "escalated": 0,
      "decision_data_unavailable": 1
    },
    "coverage": {
      "events": 2,
      "with_policy_decision_id": 1,
      "joined_policy_decision": 1,
      "with_native_outcome": 0
    }
  },
  "events": [
    {
      "audit_event_id": "evt_policy_joined",
      "created_at": "2026-07-22T00:00:00.000Z",
      "actor": "agent_example",
      "agent_id": "agent_example",
      "action": "payment_intent.execute.before",
      "policy_decision_id": "dec_example",
      "policy_check_id": "rule_example",
      "raw_policy_outcome": "allow",
      "outcome": "approved",
      "decision_data_status": "available",
      "unavailable_reason": null
    },
    {
      "audit_event_id": "evt_missing_decision",
      "created_at": "2026-07-22T00:01:00.000Z",
      "actor": "agent_example",
      "agent_id": "agent_example",
      "action": "agent.action.proposed",
      "policy_decision_id": null,
      "policy_check_id": null,
      "raw_policy_outcome": null,
      "outcome": null,
      "decision_data_status": "unavailable",
      "unavailable_reason": "policy_decision_id_missing"
    }
  ]
}
```

The full request and response schema is maintained in `Brain_API_Specification.yaml`.

### Create A Report Snapshot

```http
POST /v1/governance/reports/snapshot
X-Platform-Service-Auth: <secret-with-governance-read>
Idempotency-Key: <optional-retry-key>
Content-Type: application/json

{ "created_by": "user_admin" }
```

Query parameters:

| Parameter      | Required | Notes                                            |
| -------------- | -------- | ------------------------------------------------ |
| `tenant_id`    | Yes      | Tenant whose audit events should be reported.    |
| `period_start` | Yes      | Inclusive report start timestamp.                |
| `period_end`   | Yes      | Exclusive report end timestamp.                  |
| `agent_id`     | No       | Filters policy-relevant events to one agent.     |
| `format`       | No       | `json` only for snapshots. CSV is not persisted. |

Snapshot creation generates the same JSON `GovernanceReport` as `GET /v1/governance/reports`, stores that exact payload with its filters, and returns a `grpt_` report id. The stored payload is immutable.

`Idempotency-Key` is optional. When supplied, a retry with the same key and same snapshot request returns the original `201` response with the same `report_id`. Reusing the same key with different snapshot parameters returns `409`.

```json
{
  "report_id": "grpt_example",
  "snapshot": {
    "report_id": "grpt_example",
    "tenant_id": "tnt_example",
    "period_start": "2026-07-01T00:00:00.000Z",
    "period_end": "2026-08-01T00:00:00.000Z",
    "agent_id": null,
    "created_by": "user_admin",
    "created_at": "2026-07-22T00:02:00.000Z",
    "report": {
      "tenant_id": "tnt_example",
      "period_start": "2026-07-01T00:00:00.000Z",
      "period_end": "2026-08-01T00:00:00.000Z",
      "summary": {
        "totals": {
          "proposed": 2,
          "approved": 1,
          "blocked": 0,
          "escalated": 0,
          "decision_data_unavailable": 1
        },
        "coverage": {
          "events": 2,
          "with_policy_decision_id": 1,
          "joined_policy_decision": 1,
          "with_native_outcome": 0
        }
      },
      "events": []
    }
  }
}
```

### Get A Report Snapshot

```http
GET /v1/governance/reports/grpt_example
X-Platform-Service-Auth: <secret-with-governance-read>
```

Query parameters:

| Parameter   | Required | Notes                     |
| ----------- | -------- | ------------------------- |
| `tenant_id` | Yes      | Tenant that owns the row. |

This route returns the frozen snapshot and does not re-query the live audit store.


---

# 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://docs.brain.fi/api-reference/governance-api.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.
