# zidane/presets

> Ready-made agent option sets, plus `definePreset()` and `composePresets()` to build and merge your own.

Import: `import { … } from 'zidane/presets'`. Source: [src/presets/index.ts](https://github.com/Tahul/zidane/blob/main/src/presets/index.ts).

Use `zidane/presets` to configure an agent with one spread. `basic` sets the shell, file, edit and `spawn` tools and a general-purpose system prompt. `basicTools` is the same set without `spawn`. `artifacts` detects pull requests, branches and commits in tool results, and adds the `record_artifact` tool. `composePresets()` merges presets field by field, so hooks, tools and aliases combine and do not overwrite each other.

```ts
import { createAgent } from 'zidane'
import { basic, composePresets, definePreset } from 'zidane/presets'
import { anthropic } from 'zidane/providers/anthropic'

const concise = definePreset({ system: 'Answer briefly.' })
const agent = createAgent({ ...composePresets(basic, concise), provider: anthropic() })

const stats = await agent.run({ prompt: 'What does this repo do?' })
console.log(stats.turns)
```

## Functions

### `composePresets`

Function.

Field-aware composition of presets. Right-most preset wins for scalar fields;
objects shallow-merge; arrays and hook handler lists concatenate. Designed so
stacking presets does the obvious thing without the spread-collision footgun:

- `name`, `system`, `eager`, `skills`              → last-defined wins
- `tools`, `toolAliases`, `toolDescriptions`, `behavior` → shallow-merge (later keys override)
- `behavior.dedupTools`, `behavior.toolBudgets`    → **deep-merge** (per-tool-name; later wins on collision)
- `mcpServers`                                     → concat with last-wins on `name` collision
- `hooks`                                          → per-event concat; every handler fires

`hooks` always emerges as `event → handler[]` so downstream registration
(in `createAgent`) sees a uniform shape. Order of handlers within an event
follows preset order: earlier presets register first.

`mcpServers` is deduped by `name` because shipping two servers with the same
name would trip the connector at runtime — a later preset overriding an
earlier preset's `github` server is the practical intent.

`behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge
because they are tool-name-keyed records — a preset that ships a dedup hasher
for one tool should not erase a hasher another preset ships for a different
tool. Last-wins still applies on a per-tool collision so a downstream preset
can override an upstream preset's policy for one specific tool. Other
`behavior` fields keep last-wins semantics.

```ts
function composePresets(...presets: Preset[]): Preset
```

**Parameters**

- `...presets` (`Preset[]`): Presets to merge, in order. Later presets win on conflicts.

**Returns** `Preset`

**Example**

```ts
import { createAgent } from 'zidane'
import { basic, composePresets, definePreset } from 'zidane/presets'
import { anthropic } from 'zidane/providers/anthropic'

const concise = definePreset({ system: 'Answer briefly.' })
const agent = createAgent({
  ...composePresets(basic, concise),
  provider: anthropic(),
})
```

Source: [src/presets/compose.ts:89](https://github.com/Tahul/zidane/blob/main/src/presets/compose.ts#L89)

### `definePreset`

Function.

Identity helper for type inference when defining a preset.

```ts
function definePreset(config: Preset): Preset
```

**Parameters**

- `config` (`Preset`): Preset fields to define.

**Returns** `Preset`

**Example**

```ts
import { definePreset } from 'zidane/presets'

export const concise = definePreset({
  system: 'Answer in as few words as possible.',
})
```

Source: [src/presets/compose.ts:45](https://github.com/Tahul/zidane/blob/main/src/presets/compose.ts#L45)

## Constants

### `artifacts`

Constant.

Preset that detects pull requests, commits and branches in tool results (files are recorded by the loop, not by detection) and adds the `record_artifact` tool for outputs detection cannot see. Detection runs as `tool:transform` hooks, including those bubbled up from subagents.

```ts
const artifacts: Preset
```

Source: [src/presets/artifacts.ts:30](https://github.com/Tahul/zidane/blob/main/src/presets/artifacts.ts#L30)

### `basic`

Constant.

Default preset with the shell, file, edit and `spawn` tools and a general-purpose system prompt. The `spawn` tool is created fresh on every access, so each agent gets its own subagent state.

```ts
const basic: Preset
```

Source: [src/presets/basic.ts:27](https://github.com/Tahul/zidane/blob/main/src/presets/basic.ts#L27)

### `basicTools`

Constant.

Core tools available in every basic preset (without spawn).

`edit` and `multi_edit` ship in the basic set because surgical edits are the
default modality for production agents — `write_file` is for full overwrites.
`glob` and `grep` are exported but opt-in: not every agent needs codebase
search, and shipping them by default would force `tool:gate` work onto
consumers that prefer the model to use `shell` + classic Unix tools.

```ts
const basicTools: { edit: ToolDef; listFiles: ToolDef; multiEdit: ToolDef; readFile: ToolDef; shell: ToolDef; shellKill: ToolDef; waitTask: ToolDef; writeFile: ToolDef }
```

Source: [src/presets/basic.ts:24](https://github.com/Tahul/zidane/blob/main/src/presets/basic.ts#L24)

## Types

### `Preset`

Type.

A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`
to configure tools, a default system prompt, aliases, behavior defaults, and
agent-lifetime hooks.

`provider`, `execution`, `session`, and `mcpConnector` are excluded — they're
ambient / per-invocation runtime wiring (a custom `mcpConnector` is the MCP
connection seam, often closure-bound to a transport / auth provider), so
presets stay shareable and composable.

```ts
import { basic } from 'zidane/presets'
createAgent({ ...basic, provider })
```

### Composing multiple presets

Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`
defines, including `hooks`. Use [`composePresets`](https://zidane.si/docs/reference/presets.md#composePresets) when you want
field-aware merging (per-event hook concat, tools shallow-merge, etc.):

```ts
createAgent({ ...composePresets(basic, telemetry, mine), provider })
```

```ts
type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>
```

Source: [src/presets/compose.ts:30](https://github.com/Tahul/zidane/blob/main/src/presets/compose.ts#L30)

## Re-exports

These names are documented on the entry point that owns them.

- [zidane/agent](https://zidane.si/docs/reference/agent.md): [`AgentHookMap`](https://zidane.si/docs/reference/agent.md#AgentHookMap)
