---
title: "Console assistant"
---

# Console assistant

Turn on and govern the Neural Inverse Govern console assistant, which answers questions as the signed-in person through the model gateway and drafts changes that run only when that person confirms them.

The console assistant answers questions about your organisation inside the console and drafts a small set of changes. It is governed like any other AI use:

- **It has no identity of its own.** Every tool call runs as the signed-in person through Govern's normal API, so it can never see or do more than that person.
- **Models only through the gateway**, with the use `assistant`, so model access, residency, DLP, budgets and metering apply.
- **Cited answers.** Every answer cites the records it came from. An answer without valid citations is not shown; the assistant says it does not know instead.
- **Writes are proposals.** Nothing changes until the same person confirms the exact request.
- **Every turn is audited**, and transcripts are encrypted with a retention you set.

It is **off by default**.

## Turn it on

Open **Models > Assistant** (needs `assistant.settings:getsettings` to view and `assistant.settings:updatesettings` to change).

| Setting | Values | Default |
|---|---|---|
| Assistant | On, Off | Off |
| Models | An ordered list of up to 3 catalog models allowed for the use `assistant`; each must pass the conformance check | Empty |
| Write proposals | Allowed, Not allowed | Allowed |
| Transcript retention | 0 days up to the audit retention | 30 days |

Before saving, the page shows which model will be used and where it runs. Every change is audited with the before and after values.

### Choose a model

A model qualifies when it supports tool calling through the gateway, has a context window of at least 100,000 tokens and passes the conformance check: one tool call round trip, one cited final answer, and one refusal to follow an instruction planted in a tool result. `POST /api/v1/svc/assistant/TestModel` runs the check; it costs tokens like any request.

On a self-hosted installation, use a model your gateway serves: an `ollama` or `openai_compatible` connection in the operator's private networks, or a Bedrock connection you already have. Air-gapped installations use local models only. If no model passes, the assistant stays off and the settings page says why.

The operator can turn the assistant off for the whole installation with `NI_ASSISTANT_ENABLED=false`; every assistant route then answers `403 assistant_disabled`.

## What people can ask

People open the panel from the console top bar, or with **Cmd+.** on macOS and **Ctrl+.** elsewhere. The panel shows the page as context (identifiers only, never page content), a trace of the tools it called, and numbered citations that open the cited record.

The assistant reads through a fixed list of read tools that call mounted Govern routes as the person. It has no web access, renders no external links or images, and treats text inside records as data, never as instructions.

## Write proposals

The assistant drafts changes only from this table. Each is stored as the exact request, shown on a card that Govern writes (never the model), pre-checked as the person, and run only when the same person confirms it in the same session within five minutes, with the request hash the card showed. It runs exactly once, through the target route's own checks.

| Proposal | Route run on confirmation | Permission pre-checked |
|---|---|---|
| Create a project | `POST /api/v1/projects` | `directory.nodes:create` |
| Invite a member | `POST /api/v1/users/invitations` | `users:create` |
| Create a role | `POST /api/v1/access/roles` | `iam.roles:create` |
| Bind a role | `POST /api/v1/access/bindings` | `iam.bindings:create` on the binding's node |
| Request just-in-time access | `POST /api/v1/access/activations` | `iam.activations:request` |
| Request access | `POST /api/v1/me/access-requests` | `api:access` |

Never proposable: any delete, detach, removal or revoke; credentials, passwords and MFA; billing, payment methods and spending caps; egress destinations, model connections, webhooks and anything that sends data to an address; organisation-wide model instructions; root-only and break-glass actions; anything outside the person's own account. The assistant links to the right page instead.

A failed pre-check shows the card with Confirm disabled, and confirming is refused by the server too (`proposal_precheck_failed`). Turning proposals off stops cards already on screen (`409 proposal_withdrawn`). Audit entries written by an executed proposal carry `session_context.assistant_proposal_id`, so auditors can tell an assistant-drafted change from a typed one.

## Records

Each turn writes one audit event, `assistant:SendMessage`, with an HMAC of the prompt (not the prompt), the model, tokens, cost, every tool called and every source cited. Prompts and answers are never written to the audit log in clear.

Transcripts are envelope-encrypted per message under the organisation's key `assistant-transcripts`, kept for the retention you set (0 keeps none), and held longer under legal hold. People can read and delete their own conversations; reading someone else's needs `assistant.conversations:readanyconversation`, and each read is audited.

Model outputs are scanned with your DLP patterns before they are shown; a finding at the drop level or above is replaced with "[Removed by your DLP rules]".

## Limits

| Limit | Value |
|---|---|
| Messages per person | 30 per hour, 200 per day |
| Messages per organisation | 2,000 per day |
| Tool calls per turn | 12 |
| Model calls per turn | 8 |
| Turns per conversation | 50 |
| Proposals per turn | 3 |

On a self-hosted installation the per-day message limits are set with `NI_ASSISTANT_MESSAGES_PRINCIPAL_DAY` and `NI_ASSISTANT_MESSAGES_ACCOUNT_DAY`.

## Permissions

| Permission | Allows |
|---|---|
| `assistant.conversations:sendmessage` | Use the assistant |
| `assistant.conversations:listconversations`, `:getconversation`, `:deleteconversation` | Own conversations |
| `assistant.conversations:readanyconversation` | Read others' conversations (auditors) |
| `assistant.proposals:createproposal`, `:confirmproposal`, `:discardproposal` | Proposals |
| `assistant.settings:getsettings`, `:updatesettings` | Settings |

On a self-hosted installation, Owner and Admin hold everything; Member can send messages and manage their own conversations; Auditor can send messages and read any conversation. Proposals are held by Owner and Admin. Confirming a proposal also needs the target action's own permission.

## Not built

The Observe analyst view described in the design (quick actions on Observe pages) is not recorded as built. Read tools whose routes do not exist are not registered.
