The dsh system prompt, explained

What DeepSeek Harness assembles into the system prompt before every model step — the fixed identity, the persona slots, the tool guidance, and the plugins that rewrite them.

Last updated: 2026-10-04

Every turn starts with a system prompt the model reads before anything you typed. In DeepSeek Harness (dsh) that text is not a hand-edited file — it is assembled at request time by the official system-prompt package (packages/core/system-prompt), which merges a fixed identity line, your deployment persona, first-party tool guidance, and every prompt section registered by plugins into one ordered message.

This page explains what goes into that assembly, who can change it, and how the popular prompt plugins — persona editors, prompt armor, thinking-language injectors — hook in. For what happens after the prompt is sent, read the agent loop guide; this page stays on the text itself.

TL;DR

  • ▸The prompt is assembled per step, not stored: the system-prompt package sorts registered sections by order and renders the result with renderPrompt.
  • ▸The fixed part is one line — “You are an AI agent powered by DeepSeek Harness.” — controlled by the includeHarnessIdentity config (default true).
  • ▸You can add text without code: the personaPrefix and personaSuffix config fields, or a Settings-page persona plugin.
  • ▸Plugins inject through ctx.systemPrompt.section(...); a section marked complete replaces the entire prompt for its scope.

Where the dsh system prompt comes from

The official subsystem doc states the contract precisely: the system-prompt package owns the data exchanged between prompt contributors and one assembly call. Contributors register PromptSection entries — each with a unique name, a numeric order, and text that is static or resolved per assembly. Sections concatenate in ascending order (ties break by name), and the merged result is what the model receives as the system message.

Three terms carry the whole design:

PromptSection

One contributed block: name, order, text (static or a per-assembly provider), optional undefined} interpolation. Duplicate names throw at registration.

Assembly

One assemble() call merges the global layer with the requesting scope's layer, resolves tool schemas and variables, and runs the system-prompt/assemble waterfall.

Surface node 0

The rendered text is committed as a system-role message of derived history — surface node 0 on the first step, replaced in place when the text changes. It is not a request field.

What the model receives, in order

With first-party defaults on, the rendered prompt follows a fixed order — every slot below is real, from the −1000 identity line to the 10200 persona suffix, exactly as the package README documents the render order:

  1. 1

    The fixed identity line

    order −1000 · includeHarnessIdentity

    “You are an AI agent powered by DeepSeek Harness.” — the one hardcoded sentence, first in the prompt. includeHarnessIdentity: false omits it, recommended only for deployments that own the complete prompt.

  2. 2

    Deployment persona prefix

    order 0 · deployment:persona-prefix

    Your personaPrefix config — or a persona plugin's contribution. The README notes this slot carries the model-name introduction. Empty by default.

  3. 3

    First-party reusable instructions

    first-party guidance

    The generated tools SDK and structured-output guidance: how the model is told to call what is mounted. Registered tool schemas ride along in the same assembly.

  4. 4

    Harness source line

    order 10000 · harness source

    The environment-bearing suffix opens with the harness source entry at order 10000.

  5. 5

    Web surface

    order 10100 · Web surface

    The local Web URLs the deployment exposes, rendered next in the suffix at order 10100.

  6. 6

    Deployment persona suffix

    order 10200 · deployment:persona-suffix

    Your personaSuffix config — the last word of the prompt at order 10200, after all first-party text.

  7. ↻

    Dynamic runtime context

    separate channel
    PromptContext → user-role snapshot

    Ordered PromptContext entries do not join the system text: they become sourced user-role snapshots in model history — a separate, cache-safer channel. includeRuntimeContext: false or a scoped suppressor removes them.

Anything else a deployment registers lands at whatever order it declares — external contributions may use any finite order. One escape hatch exists: a section with complete: true becomes the sole prompt section. Assembly still resolves tools and variables, then restores that exact text as the whole prompt — and two effective complete sections make assembly fail loudly rather than send a malformed prompt.

Who changes it: the three plugin categories

Almost nobody edits YAML to touch the prompt — the community does it through plugins. Our directory tracks 40+ plugins in this cluster, and they fall into three working categories (stars verified 2026-10-04):

Persona editors

xilin3/dsh-prompt-persona (★14) edits the deployment persona from the Settings page with a live preview — the no-code way to fill the two persona slots. The same slots are reachable through plain personaPrefix / personaSuffix config.

Prompt armor

