Visually configure an agent's prompt, tools, visible skills, subagents and fallback models, and assemble several of them into a team. It never writes or edits any host preset file.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-agent-studio
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:thissensen/dsh-agent-studio
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
简体中文 · English · Documentation
A visual configuration plugin for DeepSeek Harness: configure an agent's prompt, tools, visible skills and subagents precisely, from a UI — assembling a team of them is just as easy.
Every turn, the model sees three things: the system prompt, the tool catalog, and the skill catalog. The more plugins, tools and MCP servers you install, the bigger those three get, and the worse the model performs. On top of that, DSH's subagent configuration is bare-bones: there is no easy way to give a subagent its own prompt, tools, skills, model or reasoning effort.
This plugin fixes both. It turns an agent into bricks you can assemble freely: prompt, tools, skills, model. Subagents get the same treatment, presets can be created on the spot, and official PTC mode is supported.
It never writes, deletes or edits any of the host's preset files, and uninstalling restores everything.
It pairs well with dsh-context, which shows you what prompt, tools and skills a turn actually carried.
What it solves
| The problem you hit | Platform default | With this plugin |
|---|---|---|
| The system prompt grows and grows, and you can neither turn it off nor use it | Whatever sections the preset registers gets delivered | Write a whitelist per agent; anything not on it stays out |
| Too many tools, and the model can't pick well | The full tool surface of everything installed | Pick the ones this agent needs, put the rest away |
| Many skills, no good way to manage them | Every modelInvocable skill enters the catalog |
Check the ones you want; the model can't see the rest |
| A runtime snapshot is pushed into every step | Injected by the platform, with no switch | A per-agent switch — turn it off and stop paying for it |
| Subagents can only inherit the parent wholesale, eating a lot of context | The official subagent has no entry identity and no per-role trimming |
Configure each subagent on its own: model / prompt / tools / skills / background mode |
| Subagents created under PTC are PTC too | The platform inherits the parent's mode | You decide whether a subagent runs native or PTC |
| Different jobs want different prompts, tools and skills, and switching is a chore | A preset only swaps the prompt; tools and skills stay one global set | Switch the agent bound to that preset, and you're done |
| A local model is short on context and barely lasts a few turns | You cannot clear the prompt out entirely; you have to hand-build a preset | Create an agent with nothing loaded and bind it to the preset — a truly empty prompt |
| The primary model gets rate-limited or goes down, and the whole turn fails | Retries within one provider up to a limit, then gives up | Configure a chain of fallback models (possibly across providers); failures move down the chain (optional) |
Install
Three routes — take the one that fits your setup: npm when you are online, the GitHub Release package for offline or air-gapped setups, and source if you want to change the code.
From npm
dsh plugin --profile web add dsh-agent-studio
From a GitHub Release
Download dsh-agent-studio-<version>.tgz from Releases. It is the very artifact npm serves, with the lib/ and client/ build output already inside — no build step:
dsh plugin --profile web add "./dsh-agent-studio-0.1.2.tgz"
The file can live in any directory as long as the path is right (./ or an absolute path); swap in whatever version you actually downloaded. Use this route for offline or air-gapped setups.
From source
git clone https://github.com/thissensen/dsh-agent-studio.git dsh-agent-studio
cd dsh-agent-studio
pnpm install # devDependencies only; the peers are host packages, not from the registry
node scripts/link-deps.mjs web # link the host's @deepseek-ai/* into this project's node_modules
dsh plugin --profile web add "link:<absolute path to this directory>"
You can also unpack the source archive (Source code (zip)) from the Release page instead of cloning — the steps after that are identical.
All three routes end the same way: restart DSH once and look for the panel under Settings → Agent Studio.
- With a
link:install, edits tolib/take effect immediately; edits to the panel (client/parts/panel.js) just need a page refresh. - Changing entry fields in
package.json(main/exports/dsh.*) does require a restart. --profiletakesweb(the pure web build) ordesktop. The desktop app is the web build plus an Electron shell, so the host half needs no changes at all.
Uninstall
dsh plugin --profile web remove dsh-agent-studio
Nothing is left behind in the host configuration. The presets were never touched, and everything else lives in the plugin's own data.
Panel preview
Every screen ships in a light and a dark variant:
| Area | What it does |
|---|---|
| Agent pool (left) | One row per agent: bound preset, loaded sets, Agent mode, subagent roster |
| Set libraries (left) | The three set pools: create, copy, rename, delete |
| Details (right) | Pick a set → edit its members; pick an agent → load sets, set the model and background mode, attach subagents, toggle the snapshot switch |
| Top bar | Preset tabs plus new / delete preset, main-agent binding, full import / export (the export is the draft, including unsaved changes) |
| Bottom bar | Save changes; per-pool import / export |
Import always opens a confirmation dialog first (whole-config and per-pool imports share one); its "Overwrite same ids" switch decides whether a colliding id is overwritten or fails the whole import. Import only merges into the draft — nothing is written until you save.
Before an id is renamed, the panel lists everyone referencing it, and the rename updates every reference — no dangling references are left behind.
Four pools, independent of each other
Four kinds of configuration objects, each minding its own business, referencing each other many-to-many. A set you build once can be loaded into any number of agents.
| Pool | What it is for |
|---|---|
| Agents | Which preset it binds to; Agent mode (follow preset / native / force PTC), prompt, tools, skills, subagent roster — plus the model and reasoning effort to use when it acts as a subagent |
Prompt sets promptSets |
An ordered list of prompts; you set the order |
Tool sets toolSets |
Tool names — both plugin tools and MCP tools |
Skill sets skillSets |
A skill list deciding which ones the model may invoke on its own |
- Loading attaches a set to an agent. Two sets loaded by the same agent must not overlap — the panel and the write endpoint each block that.
- Binding attaches a preset to an agent, and that preset is then managed by it.
Semantics
A binding takes over. The same rule on all three surfaces: loading nothing means nothing.
| Concept | Rule |
|---|---|
| Preset binding | The bound preset's prompt, tools, skills and subagents all go to this agent; unbind and everything is back to normal |
| Prompt sets | Loading none at all = an empty prompt is delivered |
| Tool sets | Loading none at all = no tools at all |
| Skill sets | Loading none at all = no skills exposed; load one and only the checked ones are |
Automatic model fallback (optional)
Configure a chain of fallback models for an agent, and a failure of the primary is followed down the chain. No fallbacks configured = no takeover at all — retries then behave exactly as the platform default.
- Retries: an upper bound per candidate, default 5 (aligned with the platform default). Retryable errors (empty response / rate limit / server error / timeout / transport) are retried on the current candidate up to that bound before moving on; quota exhaustion, bad credentials and the like move on immediately.
- How the chain is ordered: subagents = the route given at start (inherited when the agent has no model) to fallbacks; main agents = the model chosen in the chat window to the main-model config to fallbacks. Your choice is never overridden; when everything is fine the plugin does not touch it.
- What failure looks like: the whole chain exhausted = that request fails for good (same as the platform). After a switch the session does not switch back on its own; change the model in the chat window and the plugin steps aside.
- Visible: retries and switches are written into the session (the panel's "retrying model request (N/M)" line comes from it), and a switch also leaves the model a notice that earlier turns were produced by the previous model.
Quick start
- Open the panel: Settings → Agent Studio. The agent pool and the three set libraries (prompt / tool / skill) are on the left, details on the right.
- Create a prompt set and add sections. There are two kinds:
- Platform preset: references a section the platform registers itself; its body follows platform upgrades and is read-only here;
- Custom: your own body, supporting the platform's registered
{{variable}}interpolation. Writing a variable the platform has not registered fails that request outright.
- Create a tool set and check the tools you want to keep.
skillis required — without it the model cannot invoke skills on its own. - Create a skill set and check the skills to expose. Candidates are grouped by source, collapsible, and whole groups can be checked at once — opening the panel queries the official skill service right away, no message needed first.
- Create an agent: name it and write its note (when it acts as a subagent, the model picks by that note), load the sets above, pick its Agent mode (follow preset / native / force PTC) and background mode (resumable / one-shot / AI decides). The subagent roster lives here too. Configure a chain of fallback models too if you want (see the section above; optional).
- Bind that agent to a platform preset.
- Save. Nothing is written until you press save — don't forget it.
Once saved, open a new conversation with that preset and it is in effect.
Configuration and data
Configuration lives in the plugin's own settings namespace agent-studio (in the user's settings.yaml). The model is four keys plus one binding:
agent-studio:
agents: # agent pool
- id: reviewer
name: Code review
note: Read-only review and advice # when used as a subagent, the model picks by this
model: { provider: deepseek, model: deepseek-v4.1-flash, reasoningEffort: medium }
maxRetries: 5 # per-candidate retry bound for automatic fallback (default 5)
fallbacks: # the fallback chain (possibly across providers); empty = no takeover
- { provider: senseaudio, model: glm-5.3-flash }
background: foreground # always-background | foreground | model-decides
toolPresentation: follow # follow | native | ptc
promptSets: [review-sections] # ordered: the order here is the delivery order of sections
toolSets: [read-only]
skillSets: [review-skills]
children: [tester] # the subagents it may delegate to
promptSets: # prompt sets: ordered sections; with text = custom, without = references a platform preset
toolSets: # tool sets: tool names
skillSets: # skill sets: skill names
runtimeContextOff: [reviewer] # these agents stop receiving the official runtime snapshot
bindings:
presets: [{ presetId: standard, agentId: reviewer }] # preset → main agent
All of these lists are arrays, not dictionaries. The settings service merges objects recursively but replaces arrays wholesale, so with dictionaries the panel could never delete a member. The price is that id uniqueness is on us: the panel and the write endpoint both enforce it.
Compatibility
- Target environment: the pure web build of DSH (
dsh --profile web); community desktop builds work too. - Host services it depends on (
peerDependencies, all optional):dsh-agent-presets/dsh-scope/dsh-settings/dsh-system-prompt/dsh-tools/schemastery. When a DSH upgrade leaves one of them missing, the plugin degrades item by item instead of throwing. - Interface language and theme follow the platform; Chinese and English copy ship with it, and both dark and light themes are supported.
- The client half has no build step:
client/index.jsis the shell (loaded at startup) andclient/parts/panel.jsis the panel (served on demand by a host route).
Known limits
- Sections cannot be rewritten under minimal-style presets. Their persona section carries
complete: true, meaning "this is the whole prompt, stop splicing". After the assembly waterfall returns, the platform forces the section list back to that one section, so whatever whitelist the plugin computed inside the waterfall is overwritten — that single section is always what ships. That is platform design, not a plugin defect, and since only one section was ever in play the practical loss is small. The tool and skill surfaces have no such post-processing, andstandard/code/cordisand other regular presets behave normally. - Delegation uses the plugin's own tools:
studio_list_subagentscomputes the roster live,studio_delegatedispatches by agent id — only through it do a subagent's own settings (prompt / tools / skills / model) resolve to its identity and take effect. The officialsubagenttool gets no special treatment (it is there if your tool sets keep it), but the subagents it starts are never registered, so they only ever run with the surface of the main agent bound to that preset. - When several one-shot subagents are dispatched at once, identity is paired in order. The platform's
agent/createdevent does not say which dispatch triggered the creation, so the plugin can only assume queue order: first created pairs with first called. That held in testing, but the platform never promised it. Resumable subagents are unaffected — they get a pre-generatedchildIdbefore starting, so the pairing is exact. - Tool candidates have a cold start. With no session around, those tool registrations do not exist in the host process and cannot be queried from anywhere. So observations are cached per preset, and the panel falls back to that cache.
Layout
lib/ host-half output (the package's real entry; tsc from src/host/)
index.js entry: observation layer + routes + apply layer + delegation tools
config.js the four-pool schema + load-overlap check (single source of truth for the data model)
preset.js the one way to ask "which preset is this agent on"
observe.js read-only observation layer at assembly time
cache.js on-disk cache of observations (the panel's cold-start candidates)
apply.js the apply layer (main-agent assembly + subagent creation window)
delegate.js delegation tools + claim map and pending queue
fallback.js automatic model fallback (candidate chain / per-candidate retries / switch notice)
presets.js preset management (list / copy / delete, via official services)
models.js model catalog (provider / model / reasoning effort)
attribution.js tool source attribution (who registered it, best-effort)
sdk-strip.js PTC tools:sdk declaration trimming
api.js host-side route dispatch
http-guard.js HTTP request fence and response helpers
types.js shared types (types only, no runtime code)
client/ client-half output
index.js shell: module registration + runtime panel loading + failure fallback card
parts/panel.js the panel (served by the host at runtime; refresh the page after editing it)
src/host/ src/client/ source of truth (tsc → lib/, vite → client/)
types/ host type declarations
assets/ screenshots used by the READMEs
scripts/ dependency linking for source installs and consistency checks used by CI
Documentation
Online documentation: https://thissensen.github.io/dsh-agent-studio/ (the source lives in docs/, a VitePress site).
For the platform itself, the authoritative references remain the DeepSeek Harness repository and its documentation site.
License
Links
More in this category
Q00/ouroboros#integrations/dsh-plugin★ 6060
Config-only bundle that mounts Ouroboros through the DSH MCP client, exposing 36 interview, Seed, execution, evaluation, and evolution workflow tools in DSH.
huangruiteng/loopx#dsh-loopx-plugin★ 5918
LoopX, a provider-neutral, local-first state kernel and control plane for long-horizon agents: keeps Goal, Todo, gate, evidence, quota, recovery, and handoff state above DeepSeek Harness, while the plugin bootstraps the CLI and skills, admits bounded same-session continuation, and adds a loopback GoalBar for the exact bound loop.
chuspeeism/dashi-taskboard#deepseek-harness★ 3176
Embeds the active installed Codex Taskboard runtime in the DeepSeek Harness sidebar, using its launcher runtime descriptor instead of a fixed port.
NanmiCoder/dsh-agent-teams★ 1763
AgentTeams multi-agent teams.
EthanYoQ/AI-Novel-Writer#dsh-ai-novel-writer★ 1054
Installs a dedicated AI novel-writing preset and workbench: revisioned local project assets, a compact side drawer, and native approval-gated single-file changes.
tong-io/tongflow#dsh-tongflow★ 1023
TongFlow film-crew studio for image, voice, music and video production: the agent writes per-asset TongFlow workflow files (.tongflow.json) that run through TongFlow plugins, with an embedded workflow canvas, a shot/character/take project layout and a manga-drama template; sessions starting with @tongflow open the Studio view.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.