DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Subagent Vision — DSH Plugin for DeepSeek Harness
← Plugins

dsh-subagent-vision

Subagent Vision

dsh bundle: subagent_vision — delegate image reading to a vision-capable model from a text-only session, plus paste-to-path so pasted images reach the subagent as file paths.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add dsh-subagent-vision@0.1.7
READMECompatibilityVersions

Compatibility and provenance

Subagent Vision is published as dsh-subagent-vision and currently resolves to version 0.1.7. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
npm
Registry updated
9/20/2026

Versions

0.1.7stable
9/16/2026
0.1.6stable
9/8/2026
0.1.5stable
8/31/2026
Show 4 more versionsCollapse versions
0.1.4stable
8/21/2026
0.1.3stable
8/17/2026
0.1.2stable
8/16/2026
0.1.1stable
8/16/2026

Related plugins

Loading related plugins…

Latest
0.1.7
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
99.3 kB
Files
8
Surface
web
License
MIT
Source
npm
GitHub
★ 1
Weekly downloads
231
Security scan
✓ v0.1.7 scan passed
Last push
9/16/2026
View source ↗Project homepage ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in

Related plugins

More verified plugins in agents-orchestration.

Headless@deepseek-ai/dsh-headlessThe dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layerExperimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profileExperimental Web profile layer for Agent Teams Remote and UI pluginsSubagent Codex@deepseek-ai/dsh-subagent-codexOne-shot Codex subagent provider over the official app-server protocolSubagent Claude Code@deepseek-ai/dsh-subagent-claude-codeOne-shot Claude Code subagent provider over the official Agent SDK

README

dsh-subagent-vision

English | 中文

A DeepSeek Harness bundle plugin that lets a text-only main agent (DeepSeek) read images in the same session — no model switching, no second session, no copy-paste. When a task needs vision, the main agent delegates to a fresh subagent routed to a vision-capable model you pick in the settings (configured under Settings > Models, chosen under Settings > 视觉处理模型; the factory default is qwen3.8-max — see Configure), and the child's text result is merged back. The image itself never reaches the main model: the parent passes a file path or URL, and only the child's text reading returns — so this is not "the current model natively accepts images"; the current session's model stays text-only, and the vision happens in the delegated child. Pasting or dropping an image just works: intake stays native (thumbnail rail, remove/undo); when you hit send on a text-only session, the browser half uploads each draft image to a private temp file and appends the paths to your prompt, so the request never trips image admission and the text-only agent can delegate the paths to the vision subagent.

Why

DeepSeek chat models cannot take image input, and the harness refuses to switch a session that contains images to a text-only model (and a text-only adapter would reject the image at request time anyway). The harness does have a first-class subagent seam (subagent / subagent_fork tools) whose children can be routed to any registered provider/model — this bundle simply exposes a second delegation tool pinned to the vision route you pick in the settings, plus a send-time image-to-path conversion so images reach that tool as file paths without tripping admission.

How it works

