# Give an agent a spending limit

Goal: write a sentence in English describing what an AI agent (or human user) can do with a tenant's money. Brain compiles it to a deterministic rule, signs it with the tenant's key, and enforces it on every proposed action.

### The simplest policy

```typescript
const policy = await brain.policy.create("acme", {
  text:
    "Allow invoice payments under $5,000 to approved vendors. " +
    "Require CFO approval above $5,000. " +
    "Block payments to new counterparties without review.",
});

await brain.policy.activate(policy.id);
```

That's the whole flow. From this point on, every `brain.pay` call evaluates against this policy.

### Reviewing what got compiled

The compiler returns the structured rules and a human-readable explanation. Always review before activating.

```typescript
console.log(policy.explanation);
// This policy will:
//  - Auto-approve payments under $5,000 to vendors marked as approved
//  - Escalate payments at or above $5,000 to anyone with the CFO role
//  - Reject all payments to counterparties not yet on the approved list

console.log(policy.rules);
// [
//   { if: "amount < 5000 && counterparty.known", then: "auto" },
//   { if: "amount >= 5000 && counterparty.known", then: "needs_approval", approvers: ["role:cfo"] },
//   { if: "!counterparty.known", then: "rejected", reason: "new_counterparty_review_required" }
// ]
```

If the explanation matches your intent, activate. If not, edit the text and recompile.

### Trying it before you ship it

Dry-run a hypothetical action against the active policy.

```typescript
const decision = await brain.policy.evaluate("acme", {
  type:           "pay_invoice",
  amount:         7800,
  currency:       "USD",
  counterpartyId: "cp_vendor_x",
});

console.log(decision.outcome);     // "auto" | "needs_approval" | "rejected"
console.log(decision.matchedRule); // which rule fired
console.log(decision.approvers);   // populated if needs_approval
```

`evaluate` doesn't create a payment intent. It just shows you what would happen. Useful for testing edge cases before activating.

### Approvers

Approvers are referenced by role or user.

```typescript
"Allow invoice payments under $5,000.
 Require CFO approval above $5,000.
 Require both CFO and CEO approval above $50,000."
```

| Reference               | Matches                               |
| ----------------------- | ------------------------------------- |
| `role:cfo`              | Anyone in your team with the CFO role |
| `role:cfo + role:ceo`   | Both must sign                        |
| `user:user_cfo`         | A specific user                       |
| `any:role:cfo,role:ceo` | Either CFO or CEO                     |

### Approving counterparties

Many policies key off "approved vendors." Mark counterparties as approved through the SDK or the Console.

```typescript
await brain.counterparties.update("acme", "cp_vendor_x", {
  status: "approved",
});
```

Once approved, payments to this counterparty fall under the "approved vendor" branch of the policy.

### Multiple environments

Policies are per-tenant, per-environment. Sandbox and production each have their own active policy. You'll typically:

| Environment    | Policy approach                                                   |
| -------------- | ----------------------------------------------------------------- |
| **Sandbox**    | Loose (high limits, few required approvers) for testing           |
| **Production** | Tight (low limits, multiple approvers, narrower vendor allowlist) |

### Updating a policy

Policies are versioned. New text creates a new version that supersedes the old one.

```typescript
const v2 = await brain.policy.create("acme", {
  text: "..."  // new policy text
});

await brain.policy.activate(v2.id);
```

The old version is automatically deactivated. Past actions remain bound to the version that was active when they were proposed; you can always see which version evaluated which action by reading the action's metadata.

### What policy can express

| Concept                           | Example                                        |
| --------------------------------- | ---------------------------------------------- |
| **Amount thresholds**             | "above $5,000", "between $1,000 and $10,000"   |
| **Counterparty status**           | "approved vendors", "new counterparties"       |
| **Counterparty type**             | "to employees", "to tax authorities"           |
| **Account balance preconditions** | "if the account balance is at least $50,000"   |
| **Time windows**                  | "between 9am and 5pm Pacific", "weekdays only" |
| **Approval requirements**         | "require approval from", "with sign-off by"    |
| **Outright denial**               | "block", "do not allow", "reject"              |

### What policy can't express in plain English (yet)

Edge cases that need precise semantics. For these, you can author rules directly. See Policy in the Protocol section for the rule grammar.

### What's next

<table data-view="cards"><thead><tr><th></th><th></th><th data-type="content-ref"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>💸 Pay an invoice</strong></td><td>Watch the policy you just wrote enforce itself.</td><td><a href="/pages/EvXLQlWSFcn9RYDpmBqe">/pages/EvXLQlWSFcn9RYDpmBqe</a></td><td></td></tr><tr><td><strong>📜 Audit trail</strong></td><td>Every policy decision lands in the audit log.</td><td><a href="/pages/Fypem4aaYkeJlDtrdFXd">/pages/Fypem4aaYkeJlDtrdFXd</a></td><td></td></tr></tbody></table>


---

# Agent Instructions: 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:

```
GET https://docs.brain.fi/build/give-an-agent-a-spending-limit.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
