NI0317 069e0ecdc9 docs: refresh top-level README + add dsh-arch-diagram skill
Replaces the 20-line stub with a bilingual README pair covering:
- getting started (`pnpm run demo:repl` + Node ^22.19 || ≥24 + pnpm 11.7)
- editor integration (Zed / VS Code / Cursor over ACP)
- programmatic embedding via `@deepseek-ai/dsh-app-boot` (with the
  two failure paths of `boot()` vs `installFailLoud` spelled out)
- writing a plugin (`echo-tool` grounded in `examples/echo-agent`, with
  the runnable command `pnpm run demo:echo`)
- Packages table grouped by family, including `session-query`,
  `context`, and Support (with `invariants` called out as a runtime
  diagnostic mounted by `dsh-agent-core`, not test-only)
- deep-dive links, community, license

Bilingual pairing: English and Chinese sides share byte-identical code
blocks and mirroring link ordinals; language-asymmetric community
channels (Discord/X in EN, WeCom in ZH) sit inside HTML `<a href>`
tags that the pairing gate's structural signature excludes by design.
ZH side follows `docs/i18n/terminology.md` — first `agent` occurrence
annotated as `agent(智能体)`, plain `agent` thereafter.

Ships an in-repo skill at `.agents/skills/dsh-arch-diagram/` that owns
the two architecture PNGs (`assets/arch-{en,zh}.png`). HTML templates
+ shared CSS + a `render.sh` that renders via Chrome headless. The
renderer is portable (auto-detects Chrome/Chromium on macOS + Linux,
uses `--no-sandbox` under root for container envs, discovers the local
http.server port from Python's own startup line so `lsof` isn't
required). The 12-card capability row uses `flex: 0 0 auto` so
adjacent card backgrounds cannot clip descriptions; layout tuned to
1560px page / 96% row-width / 1820×580 render viewport.

Consolidates the four review-response commits from the initial round
of ds-review-bot feedback; each review round is documented in a
top-level PR comment for traceability.
2026-07-15 21:06:18 +08:00
2026-07-15 11:28:45 +08:00
2026-07-15 11:28:45 +08:00

DeepSeek Harness

The plugin-first agent SDK. Every capability — including the loop — is a plugin.

license node pnpm typescript ACP Discord X

English | 中文

Docs  ·  Landing page  ·  Community


DeepSeek Harness — System overview

What is this?

DeepSeek Harness is a TypeScript SDK for building AI agents on top of the Cordis microkernel. Every service, including the ReAct loop, is a plugin registered through ctx.*. A batteries-included service registry ships in the box — LLM adapters, sandboxed execution, filesystem with policy, web search, sub-agents, dynamic workflows, session persistence, and more — and a cordis.yml at your project root chooses which get loaded. You can replace any of them, add your own, or leave the shipped defaults alone.

Getting started

New project (one-command scaffold):

npm create @deepseek-ai/harness   # coming soon, not yet on npm

From source (read the code / run demos / contribute):

git clone https://github.com/deepseek-harness/deepseek-harness.git
cd deepseek-harness
pnpm install
export DEEPSEEK_API_KEY=sk-...    # optional — omit and use pnpm run demo:echo (mock, no key)
pnpm run demo:repl

Requires Node ^22.19 || ≥24 and pnpm ≥ 11.7 (Node engine and pnpm pinned in package.json; corepack enable picks up the exact pnpm version). Node 23 is not on the support matrix.

Heads up: demo:repl runs real read / write / edit file tools and bash in your current working directory — best run from a scratch dir or a git-clean project so you can review the changes.

Use it in your editor

Harness ships an Agent Client Protocol (ACP) server. ACP lets an editor drive an agent from its sidebar; Zed supports it natively.

The ACP server command (from your local clone):

pnpm run demo:acp

Zed side — Zed's settings.json (Cmd-Shift-P → "zed: open settings") takes an agent_servers entry:

{
  "agent_servers": {
    "DeepSeek Harness": {
      "command": "pnpm",
      "args": ["--dir", "/path/to/deepseek-harness", "run", "demo:acp"],
      "env": { "DEEPSEEK_API_KEY": "sk-..." }
    }
  }
}