The bundle's cordis.patch.yml inserts one row into the profile composition:

  • subagent-vision — this package's root plugin, which mounts two halves and does four things:
    • The vision tool (tool.js): registers the subagent_vision delegation tool on the public ctx.tools / ctx.subagents seams, so this package implements the tool itself instead of inserting a second instance of another bundle's subagent tool. The row's visionTool config block carries the provider name (default spawn) and the child's agentOptions; the tool appears when that provider appears and disappears with it. The row starts with the factory-default agentOptions in the shipped cordis.patch.yml (qwen/qwen3.8-max) so the tool works out of the box; picking a different model in Settings > 视觉处理模型 applies to the running tool from the next delegation and rewrites that file for the next boot; if anything breaks, edit the agentOptions block directly in that file. Image blocks never enter the parent's session: the parent passes a file path or URL in the tool prompt, the vision child reads it with its own read_image tool (its execution gate checks the child's routed model, which declares image input), and only the child's final text returns as the tool result.
    • Guidance: registers one prompt section telling the model when to use subagent_vision (the stock subagent tool description says nothing about vision). With no route configured it tells the model not to call the tool and to ask the user to configure one first.
    • Vision-route settings: a settings section (subagent-vision namespace, persisted in settings.yaml) plus a Settings > 视觉处理模型 entry rendered by the browser half. The dropdown lists every routable model that declares image input — enumerated live from the adapter catalog (ctx.llm.listModels), which merges each provider's catalog with its settings overrides, so an adapter-shipped vision model such as llm-deepseek's deepseek-v4-flash-vision-exp appears even when its settings entry never names a modality (the same metadata the paste verdict trusts). When none exist it shows a hint that names the configured-but-undecided models and offers each a one-click declare image input button (writes input: [text, image] into that model's entry in the provider settings document, e.g. settings.yaml — the Settings > Models surface itself cannot express input modalities, so a model configured there arrives text-only until declared). The choice applies to the running tool from the next delegation and is also persisted into this bundle's own cordis.patch.yml, so the next boot starts from it before the settings settle; a saved model that no longer resolves, or that doesn't declare image input, is refused and the current route stays.
    • Paste-to-path route (/subagent-vision/paste): GET answers whether a given provider/model is positively confirmed text-only (from inputModalities, never a name guess); POST sniffs image magic bytes (PNG/JPEG/GIF/WebP/HEIC/HEIF), enforces a 25 MB cap, writes a private 0600 temp file, and returns its path.
  • Browser half (client.js, loaded automatically through the package's dsh.client manifest): intake is left fully native — pasting or dropping an image shows the composer's own thumbnail rail, native caret behaviour, and native remove/undo. The plugin's only interception is at send time: when the draft carries image attachments and the target session's model is positively confirmed text-only (the host's verdict, cached 60 s and re-asked when stale), each draft image is uploaded to the host route (POST /subagent-vision/paste -> private temp path), the draft is released, and the paths are appended to the prompt text before the real send — so the request carries text only and never trips image admission. Image-capable models and unknown models send natively (attachments go through unchanged).

The child is composed like any in-process subagent: its own session, its own tools (the parent's preset composition, including read_image when attachments are mounted), and the standard delegation policy (child approval pinned to never, sandbox inherited). The child's internal image blocks stay in the child's own log.

Requirements

  • A dsh installation whose base bundle mounts the subagent capability, tool-fs (read_image), attachments, and the Web surface (the stock web profile does; the browser half needs the Web GUI).
  • At least one vision-capable model configured through Settings > Models (model metadata declaring image input). The shipped patch's factory default is qwen/qwen3.8-max: if that model isn't configured in your deployment, either configure it, pick your own model in Settings > 视觉处理模型, or edit the agentOptions field in the bundle's cordis.patch.yml.
  • The pasted image must fit the route cap (25 MB default); the child's read_image applies the deployment's canonical image limits when it reads the file.
  • Runtime dependencies resolved from the profile (@deepseek-ai/schemastery host-side; the harness services this package builds on — tools, subagents, systemPrompt, llm, settings, and optionally jobs — are provided by the dsh installation itself; react comes from the client module system).

Install

# from npm (fastest — works with the official registry or CN mirrors)
dsh plugin --profile web add dsh-subagent-vision

# from GitHub (pnpm shorthand; append #<tag-or-branch> to pin a revision)
dsh plugin --profile web add github:niuniuaba/dsh-subagent-vision

# from GitHub (explicit git URL)
dsh plugin --profile web add git+https://github.com/niuniuaba/dsh-subagent-vision.git

# from a local checkout
dsh plugin --profile web add /path/to/plugins/dsh-subagent-vision

Restart dsh, then confirm with dsh plugin --profile web list.

Use

Paste an image, drag one into the composer textarea, or give the agent a path/URL, and state a task. On a text-only model the intake becomes a file path in the composer; on a vision model it stays a normal thumbnail paste. Either way, tell the agent what you need:

Read the pasted image and summarize what it shows, then continue from there.

The main agent calls subagent_vision with the path; the child reads it and returns text; the conversation continues in the same session.

Configure

Factory default: qwen3.8-max. The shipped cordis.patch.yml pins qwen/qwen3.8-max as the vision processing model, so the tool works out of the box. To use your own model:

  1. Configure it under Settings > Models — a provider whose model declares image input (e.g. qwen3.8-max with input: [text, image]).
  2. Open Settings > 视觉处理模型, pick your model from the dropdown, and save. The choice is written to settings.yaml, applies to the running tool immediately, and is persisted into this bundle's own cordis.patch.yml for the next boot.

A model whose adapter ships it image-capable needs no declaration at all: llm-deepseek's default catalog already marks deepseek-v4-flash-vision-exp with inputModalities: [text, image], so it appears in the dropdown the moment the provider is configured. (That still only makes it a candidate here — the vision processing model delegated to by subagent_vision. The main conversation model stays whatever you selected; declaring a model image-capable never changes what the current session's model can take directly.)

The Models surface cannot express input modalities: a model configured there is stored without an input declaration and is therefore treated as text-only by the harness until you declare otherwise. If the picker shows your model under "声明支持图片输入", click that button (it writes input: [text, image] into the model's settings.yaml entry) — or add the line by hand:

llm-pi-ai:
  providers:
    qwen:
      models:
        - id: qwen3.8-max
          name: qwen3.8-max
          input: [text, image]

If something goes wrong, you can edit the agentOptions field directly in the bundle's patch file:

$DSH_HOME/profiles/web/node_modules/dsh-subagent-vision/cordis.patch.yml
agentOptions:
  provider: qwen        # use a provider your deployment actually has
  model: qwen3.8-max
  maxTokens: 16384

(A row with the same id in your profile's own cordis.patch.yml also overrides this one — later patch layers win.) If the dropdown instead shows a hint naming your configured model under "声明支持图片输入", click that button (or add input: [text, image] to the model's settings.yaml entry), then reload the settings page — the list is re-read live.

The plugin is configurable through the subagent-vision row's config: visionTool (provider, toolName, enableRunInBackground, and the child agentOptions; visionTool: false turns the tool half off), modelHint, order, visionSettings: false (turns the settings section and picker off), pasteToPath: false (turns the takeover off; the client stands down when the route 404s), maxBytes, verdictTtlMs.

Verify

From the plugin directory (after npm install):

node verify.mjs                   # tool registration, delegation wiring, guide prompt, paste route
node verify-settings.mjs          # settings section, enumeration, picker route, live route
node verify-live.mjs              # live instance: named hint + one-click declare (see below)
node browser-verify/driver.mjs    # browser half in real Chrome (see browser-verify/README.md)

verify-live.mjs drives the REAL running dsh web instance through /subagent-vision/settings: with the model under test temporarily not declaring image input (options empty), it asserts the hint names the configured-but-undecided model, POSTs the declareImage action, and asserts the model becomes selectable again — the declaration itself restores the config. Run node verify-live.mjs [baseURL] [provider] [model] (defaults http://127.0.0.1:3080 qwen qwen3.8-max).

verify-settings.mjs runs the host plugin against a real cordis context with stub llm/settings/loader services and asserts: the settings section registers under subagent-vision, its dropdown options are exactly the image-declaring models from the adapter catalog (including an adapter-shipped vision model whose settings entry never names a modality), a settings change re-points the running tool without rewriting the loader entry that mounts the plugin, unresolvable or non-image routes are refused, the picker's HTTP route serves and persists the choice, configured-but-undecided models are surfaced and can be declared image-capable with one click, and the no-model hint renders. The browser suite drives the shipped client.js in Chrome against the real paste route and the send-time conversion (native intake untouched, drafts converted on send for text-only sessions, native send for vision/unknown models, upload failures abort the send).

verify.mjs mounts the host plugin on the REAL tools/subagents/system-prompt services with a scripted ctx.subagents provider and stubbed llm/settings/loader/webServer, and asserts: the subagent_vision tool appears only when its provider registers, executing it forwards the configured vision agentOptions into the child start request and returns the child's text, a settings change re-points the next delegation while the loader entry stays untouched, the guide prompt section renders, and the paste route answers verdicts and stores uploads.

Limitations

  • No per-call model selection: the child route is the deployment-configured agentOptions, not a tool argument the model can change mid-task. (This mirrors the stock subagent tools' fixed-route constraint.)
  • Send-time conversion is all-or-nothing per send: a draft's images are all converted before the send; a failed upload aborts the send (the composer restores the draft and thumbnails, so nothing is lost).
  • Temp files accumulate: pasted images land in the OS temp directory under subagent-vision-paste-*; nothing deletes them (the OS temp cleaner will).
  • One-shot children: the child settles and its conversation is read-only afterwards (use the stock subagent/continuable tools if you need to keep talking to a child).
  • The parent model never sees the image itself — only the child's text reading of it.

Credits

The image-to-path pattern (magic-byte sniffing, private temp files, host-side verdict) follows ModLens (MIT); this bundle differs by resolving the current model from the client object layer instead of the model-selector DOM label, converting at send time instead of intercepting intake, and delegating to a vision subagent instead of an external vision engine.

License

MIT