> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heylua.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Governance

> Policy enforcement on an agent's tool calls and incoming messages, in SDK or API mode

Governance is a policy layer on an [agent](/concepts/agents) that blocks or gates [tool](/concepts/skills-and-tools) calls and scans incoming messages for prompt injection, enforced by the platform regardless of what the model decides. It exists because a [persona](/concepts/persona) is guidance, not a control: a model can be argued into calling a tool, so a tool that must never run from a conversation needs a rule the model cannot override.

## How a policy is enforced

You declare a `governance` object on `LuaAgent`. It travels with `lua push agent` and applies to every conversation the agent has, on every [channel](/concepts/channels).

```ts src/index.ts theme={null}
import { LuaAgent } from 'lua-cli';
import refunds from './skills/refunds.skill';

export default new LuaAgent({
  name: 'support',
  persona: 'You help customers of Acme with orders and refunds.',
  skills: [refunds],
  governance: {
    mode: 'sdk',
    preset: 'security',
    injection: { threshold: 0.8, ml: true, mlThreshold: 0.95 },
    rules: {
      blockTools: ['delete_customer'],
      requireToolApproval: ['issue_refund'],
    },
  },
});
```

The object has two modes.

In SDK mode (`mode: 'sdk'`) the platform evaluates the rules itself, in memory, on every request. Three parts layer in order:

* `preset: 'security'` seeds a baseline rule set that blocks tools the policy classifies as dangerous.&#x20;
* `injection` scans each incoming message before any [preprocessor](/concepts/processors) runs. `threshold` is the score, from 0 to 1, at which the pattern-based scan blocks. `ml: true` also sends the message to the Governance Cloud classifier and blocks when its confidence crosses `mlThreshold` (default 0.95); when the classifier is unavailable the pattern scan still applies.
* `rules` are your explicit lists. `blockTools` names tools that never run. `requireToolApproval` names tools that pause until a human approves; the entries are runtime tool names, matched on each tool call. `tokenBudget` builds a rule, but the runtime never supplies the token count that rule reads, so it never fires.

In API mode (`mode: 'api'`) the platform asks your governance server at `serverUrl` for each decision. The bearer token is read at runtime from the `GOVERNANCE_API_KEY` variable in the agent's environment (`lua env production -k GOVERNANCE_API_KEY -v <value>`), so it is never stored in the agent configuration. If the key or the URL is missing, the platform logs a warning and proceeds without enforcement.

Enforcement happens at three points: before your preprocessors see a message, on each tool call, and on the response before your postprocessors run. A blocked message ends the turn, and the end user receives the policy message `🛑 Blocked by governance policy — <reason>` as the reply. A tool that requires approval pauses the turn, and the end user receives `⏸️ Awaiting human approval — <reason>` followed by the approval ID. The request is tracked by the Governance Cloud service; the approver gets an Inbox item or replies `APPROVE <code>` on a channel, and the turn resumes when the decision arrives. Approval gating needs approvals enabled for the organization.

When the policy engine itself fails to load or throws, the turn proceeds. Governance fails open: it is a control on the model, not on platform availability. Two cases fail closed instead: a tool listed in `requireToolApproval` is blocked when the approval capability is unavailable, and a tool call whose pre-approval check fails is gated rather than allowed.

An organization can set a baseline. When governance is enabled on the organization, every agent created in it starts with SDK mode, the `security` preset, and injection scanning at `threshold: 0.8`, `ml: true`, `mlThreshold: 0.95`. An explicit `governance` value at creation, including `null`, overrides the baseline, and `lua sync` pulls a server-set policy into `src/governance.ts` so the next push round-trips it.

`lua governance add` scaffolds the file: it asks for the mode, lists the tools in your compiled manifest to pick what to block and what to gate (run `lua compile` first), writes `src/governance.ts`, and prints the import to add to `LuaAgent`. `lua governance remove` deletes the file and clears the policy on the server. Either way the policy reaches production with `lua push agent` followed by an agent version promote, like any other agent change.

## Governance and processors

A [preprocessor](/concepts/processors) is your code and can also block a message, so the two overlap on inputs. They differ in three ways. Governance runs first, before any preprocessor. Governance is declarative policy and can be set by the organization; a preprocessor is a versioned primitive you write and deploy. And only governance sees tool calls: a preprocessor has finished by the time the model decides to call a tool.

Governance also differs from a [workflow](/concepts/workflows) approval step. `requireToolApproval` gates one tool call inside a conversation; `.approval()` is a durable step in a run, with approver routing, timeouts, and an editable payload.

## When to use it

* A tool must never run from a conversation, whatever the end user says: list it in `blockTools`.
* A tool has consequences (refunds, deletions, payments) and a person should confirm each call: list it in `requireToolApproval`.
* You need a named control against prompt injection for a security review: set `injection`.
* Your organization runs a central policy service: use API mode with `serverUrl`.
* Don't use governance to rewrite or enrich messages; that is a preprocessor. Don't use it to hide a tool under a business condition; that is the tool's `condition`. Don't use it for approvals inside workflows; use a workflow approval step.

## Limits

| Setting                                              | Value                                             |
| ---------------------------------------------------- | ------------------------------------------------- |
| `injection.threshold`, `injection.mlThreshold`       | 0 to 1; organization baseline 0.8 and 0.95        |
| `rules.tokenBudget`                                  | Accepted; never fires                             |
| API mode without `GOVERNANCE_API_KEY` or `serverUrl` | No enforcement; a warning is logged               |
| Policy engine failure                                | Turn proceeds (fail-open), except approval gating |

## Next steps

<Columns cols={2}>
  <Card title="LuaAgent reference" href="/reference/sdk/luaagent">The `governance` field and every other agent option.</Card>
  <Card title="lua governance" href="/reference/cli/governance">Scaffold, pull, and remove a policy from the CLI.</Card>
  <Card title="About security and data" href="/concepts/security-and-data">Credentials, secrets, change control, and what is retained.</Card>
  <Card title="Approvals and signals" href="/build/workflows/approvals-and-signals">Human approval inside a durable run.</Card>
</Columns>
