zidane/ presets
Ready-made agent option sets, plus definePreset() and composePresets() to build and merge your own.
import { … } from 'zidane/presets'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.
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#
composePresetsFunction#
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 winstools,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 onnamecollisionhooks→ 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.
Parameters
| Name | Type | Description |
|---|---|---|
| ...presets | Preset[] | Presets to merge, in order. Later presets win on conflicts. |
Returns
Example
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(),
})definePresetFunction#
Identity helper for type inference when defining a preset.
Example
import { definePreset } from 'zidane/presets'
export const concise = definePreset({
system: 'Answer in as few words as possible.',
})Constants#
artifactsConstant#
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.
const artifacts: PresetbasicConstant#
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.
const basic: PresetbasicToolsConstant#
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.
Types#
PresetType#
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.
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 when you want
field-aware merging (per-event hook concat, tools shallow-merge, etc.):
createAgent({ ...composePresets(basic, telemetry, mine), provider })
type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>Re-exports#
These names are documented on the entry point that owns them.