DeepSeek Harness Bluebook
User Guide

Agent Presets

Compose one agent per session with an agent preset: a single agent.cordis.yml decides that session's persona, tools, prompt sections, and skills

An agent preset is a directory holding one agent.cordis.yml. Mounting it under an agent's scope context gives that session its own tools and prompt sections while every other live session keeps its own — so one process can run several differently composed agents at once.

What a composition looks like

agent.cordis.yml is a top-level list of plugin rows, using the same Loader dialect as the host composition (including !!js). It carries what one agent contributes to the shared registries: tools, prompt sections, variables, restrictions, and the persona row. Registries and cross-session facilities stay process singletons in the host composition; a preset owns only "this one session's" composition.

A preset may publish display text in an optional preset.yml, and nothing else:

name: Minimal
description: A two-tool coding agent with only persistent bash and str_replace_editor.

id is the directory name and trust comes from the root the preset was discovered under, so neither is writable here. Display metadata is not capability: a preset with a broken name still mounts.

Where presets live

Shipped presets sit in the installed app's config directory apps/cli/config/agent-presets/, one directory each. Your own presets live under <dshHome>/.agent-presets (by default $DSH_HOME/.agent-presets or ~/.dsh/.agent-presets), discovered as a user root. Discovery is unmemoized: a preset authored while the process runs is visible immediately, and a deleted one disappears on the next read.

The shipped minimal preset fixes the system prompt to You are a helpful software engineer assistant. and composes only persistent bash and str_replace_editor; every other prompt section and model-facing plugin stays absent.

Selecting and switching

Choose a preset when creating a Web session; when none is named, the default applies. The default is a user setting, under the agent-presets namespace's default field:

agent-presets:
  default: minimal

The value is read per resolution, so a hot-reloaded setting takes effect on the next session created while every running session keeps the preset it was composed from. Clearing the field re-inherits the composition default.

Switch only on a blank session

Once a session has produced anything, its preset can no longer be switched: swapping tools mid-conversation would leave logged tool calls the new composition cannot make. Switching is available only to a blank, produced-nothing session.

Authoring: copy, never hand-write

Authoring is copy-only. A new preset is a whole-directory copy of an existing one (composition, metadata, skill directories, assets), landed under the first user root; the copy takes two ids plus an optional display name and never accepts composition text. Copying refuses three things before anything lands:

  • an id that is not a usable preset id — the id becomes a directory name and must match [a-z0-9][a-z0-9-]*; ../escape, a/b, and absolute paths are all rejected;
  • an id already taken — a copy never overwrites;
  • an unknown source — a failed copy rolls its half-made directory back.

The copied preset.yml keeps the source's description for you to edit in place but drops its name and roster order, so a copy cannot present itself identically to its source.

How a preset's rows resolve

  • A row's package name resolves from the host composition, not the preset directory — a locally authored preset lives under your home, where Node's upward node_modules walk never reaches the harness, so the mount records the host base and sends bare specifiers there;
  • a relative path still resolves from the preset's own directory, so the preset's own plugin files and skill directories travel with it;
  • an absolute filesystem path keeps its location, converted to a file: URL before ESM import.

What a mount rejects

  • an unscoped target: mounting into a context with no agent scope would register the preset's tools globally, for every agent in the process;
  • a row that never became usable: a row still waiting for a service the composition never supplies is named by the audit;
  • a row that published a process-global service: such a service is process-global, so two presets publishing the same name collide. A preset that genuinely owns a service puts it behind an isolate realm, or the service belongs in the host composition instead.

Trust boundary

Presets are compositions, so a preset is exactly as privileged as the plugins it names. A user preset carries the same trust as shell access; the trust field exists so consumers can present that difference, not to enforce it.

Next steps

On this page