minglink/dsh-infinite-gen-4 (★2,294, the cluster's top star) is the best-known armor-style entry: it hardens the deployed prompt against probing and extraction instead of adding text — protection, not injection.

Injection & prompt context

len7183/dsh-think-zh (★32) and max-null/dsh-chinese-thinking (★10) inject thinking-language directives (next section); asktheway/dsh-auto-memory (★81) contributes long-term memory as dynamic runtime context rather than prompt text.

how to develop a dsh plugin.

The Chinese thinking axis

One demand shaped this cluster early: the model's chain of thought defaults to English even when the conversation is in Chinese. Official discussion #8798 collects the request, and two community plugins answer it from the prompt layer — no fork, no model switch.

len7183/dsh-think-zh (★32) adds a thinking-language switch in Settings — Simplified Chinese or default English — and replies follow the question's language while code and identifiers stay untouched. max-null/dsh-chinese-thinking (★10) is the lighter-weight alternative. Both work by injecting a directive into the assembled prompt, which is exactly what the persona slots and plugin sections exist for.

What it costs — and how the prompt reaches the model

The README is candid about the bill: identity is a fixed per-request cost when enabled, and persona prefixes, suffixes and plugin text repeat on every request, scaling with their rendered length. The offsetting mechanism is caching, not deletion:

  • ▸While a rendering is unchanged, the prompt stays prefix-stable: the system nodes in history are left untouched and KV-cache reuse holds from turn to turn.
  • ▸Any change — a persona edit, a new tool, a different order — invalidates reuse from the first changed token.
  • ▸In a continuing series with systemPromptUpdate: 'in-history', a changed prompt is appended after the cached history, so the prefix through that history stays reusable.
  • ▸Context compaction cannot shrink any of this — compaction works on retained history, not on the per-step assembly. The lever is trimming what you register, not compacting harder.

how the dsh agent loop runs one turn. how context compaction works.

FAQ

The most common questions about the dsh system prompt.

Can I change the dsh system prompt?

Yes — three ways, in rising order of power. Config: set personaPrefix and personaSuffix (and includeHarnessIdentity: false to drop the opener) on the system-prompt plugin entry. Settings: a persona editor like dsh-prompt-persona edits the same slots visually, no YAML. Code: register a section with ctx.systemPrompt.section(undefined) — and a section marked complete: true replaces the entire prompt for its scope, though two effective complete sections fail assembly.

Does a longer system prompt slow sessions down?

It costs tokens, and caching absorbs most of that. The identity line plus persona plus plugin text repeats per request, but while the rendering is unchanged the system nodes in history stay untouched, so provider-side KV-cache reuse holds between turns. You only pay full price from the first changed token — which is why persona text that churns every turn is the expensive pattern, and stable text is nearly free after the first request.

How do plugins inject into the prompt?

Through the registry. A plugin calls ctx.systemPrompt.section(undefined), and the section is concatenated in ascending order at every assembly. Registrations made through an agent's own ctx are scoped: they shadow same-named globals for that agent only. After merging, the system-prompt/assemble waterfall can rewrite the result — unless a complete section is in play, which listeners cannot add to or replace.

Do different profiles see different system prompts?

They can. Assembly merges a global layer with the requesting scope's layer, and scoped sections, variables and tool providers shadow the global ones per agent — so a work profile and a personal profile that register different persona sections get different prompts from the same install. The fixed identity line and first-party guidance stay the same unless a profile disables them or ships its own complete section.

Is this the model's built-in system prompt?

No — different layers. The model vendor's behavior tuning lives in the weights and is invisible to dsh. The dsh system prompt is runtime text the harness assembles and sends as a system-role message; its only fixed part is the one-line harness identity. That separation is why the same model can behave differently under dsh than under another harness, and why prompt-level plugins work across every model you mount.

Where can I see the actual assembled prompt?

The two official sources below are the authoritative contract: the subsystem doc lists the exact types, and the package README documents the render order and every config field. At runtime, your session's trajectory records what the model received in a given turn — pair it with the loop's logged system-node replacements to see exactly when a prompt changed mid-session.

Related guides

Where the system prompt sits in the bigger picture.

Sources & evidence

Every mechanism on this page traces to the sources below; commit shas and star counts verified 2026-10-04.

DSH Plugins is an independent community directory of DeepSeek Harness plugins. Not affiliated with or endorsed by DeepSeek. Third-party plugins are not security-audited — review the source before installing.

New DeepSeek Harness plugins, weekly. No spam.