# Tools and presets

> Understand the action surface a model sees, and narrow it when a workflow should not reach every operation.



A preset is the tool surface a model sees: the tool definitions, the system prompt describing them, and the dispatcher that runs them. The SDK ships two.

## The core preset [#the-core-preset]

`preset: 'core'` advertises two tools:

| Tool                      | Purpose                                                            |
| ------------------------- | ------------------------------------------------------------------ |
| `superdoc_inspect`        | Read-only snapshots of current document state                      |
| `superdoc_perform_action` | One named, statically validated edit verb from the action registry |

Every edit runs through the second tool with an `action` argument naming what to do. Forty actions are available, grouped by what they touch: text and structure, lists and numbering, comments, tracked-change review, formatting, tables, and history.

Two tools instead of forty keeps the advertised surface small while the action enum stays explicit. The model picks a verb by name rather than assembling an operation, and an unknown verb is rejected before anything touches the document.

## Narrow the surface [#narrow-the-surface]

Pass `excludeActions` when a workflow should not reach part of the surface:

```ts
import { createAgentToolkit } from '@superdoc-dev/sdk';

const { tools, systemPrompt, dispatch } = await createAgentToolkit({
  provider: 'anthropic',
  preset: 'core',
  excludeActions: ['accept_tracked_changes', 'reject_tracked_changes'],
});
```

An agent that proposes edits but never resolves them is a common shape: it can suggest, and a person still decides.

Exclusions apply to all three pieces at once. The action leaves the tool enum, its documentation leaves the system prompt, and `dispatch` refuses it even if the model guesses the name. An unknown action name throws immediately rather than silently doing nothing, so a typo in an exclusion list surfaces at startup instead of in production.

## Prompt caching [#prompt-caching]

Tool definitions and system prompts are stable across requests, so they cache well:

```ts
import { createAgentToolkit } from '@superdoc-dev/sdk';

const { tools, meta } = await createAgentToolkit({
  provider: 'anthropic',
  preset: 'core',
  cache: true,
});
```

`meta.cacheStrategy` reports what actually happened. Anthropic marks the tool block explicitly and reports `explicit`. OpenAI caches long prompts on its own and reports `automatic`. Vercel and generic providers pass through and report `unsupported`, because caching depends on the model underneath.

## The legacy preset [#the-legacy-preset]

`preset: 'legacy'` is the older surface: ten grouped intent tools, each taking an `action` argument, generated from the Document API contract.

It remains the default when `preset` is omitted, so code written before presets existed keeps working. Two consequences are worth knowing:

* A `createAgentToolkit()` call with no `preset` gets legacy, not core.
* The MCP server also defaults to legacy. Set `MCP_PRESET=core` to switch it.

Build new integrations on `core`. Use `legacy` when you already have one running on it, and see [Legacy tools](/agents/build/legacy-tools) for what it advertises and how to move.

## Replay a call without the model [#replay-a-call-without-the-model]

Any tool call the model makes is an ordinary SDK operation underneath. When output looks wrong, run the same operation directly:

```ts
const receipt = await dispatch(doc, 'superdoc_perform_action', {
  action: 'replace_text',
  find: 'termination',
  replaceWith: 'cancellation',
  changeMode: 'tracked',
});
```

If the direct call produces the right result, the operation is fine and the model chose or parameterized it badly. If it reproduces the problem, the operation is where to look. Separating those two cases first is the fastest way to stop debugging the wrong layer.

## Next [#next]

[Safety](/agents/operate/safety) covers the operational boundary around an agent. [Receipts and errors](/document-api/receipts-and-errors) explains the result contract a dispatched action returns. Reads and validation failures do not follow it: `superdoc_inspect` returns a snapshot with no `status`, and an invalid argument throws before any receipt exists.
