# Add knowledge to Last9 AI

> Create knowledge topics, upload app runbooks, opt topics into incident triage, and bind remote MCP tools with auto or approve policies.

Source: https://last9.io/docs/ai/knowledge/

Give Last9 AI your app context: runbooks, service notes, and investigation procedures. Knowledge topics can also bind tools from [remote MCP servers](/docs/ai/remote-mcp-servers/) so incident workflows call the right tools with the approval policy you choose.

## Prerequisites

- Last9 AI enabled for your organization. See [Enable Last9 AI](/docs/ai/#enable-last9-ai).
- An **Admin** user (writes need an administrator).
- An API refresh token with **write** scope to create or update, and **delete** scope to remove topics or documents. See [Getting started with API](/docs/getting-started-with-api/).
- Your organization slug (from the dashboard URL: `app.last9.io/v2/organizations/<org_slug>/...`).
- Optional: a remote MCP server already registered if you will bind tools. See [Remote MCP servers](/docs/ai/remote-mcp-servers/).

:::note[Base path]
All examples use:

`https://app.last9.io/api/v4/organizations/<org_slug>/ai`

Replace `<org_slug>` and send `X-LAST9-API-TOKEN: Bearer <access_token>` on every request. Mint the access token from your refresh token with `POST /api/v4/oauth/access_token` as described in [Getting started with API](/docs/getting-started-with-api/#tokens).
:::

## What a knowledge topic contains

| Field                       | Purpose                                                                                 |
| --------------------------- | --------------------------------------------------------------------------------------- |
| `id`, `name`, `description` | Stable id and labels for the topic.                                                     |
| `overview`                  | Short procedure the model should follow (when to call which tools, order of checks).    |
| `use`                       | Closed purpose list. Currently the only value is `incident_triage`.                     |
| `mcp`                       | Optional bindings to tools on a registered remote MCP server, with `auto` or `approve`. |
| Documents                   | Longer runbooks and notes attached to the topic.                                        |

`use: ["incident_triage"]` makes the topic eligible on investigation / incident turns. Omit `use` or set `[]` when creating through the API to keep the topic out of investigations. The topic stays readable through the management APIs and can still appear in regular AI Assistant chats.

## Create a topic and upload runbooks

Worked example: topic `payments-incident-playbook` bound to a remote MCP server named `payments`. Register that server first if you need tool bindings.

1. **Mint an access token**

   ```bash
   curl -sS -X POST 'https://app.last9.io/api/v4/oauth/access_token' \
     -H 'Content-Type: application/json' \
     -d '{"refresh_token":"<refresh_token>"}'

   export LAST9_TOKEN='<access_token>'
   export LAST9_ORG='<org_slug>'
   export LAST9_AI="https://app.last9.io/api/v4/organizations/${LAST9_ORG}/ai"
   ```

2. **Create an incident knowledge topic**

   ```bash
   curl -sS -X POST "${LAST9_AI}/knowledge/topics" \
     -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}" \
     -H 'Content-Type: application/json' \
     -d '{
       "id": "payments-incident-playbook",
       "name": "Payments incident playbook",
       "description": "How to triage payments and ledger incidents",
       "overview": "For SEV1/2 payments incidents: call get_incident on the payments MCP, then Last9 traces and logs for the same service and window, then add_comment. Prefer payments-incident-playbook__* tools over raw mcp__payments__* names.",
       "use": ["incident_triage"],
       "mcp": [
         {"server": "payments", "tools": ["get_incident", "add_comment"], "approval": "auto"},
         {"server": "payments", "tools": ["close_incident"], "approval": "approve"}
       ]
     }'
   ```

   | Field                      | Meaning                                                                          |
   | -------------------------- | -------------------------------------------------------------------------------- |
   | `use: ["incident_triage"]` | Topic is eligible on investigation / incident turns.                             |
   | `mcp[].server`             | Must already exist in `GET /mcp-servers`.                                        |
   | `mcp[].tools`              | Allowlist of tool names, or `["*"]` for every tool on that server.               |
   | `mcp[].approval`           | `auto` runs without a UI click; `approve` (default) requires human confirmation. |
   | `overview`                 | Short procedure. Put the _when_ and _order of tools_ here.                       |

   `use` is a closed list. Unknown values return `400`. You can create a topic without `mcp` and add bindings later with PATCH. Expected create response: `201` with `activation.status: "pending"`.

   Topic and document `id` values must be lowercase kebab-case (`[a-z0-9]+(?:-[a-z0-9]+)*`). Underscores are rejected.

3. **Upload app knowledge documents**

   JSON body:

   ```bash
   curl -sS -X POST "${LAST9_AI}/knowledge/topics/payments-incident-playbook/documents" \
     -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}" \
     -H 'Content-Type: application/json' \
     -d '{
       "id": "sev1-runbook",
       "title": "SEV1 payments runbook",
       "content": "## SEV1\n1. Confirm affected merchant and region.\n2. Call get_incident.\n3. Correlate with Last9 error rate and traces.\n4. add_comment with findings.\n5. close_incident only after human approval."
     }'
   ```

   Or upload a file (`text/plain`, `text/markdown`, or `.docx`). PDF returns `415`. Extracted text is stored; uploads do not install executable tools.

   ```bash
   curl -sS -X POST "${LAST9_AI}/knowledge/topics/payments-incident-playbook/documents" \
     -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}" \
     -F 'id=sev1-runbook' \
     -F 'title=SEV1 payments runbook' \
     -F 'file=@./sev1-runbook.md;type=text/markdown'
   ```

4. **Activate with a chat turn**

   After create or PATCH, `activation.status` is `pending`. Open [AI Assistant](https://app.last9.io/ai-assistant) (or start an investigation) and send a turn. Then check:

   ```bash
   curl -sS "${LAST9_AI}/config/status" \
     -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}"
   ```

   Expect `active`.

5. **Verify in an investigation**

   Ask about a payments incident and instruct the assistant to follow the playbook. Bound tools appear as `{topic_id}__{tool}` — for example `payments-incident-playbook__get_incident` — with the approval you configured.

   Raw names `mcp__payments__get_incident` remain available for API-managed servers but still default to **approve**, even when the topic binding says `auto`. Prefer the topic-prefixed tools in the overview so auto-approved paths are used.

## List and read

```bash
curl -sS "${LAST9_AI}/knowledge" \
  -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}"

curl -sS "${LAST9_AI}/knowledge/topics" \
  -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}"

curl -sS -D - "${LAST9_AI}/knowledge/topics/payments-incident-playbook" \
  -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}" -o /tmp/topic.json
```

Keep the quoted `ETag` from the topic GET for PATCH or DELETE.

## Update or remove

```bash
curl -sS -X PATCH "${LAST9_AI}/knowledge/topics/payments-incident-playbook" \
  -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}" \
  -H 'Content-Type: application/json' \
  -H 'If-Match: "<etag_from_get>"' \
  -d '{"overview":"Updated procedure…"}'
```

Clear MCP bindings or opt out of triage:

```bash
curl -sS -X PATCH "${LAST9_AI}/knowledge/topics/payments-incident-playbook" \
  -H "X-LAST9-API-TOKEN: Bearer ${LAST9_TOKEN}" \
  -H 'Content-Type: application/json' \
  -H 'If-Match: "<etag>"' \
  -d '{"mcp": [], "use": []}'
```

Missing `If-Match` returns `428`; a stale value returns `412`. Delete topics or documents with DELETE and the same precondition header (needs **delete** scope).

## How tools and approval behave

| Call shape                                        | Typical approval                    |
| ------------------------------------------------- | ----------------------------------- |
| `{topic_id}__{tool}` from a topic `mcp` binding   | As configured (`auto` or `approve`) |
| `mcp__{server}__{tool}` for an API-managed server | `approve` (human must confirm)      |
| Deployment-managed Last9 tools (`mcp__last9__…`)  | Per Last9 product policy            |

Investigation turns only load knowledge topics whose `use` includes `incident_triage`. Topics created through the API default to `use: []` and stay out of investigations until you opt them in.

## Checklist

1. Admin has AI enabled and an API refresh token with write and delete scopes.
2. Remote MCP (if needed) is registered and healthy. See [Remote MCP servers](/docs/ai/remote-mcp-servers/).
3. Topic exists with `use: ["incident_triage"]`, a concrete `overview`, and `mcp` bindings for the tools the runbook needs.
4. At least one document holds the detailed runbook (markdown preferred).
5. After one AI Assistant turn, `GET /config/status` is `active`.
6. A test investigation calls a topic-prefixed tool; `auto` tools run without a click, `approve` tools wait for confirmation.

## Related

- [Remote MCP servers](/docs/ai/remote-mcp-servers/) — register and test remote MCP endpoints
- [AI Assistant](/docs/ai/ai-assistant/) — run a verification chat after activation
- [Investigate an incident with AI](/docs/ai/investigate-an-incident/) — investigation method
- [Getting started with API](/docs/getting-started-with-api/) — refresh and access tokens

---

## Troubleshooting

| Symptom                      | What to check                                                                                                                                      |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `403` on DELETE              | Token has write but not delete scope. Create a refresh token that includes delete, or ask an Admin.                                                |
| `400` on topic create        | Unknown `use` value, invalid kebab-case `id`, or `mcp` references a server that does not exist yet. Correct the field and send the request again.  |
| `412` / `428` on PATCH       | Send a fresh `If-Match` from the latest GET.                                                                                                       |
| Model never uses the topic   | Missing `incident_triage`, empty overview, or you only registered MCP without a topic. Add `incident_triage` and an overview that names the tools. |
| Auto approval does not apply | You called `mcp__{server}__{tool}` instead of `{topic_id}__{tool}`. Prefer topic-prefixed names in the overview.                                   |
| PDF upload fails             | Use markdown, plain text, or `.docx` instead.                                                                                                      |

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
