---
title: "Propose playbooks with the advisor"
description: "Let a model read signals and propose one of your declared playbooks, with a person approving every proposal."
section: "guides"
status: "Building for 0.6"
spec: "advisor"
canonical: "https://mainsdk.dev/docs/guides/propose-playbooks-with-the-advisor"
updated: "2026-10-28"
---

# Propose playbooks with the advisor

> Let a model read signals and propose one of your declared playbooks, with a person approving every proposal.

Status: Building for 0.6 · Canonical: https://mainsdk.dev/docs/guides/propose-playbooks-with-the-advisor · Updated: 2026-10-28

You will turn on the advisor so that, when signals suggest trouble, a model proposes one of the playbooks you already declared and a person approves it. It takes about 10 minutes.

## You need

- At least one playbook rule declared, or a preset turned on, such as `attack.contain`.
- The `ai` interface configured with a model (or `driver: local` in tests).

## 1. Declare it

```yaml title="main.yaml"
agents:
  advisor: { budget: { spend: $2/day, calls: 50/day } }
advisor:
  on: [attack.suspected, anomaly.detected]
  may: [attack.contain, pressure.slim]
  run: approve
```

`mainsdk check` fails with `MAIN-ADVISOR-0001` when `may` is empty, names a rule that is not declared, or when `run: auto` would apply a rule whose steps are not notice or instance class.

## 2. Read a proposal

A wake at medium severity or above makes the advisor ask the model. You can also ask now:

```ts title="ops/ask.ts"
import { advisor } from "mainsdk/experimental/advisor";

const p = await advisor.propose();
console.log(p.choice, p.reason, p.evidence);   // choice is one of may, or none
```

A proposal with a choice starts a playbook run with source `advisor`, held for a person to approve. The advisor never approves anything itself.

## Test it offline

```ts title="test/advisor.test.ts"
import { createTestApp } from "@mainsdk/testing";

const app = await createTestApp({
  ai: { replies: [JSON.stringify({ choice: "attack.contain", reason: "Many failed sign-ins", evidence: ["s1"], confidence: 0.8 })] },
});
```

## Check it worked

A model answer that names a playbook outside `may` is refused and logged as `MAIN-ADVISOR-0002`, and no run starts. When the budget or the hourly limit is reached the advisor stops with `MAIN-ADVISOR-0003` and your playbooks carry on without it. Secrets and personal data never reach the model: a field that matches a detector is dropped and logged as `MAIN-ADVISOR-0004`.

## Next

- [Playbook advisor](https://mainsdk.dev/docs/interfaces/advisor)
- [Give an agent a budget](https://mainsdk.dev/docs/guides/govern-an-app-agent)