--dir points at your local clone. Zed launches the agent as a subprocess; each Zed session maps to its own agent instance, with chat in the sidebar and tool calls (arguments, results, file diffs) rendered inline in the editor. Configuration details in examples/acp-agent (including the snapshot-tested surface).

VS Code / Cursor — install an ACP client extension for either editor, such as ACP Client (formulahendry.acp-client) or ACP Pro (duclvz.acp-pro), and point a custom agent at pnpm run demo:acp.

Other ACP clients — same launch. Feature-by-feature support matrix in packages/ui/acp/acp-feature-support.md.

Embed it in your own app

Harness bootstraps from a cordis.yml via @deepseek-ai/dsh-app-boot. For library-style integration into your own Node.js service, the same boot helpers apply:

// my-app.ts
import {
  boot,
  installFailLoud,
  loadEnv,
  resolveConfigPath,
} from '@deepseek-ai/dsh-app-boot'

installFailLoud('my-app')
loadEnv('my-app')

const ctx = await boot('my-app', resolveConfigPath('./cordis.yml', undefined))
// ctx is the Cordis root Context; every service you mount in cordis.yml
// is reachable via ctx.* (ctx.agents, ctx.sessions, ctx.tools, …).
// The app plugins loaded from cordis.yml keep the process alive on their own
// (stdio agents hold stdin; the ACP agent holds an RPC connection).
// To shut down programmatically, call `await ctx.fiber.dispose()`.

boot() returns once the whole plugin tree has settled. Two separate failure paths: a module-import failure rejects the boot() Promise directly, so the caller's await throws — handle it with try/catch. installFailLoud covers a different case — a late plugin-init rejection surfacing after boot() has already resolved, which would otherwise become an unhandled rejection and die silently. In cordis.yml, the entry-point app plugin — dsh-stdio-agent for a REPL, dsh-acp-agent for an ACP server, or a custom one — sits alongside whichever services should load. Full helper surface: packages/ui/app-boot.

For end-to-end examples, see examples/:

  • echo-agent — a minimal setup with a mock LLM and an echo tool
  • coding-agent — a full coding agent wired to the real DeepSeek LLM
  • acp-agent — ACP server, with a sandbox composition variant

Demo

Harness driving Zed as an ACP agent — chat in the sidebar, tool calls (bash, file edits, diffs) rendered inline in the editor:

Write a plugin

A Harness function/namespace plugin exports name, inject, and apply — cordis's Loader reads those separately. export default breaks this shape (why): the Loader keeps only the apply function and silently drops inject / name, so the plugin fails to load with cannot get property … without inject. Inside apply(ctx), tools / LLM adapters / services register through ctx.*.

The minimal echo tool from examples/echo-agent:

// echo-tool.ts
import type { Context } from 'cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'

export const name = 'echo-tool'
export const inject = ['tools']

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'echo',
    description: 'Echo the given text back, uppercased.',
    parameters: {
      text: { type: 'string', required: true },
    },
    async execute(args) {
      // args is typed: { text: string }
      return [{ type: 'text', text: `ECHO: ${args.text.toUpperCase()}` }]
    },
  }))
}

parameters uses the schemastery JSON-Schema-shaped DSL — one field per property, with required: true for mandatory ones. A leaf cordis.yml is a flat EntryOptions[] the Loader iterates; this tool's entry looks like:

- id: echo-tool
  name: './echo-tool.ts'          # your tool

Alongside it, a bootable config also needs an LLM adapter and a stdio-agent app entry whose config.model points at an id that adapter registers. The minimal runnable version — mock LLM + this echo tool + a stdio-agent entry wired to mock-echo — is examples/echo-agent, launched via:

pnpm run demo:echo

LLM-adapter and UI-plugin shapes: docs/cookbook/extension-cookbook.md.

Packages

All packages ship under the @deepseek-ai/dsh-* scope. Grouped by family:

