deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:HEO-Club/DSH-DAG
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
English · 中文(简体)
Give your DeepSeek Harness agents the power to run complex multi-agent workflows, declaratively: break one big task into a graph of smaller agent subtasks, run the independent ones in parallel, and combine the results — with deterministic, code-enforced orchestration.
The DSH main agent is a single long-running turn. Fanning out to many agents by hand — some subtasks depending on others, results flowing back and forth — is error-prone and doesn't scale. DSH already ships imperative fan-out (subagent, workflow), but nothing that declaratively describes a dependency graph and lets the machine run it.
This plugin fills that gap. The model (or any caller) submits a small JSON description of the workflow — nodes, dependencies, success criteria — and the plugin takes care of the rest:
You describe what the workflow is. The plugin handles how it runs.
| Capability | What it does |
|---|---|
| Declarative input | A JSON task graph: nodes, dependsOn, inputSources, success criteria, optional per-node model |
| Deterministic validation | Duplicate ids, unknown dependencies, cycles, missing input sources… invalid proposals are rejected before any run starts, with structured, model-correctable errors |
| Parallel scheduling | Independent nodes run concurrently under global + per-model limits; dependent nodes are released only when every parent succeeds |
| Node state machine | PENDING → READY → RUNNING → SUCCEEDED / FAILED / CANCELLED, failures cascade as BLOCKED, full audit trail |
| Retry & recovery | Only retryable errors retry, with bounded exponential backoff; per-node timeouts; clean cancellation propagation |
| Result aggregation | A single result passes through; many results are fused by one LLM call (or deterministically deduped and concatenated) |
| Observability | dag/* lifecycle events on the host, optionally recorded into the calling agent's session |
DSH main agent
│ the model calls the dag_run tool (or a plugin calls ctx.dag.start())
▼
dsh-dag the Cordis plugin — tool, service, config, events
│
▼
dag-core the framework-free engine — model, validation, analysis,
scheduler, state machine, retry, fusion
│
▼
Parallel agent execution — concurrent child agents via DSH subagents
Every run follows one deterministic pipeline:
dsh plugin --profile <name> add dsh-dag
Installing applies the plugin's bundle patch, which inserts the dsh-dag row into the host composition and provides the dag service on the host plane. Verify it landed:
dsh --profile <name> --dump-config | grep dsh-dag
The dag_run tool is exposed per agent by composing a preset copy with an isolated dag realm (mirroring how the built-in delegation group isolates workflowEngine):
- id: dag-delegation
name: cordis:group
group: true
isolate:
dag: true
config:
- id: dsh-dag-tool
name: 'dsh-dag'
Ask your agent for a multi-step task, or call the tool directly with a workflow like the one below.
dag_run toolSubmit a TaskGraphProposal-shaped JSON:
{
"schemaVersion": "1.0",
"planId": "research_plan", // ^[a-z][a-z0-9_-]{0,63}$
"objective": "Research X and write a report",
"nodes": [
{
"nodeId": "search",
"title": "Search the literature",
"prompt": "Find and summarize the top sources on X.",
"capabilityRequirements": ["web"],
"outputRequirements": ["A bullet list of sources"],
"successCriteria": ["at least 3 sources"],
"executorKind": "runtime",
"toolLabels": ["web_search"],
"dependsOn": [],
"inputSources": []
},
{
"nodeId": "draft",
"title": "Draft the report",
"prompt": "Write the report from the search results.",
"dependsOn": ["search"],
"inputSources": [{ "sourceNodeId": "search", "purpose": "use search results" }],
"capabilityRequirements": ["general"],
"outputRequirements": ["Markdown report"],
"successCriteria": ["covers all sources"],
"executorKind": "runtime"
}
]
}
Invalid proposals never create a run — you get back structured, correctable errors instead.
{
"runId": "dag_a1b2c3d4",
"status": "completed", // completed | partial | failed | cancelled
"value": "…fused final answer…",
"nodeCount": 2,
"agentsStarted": 3,
"failures": [{ "nodeId": "draft", "status": "failed", "error": "…" }]
}
Anything other than completed surfaces as a tool error — never as a silent success.
const run = ctx.dag.start({
proposal, // TaskGraphProposal
parent: exec.agent,
options: { idempotencyKey?, nodeTimeoutMs?, maxTotalNodes?, fusion?, globalLimit?, maxRetries? },
})
const outcome = await run.result
await run.dispose()
| Key | Default | Meaning |
|---|---|---|
toolName |
dag_run |
The model-facing tool name |
subagentProvider |
spawn |
ctx.subagents provider used for every node (and fusion) call |
globalLimit |
4 |
Global node concurrency (0 = unlimited) |
perModelLimits |
{} |
Per-model node concurrency (0 = unlimited) |
retryPolicy.maxRetries |
2 |
Per-node retry ceiling |
retryPolicy.baseDelaySeconds |
1 |
Exponential backoff base |
retryPolicy.maxDelaySeconds |
30 |
Backoff cap |
nodeTimeoutSeconds |
300 |
Per-node timeout (0 disables) |
maxTotalNodes |
32 |
Hard node-count cap per run |
maxResultChars |
100000 |
Cap on dependency outputs injected into downstream prompts |
fusion |
auto |
auto: single result passes through, many fuse via LLM; llm: always fuse; none: deterministic concatenation |
emitSessionEvents |
true |
Record dag/* events into the calling agent's session |
Observe-only dag/* events are emitted on the host and (optionally) appended to the calling agent's session:
dag/run-start · dag/node-start · dag/node-end · dag/retry · dag/run-end
Payloads carry scalar facts only — never live handles.
What you can rely on
run.cancel() / exec.signal aborts in-flight children; every child run is disposed.Current limitations (V0.1)
dag_run only when it judges the task genuinely needs a DAG.never, sandbox scope inherited); nodes that need approval-gated tools fail deterministically.dsh plugin --profile <name> remove dsh-dag
Then remove the composed preset copy (e.g. the dag-delegation group above) from your agent preset and restart the session. Active runs are cancelled automatically on unload.
Quick orientation — the full engineering specification and migration plan lives in
docs/DSH Multi-Agent DAG Plugin — Engineering Specification & Migration Plan.md.
packages/
├── dag-core/ dsh-dag-core — framework-free orchestration engine (zero runtime deps)
└── dsh-dag/ dsh-dag — the Cordis plugin adapter
npm install --ignore-scripts # workspace install (typescript + vitest)
npm run build # tsc → packages/*/lib
npm run typecheck
npm test # 110 deterministic tests — no network, no real LLM
dag-core is a faithful TypeScript port of a proven Python orchestration middle layer, kept 1:1 for parity (component mapping in the spec above). The plugin adapter is deliberately thin: everything orchestration-related lives in dag-core, everything DSH-related lives in dsh-dag.
MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。