Family What lives here
Core (packages/core/) dsh-scope · dsh-session · dsh-tools · dsh-agent · dsh-agent-loop · dsh-system-prompt
LLM (packages/llm/) dsh-llm (the seam) + dsh-llm-deepseek (hand-rolled) and dsh-llm-pi-ai (library-backed twin — same DeepSeek endpoint, different internals, kept for design verification)
Bash (packages/bash/) Shell execution: local + sandboxed backends, model-facing bash tool
Filesystem (packages/fs/) Filesystem service with a policy layer, read / write / edit tools
Web (packages/web/) Web search (Perplexity, Exa, DeepSeek) + fetch, model-facing tool
Sandbox (packages/sandbox/) Process-confinement seam (bwrap / Landlock / Seatbelt) — wraps a caller's argv under a per-call policy; execution itself lives in ctx.bash
Code runtime (packages/code-runtime/) JS worker runtime that Code Mode dispatches into
Sub-agents (packages/subagent/) spawn, fork, plus in-process / subprocess / ACP-backed backends
Workflows (packages/workflow/) Dynamic workflow orchestration (worker-thread execution)
Skills (packages/skill/) Skill-provider registry (ctx.skills) + a local-filesystem provider
Session persistence (packages/session-persistence/) Event-log persistence: JSONL and SQLite backends
Session query (packages/session-query/) ctx.sessionQuery — unified logical-corpus reads over live sessions + persistence
Compact (packages/compact/) Context compression / summarization
Context (packages/context/) Opt-in request-context enrichment (e.g. dsh-time-context — dynamic time-in-prompt)
Cordis toolset (packages/cordis/) Model-facing tools that inspect / mount / unmount cordis plugins at runtime
UI apps (packages/ui/) dsh-stdio-agent (REPL) · dsh-acp-agent (ACP server) · dsh-app-boot · approval + ask-user primitives
Hooks (packages/hooks/) Hook protocol + Claude Code / OpenAI Codex hook-config bridges
Guards (packages/guard/) Advisory loop-hygiene plugins (e.g. repeat-tool-guard for repeated-call escalation)
Timeouts (packages/timeout/) timeout-policy — a zero-config tools/execute wrapper enforcing per-tool timeoutMs
Todo (packages/todo/) The model-facing todo_write tool (whole-list task tracker)
Support (packages/support/) invariants — runtime diagnostic plugin mounted unconditionally by the shipped dsh-agent-spine-demo bundle; plus test/dev-only helpers (llm-replay, acp-snapshot, subagent-mock)
Example bundles (packages/examples/) Ready-to-run demo compositions the top-level demo:* scripts launch: dsh-agent-spine-demo (default spine + capabilities), dsh-stdio-demo (REPL), dsh-acp-demo (ACP server), dsh-jsonrpc-demo
Utils (packages/util/) Internal utility packages (brand, timeout)

For the full module dependency graph, see docs/module-graph.md.

Deep dives

To understand what makes DeepSeek Harness different, start here:

  • Architecture — the service taxonomy and the microkernel structure
  • Agent lifecycle — how a turn flows through the loop, with sequence diagrams
  • Cordis primer — a working introduction to the underlying plugin framework
  • Tool execution pipeline — how a tool call passes through permission gates, hooks, and logging
  • Capability seams — the extension points each service exposes
  • Code Mode — the model writes one JavaScript program per turn that chains many bash / tool calls, executed in a single runtime pass. One model round-trip per multi-step operation, not one per call.
  • Dynamic Workflows — the model writes a plain-JS orchestrator that fans out sub-agents in parallel, joins their results, and returns to the parent — instead of a chain of sub-agent tool calls.
  • Self-referential Cordis toolset — the SDK's own plumbing (cordis_inspect, cordis_mount, cordis_unmount) is exposed as tools, so the model can inspect its own runtime and load new plugins on the fly.

Docs site: deepseek.com/harness-sdk/docs.

Community

Real-time chat on Discord. Release announcements on X / Twitter.

License

BSD 3-Clause © DeepSeek

Description
No description provided
Readme MIT 120 MiB
Languages
TypeScript 97%
CSS 1.6%
Python 0.7%
JavaScript 0.6%