deepseek-super-agent
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Basarisiz
- exec() — Shell command execution in .github/workflows/acceptance.yml
- exec() — Shell command execution in .github/workflows/ci.yml
- process.env — Environment variable access in src/channels/feishu.ts
- exec() — Shell command execution in src/channels/github-source.ts
- process.env — Environment variable access in src/channels/github-source.ts
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Open-source DeepSeek Super-agent style multi-agent framework with a thin harness — Router/Worker, triggers, Watchdog (not an official DeepSeek product).

deepseek-super-agent
English | 简体中文
CLI: ds-agent. License: MIT.
Thin TypeScript runtime. Custom Harness below. Domain engine on top.
Inspired by DeepSeek's public article and prototype. Independent implementation. No DeepSeek Harness, Cordis, or @deepseek-ai/dsh*.
Author: LofiSu. Co-written with Grokbot (CoderBot).
Docs · Inspiration · Features · Architecture · Quick start · Demo · Models · Credits · License
Shorter pages, same facts: install, architecture, safety. 中文.
What this is
Two layers.
- Harness. Session log, async ReAct loop, OpenAI-compatible calls, tools by role, daemon.
- Engine. Intake → Eval (Gate + Assessment) → Mandate/Ticket → Assignment → Outbox. Domain writes stay in the Engine.
Domain naming follows 从零打造 Personal Agent(三): the router role is the Main Agent / Main Session, the worker role is the Executor, and Subscription is a context-only Ticket ↔ Thread relation. The audit and corrections are in docs/DOMAIN_ALIGNMENT.md.
Inspiration
| Source | Link | Used for |
|---|---|---|
| WeChat article | Super-agent 设计探索 | §2–§6: dual Router/Worker, Trigger, async tools, multi-channel, state vs environment, Watchdog |
| Official prototype | deepseek-ai/dsh-superagent-prototype | Trigger → Eval → Ticket → Assignment. The Harness is ours. |
Features
Checked against Super-agent 设计探索, one item at a time. Status follows this repo, pnpm demo, and pnpm test. Task list: PLAN.md (T01–T51). Where the plan and the code diverge: docs/REVIEW.md.
[x] done and covered. [~] partial. [ ] not done. Extension domains are always-wired Runtime services, not an opt-in gate: router shards, Worker mesh, long-term memory, lifecycle events, and A2A are assembled on every run. See docs/MODULES.md.
§1 Four traits
- Continuous. IM and GitHub-style channels share one domain state. Sessions stay inside the runtime. (Harness Session + Engine Thread/Ticket)
- Efficient. Workers run in parallel. The Router batches Triggers waiting on the same Thread (
evals+ harness inbox). - Proactive. Triggers drive the loop. Speculative Assignment, then a deliver gate (
speculate/). - Persistent. SQLite. A restart can resume (
store/plus the demo restart check).
§2 Dual Router / Worker
- Continuity vs throughput. Two layers. The Router talks and dispatches. Workers execute alone (
Role). - Router is the sequence point. Inbound goes through the Engine. Outbound goes through Router/Outbox.
- Router stays light. Workers hold the execution tools. The Router tool set is smaller.
- Small model on the Router.
models.routerfromroleModelsFromEnv. Workers can use a stronger model. - Trigger batching. A positive
batchWindowMsfolds same-Thread Triggers into one Eval. Covered bytest/batching-bench.test.ts; the real-channel demo uses the default window (0), so it does not exercise folding. - [~] Router sharding / multi-layer filter.
RouterShardRegistryis always wired into the Runtime (PLAN T09/T46). Configure withDS_AGENT_SHARDSorRuntimeOptions.routerShards; the default shard always exists. - Isolated Worker context. Each Worker has its own Session and the full tool set.
- Workers report upward.
reportgoes to the Router. The Router sends the reply. A worker session holdsWorkerPorts, not the Engine, and cannotreplyordecide. - Worker ↔ Thread subscriptions. Many-to-many, via
subscribeand fan-out. - Subagent / Team inside a Worker. Async jobs +
spawn_team/team_status/complete_team→ member jobs →TEAM_MEMBER_DONE→ aggregate report. Team rows persist in SQLite andds-agent team/teamsinspect them offline. Router only sees the parent Assignment report (T14; unit + harness + live e2e). - [~] One UI, many topics. Several Tickets can exist at once.
LifecycleBusis always wired as a read model; there is no default UI yet (T15/T49).
§3 Event-driven
- Triggers. Semi-structured events from IM / GitHub-style sources.
- Fast Path. Deterministic source and noise rules (
ingress/filter). - Slow Path. Semantic or policy filter. The shipped classifier is deterministic (
ruleClassify); a model-backed policy classifier is not wired, so rules stand in. - Thread. One topic or PR. One event stream. Thread key.
- Already subscribed. Straight to the Worker. Log line
bypass=subscriptionplusticketId. - Not subscribed. Cold start: Intake → Eval → Ticket.
- Unsubscribe / hand back.
handbackdrops the subscription and requeues the trigger for Eval (T21). - Router still sees every Trigger. Intake records them.
- Inline. Short summaries stay in context (
memory/recall). - Spill. Long content is stored out of band, with an id (
store/spill). - Locality. IDs and summaries first. Expand on demand (
read_object). - Chain of Recall. Pull a spill id or object ref when needed (minimal T25).
- Speculative work. A background Assignment can run first.
- Deliver gate.
deliver=true, or the result is dropped. The demo checks this.
§4 Talking to people
- Async ReAct. The
start_jobtool returns{status:'started',jobId}at once and ends the turn;Harness.launchenqueues the next turn. The foreground does not wait. Covered bytest/job.test.ts; the real-channel demo does not callstart_job. - Started notice. A job-started log event.
- Completion comes back. A finished job re-enters the Worker as a
JOB_DONEprompt and triggers the next turn. - Duplex. New input still arrives while a job runs.
- IM norms. Short replies. Low interruption (
channels/norms, with a word cap). - GitHub-style output. Structured text from the GitHub channel formatter.
- Only the Router speaks outward. Workers cannot write a channel directly.
§5 Compute, state, environment
- Stateless compute. Session and domain state live in SQLite.
- Env stays on the machine. Sandbox directory via
LocalEnv. - Daemon holds no session.
daemon.tsschedules the Watchdog and similar work. - BYOM. OpenAI-compatible
DS_AGENT_API_*and provider key presets (resolveLiveApi). - [~] Machines that come and go.
MachineRegistryheartbeats + stale detection (DS_AGENT_MACHINE_STALE_MS) + daemon resume hook (T40). True multi-host mesh still optional.
§6 Watchdog
- Outside control loop.
watchdogrole. - Timer. Daemon interval tick.
- Stuck work. Nudge or fail. Watchdog tools, plus the demo tick.
- [~] Infra faults and goal drift, in plain language. Nudge/fail + rules + read-only
ds-agent health(store/vault mode/machines/watchdog). Deeper NL drift checks still thin (T43–T44).
§7 Experiments
Article evals. They do not block the release.
- Runtime counters. Ingress admit/drop, eval accept, bypass fan-out, speculative deliver/discard, watchdog nudge/fail, model latency.
ds-agent metricsreads<stateDir>/metrics.json. - [~] Latency curve samples. Optional
curveSamples/summarizeCurvein metrics (T45). Full dual-layer vs one-Session bake-off still open. - Router batching stress curves.
runBatchingStressfloods same-Thread Triggers, records batch sizes + eval counts, and appends one Eval latency sample per eval tocurveSamples(T45 stress harness).
§8 Left open
Kept out of M11.
- [~] Router scale-out / Worker-direct topology (§8.1) — always-wired
RouterShardRegistry+WorkerMeshRegistry(placement is logical; a remote transport is external) - [~] Memory that spans tickets (§8.1) — always-wired
SpillBackedLongTermMemory(not month-scale yet) - [~] A product shell that is not a Session (§8.2) — always-wired
LifecycleBusread model; no default UI yet - Mid-task collaboration with a person (§8.2) — CLI
pause/intervene/resume/collab+ durableTicket.collaboration; harness/watchdog honor pause - Panel · Execution —
ds-agent panelderives Open/Pending/Working/Waiting/Blocked/Awaiting from Ticket facts, with Mandate, Executor Session, directory, report, and Outbox delivery counts (src/core/panel.ts) - [~] A2A across instances (§8.3) — always-wired
A2ARouter(in-process;runtime.sendA2A) - [~] Credentials stay out of tool output. LocalEnv allowlist +
[redacted]for secret-named env values of at least 8 characters (shorter values and other names are left as-is) + FileVaultdescribe()(names only). Every worker bash is wrapped:sandbox-execon macOS,bwrapon Linux; a missing wrapper is a hard error with no plain-bash fallback, and network is denied unless the policy allows it. The wrapper confines writes and network, not reads: both platforms still allow broad reads, so process-level read isolation, including the SQLite DB, remains an external/container boundary (§8.4, T51). Host vault/seccomp policy still external.
Modules M0–M11
| Module | Article | Status |
|---|---|---|
| M0 shared | types / ports | [x] |
| M1 Harness | §2 / §4.1 / §5 | [x] |
| M2 Store | §5.1 / §3.3 Spill | [x] |
| M3 Engine | §2 / §3 Eval, Ticket, Assignment | [x] |
| M4 Ingress | §3.1 | [x] |
| M5 Subscribe | §3.2 | [x] |
| M6 Memory | §3.3 | [x] |
| M7 Speculate | §3.4 | [x] |
| M8 Channels | §4.2 | [x] |
| M9 Env | §5.2 | [x] |
| M10 Watchdog | §6 | [x] |
| M11 CLI demo | acceptance script | [x] pnpm demo |
Architecture
A Channel enters Ingress, then the Engine. The Engine routes and batches, then runs Thread → Eval → Ticket → Assignment. Harness runs the Worker Session. Store and Env are underneath. Watchdog stays outside that path.
flowchart TB
subgraph Channels["Channel"]
C1["CLI / Feishu IM / GitHub (real adapters)"]
end
subgraph Ingress["Ingress"]
Fast[Fast Path]
Slow[Slow Path]
Fast --> TK[Thread key]
Slow --> TK
end
subgraph Engine["Engine"]
Intake[Intake / routing + batching]
Thread[Thread]
Eval[Eval]
Ticket[Ticket]
Assign[Assignment]
Intake --> Thread --> Eval
Eval -->|actionable| Ticket --> Assign
Eval -->|noise| Drop[drop / archive]
end
subgraph Harness["Harness"]
Sess[Session · async ReAct · model · tools]
Worker[Worker]
Assign --> Worker
Worker --> Sess
end
subgraph Bottom["Foundation"]
Store[(Store · SQLite + Spill)]
Env[Env · LocalEnv / daemon]
end
WD[Watchdog]
C1 --> Fast
C1 --> Slow
TK --> Intake
Sess --> Store
Sess --> Env
Worker -.->|report| Intake
WD -.-> Worker
Text flow:
Channel ──► Ingress (Fast/Slow → Thread key)
│
▼
Engine.receive
│ routing / batching
▼
Thread ──► Eval ──► Ticket ──► Assignment
│ │
└─ drop ▼
Harness Worker
│
Store ◄───────────────────┤
Env ◄───────────────────┘
Watchdog → stuck Workers
A subscribed Thread uses bypass=subscription. It skips Router Eval and goes to the Worker already on that Thread.
| Layer | Job |
|---|---|
| Channel | inbound adapters, outbound shape |
| Ingress | Fast / Slow Path → Thread key |
| Engine | routing and batching, Thread, Eval, Ticket, Assignment |
| Harness | session, async ReAct, model, tools, daemon |
| Store | SQLite, Spill, read_object |
| Env | sandbox directory and process |
| Watchdog | stuck Workers |
Quick start
Node.js 22+. See engines in package.json. The store uses node:sqlite. Install pnpm. This is a source-only repository: no npm package, no bin, no build; run pnpm ds-agent ... from the checkout.
pnpm install
export DS_AGENT_API_BASE=https://api.deepseek.com
export DS_AGENT_API_KEY=sk-...
export DS_AGENT_API_MODEL=deepseek-flash
pnpm test
gh auth login # real GitHub Source + Outbox
export DS_AGENT_GH_REPO=your-account/your-writable-repo
pnpm demo
pnpm test and pnpm demo both require a live OpenAI-compatible model. MockModel is forbidden in the default suite and demo. Set DS_AGENT_API_BASE, DS_AGENT_API_KEY, and DS_AGENT_API_MODEL before pnpm test. If any of the three is missing, the test script fills a local Magpie default (http://127.0.0.1:3425/v1, key magpie, model workbuddy/deepseek-v4.1-flash). A provider key alone does not replace that, because the script sets the base and key itself.
pnpm demo uses real channels only: it creates and reads real GitHub issues and posts real issue comments through gh api. There is no fake IM or GitHub fallback. Set DS_AGENT_GH_REPO to a repository you can write. Unset, it is LofiSu/deepseek-super-agent. Closing the issues is best-effort. The close runs after each scenario's main work, a failed close is ignored, and a throw or an early return before the close leaves issues open. DS_AGENT_GH_KEEP=1 skips the close. Afterwards, check for open issues labeled ds-agent-demo. pnpm demo:local is an in-memory fixture baseline for offline smoke checks, not the acceptance path. Feishu setup and pnpm demo:feishu are documented in docs/REAL_CHANNELS.md.
pnpm demo and pnpm ds-agent chat do not apply the Magpie default from the test script. For those, set both DS_AGENT_API_BASE and DS_AGENT_API_KEY, or one provider key. Setting only one of that pair exits with an error.
Live demo for DeepSeek V4.1 Flash. The API name is deepseek-flash. Set DS_AGENT_API_*:
export DS_AGENT_API_BASE=https://api.deepseek.com
export DS_AGENT_API_KEY=sk-...
export DS_AGENT_API_MODEL=deepseek-flash
pnpm demo
pnpm ds-agent chat "fix the login timeout"
Omit DS_AGENT_API_MODEL on that pair and the client sends deepseek-chat. DEEPSEEK_API_KEY alone defaults to deepseek-flash.
DS_AGENT_API_BASE can be any OpenAI-compatible URL. A local Magpie gateway is allowed. Use the gateway token as the key (often magpie on this machine), and Magpie's model id.
export DS_AGENT_API_BASE=http://127.0.0.1:3425/v1
export DS_AGENT_API_KEY=magpie
export DS_AGENT_API_MODEL=deepseek/deepseek-flash
export DS_AGENT_GH_REPO=your-account/your-writable-repo
pnpm demo
GitHub Actions runs pnpm typecheck and pnpm test on pushes to main and on pull requests. The demo job runs pnpm demo:local (in-memory fixture smoke, no repository writes) when DEEPSEEK_API_KEY or DS_AGENT_API_KEY is set; real-channel acceptance is pnpm demo run by an operator with gh auth.
State lives in DS_AGENT_HOME, or in ./.ds-agent (SQLite).
pnpm ds-agent tasks
pnpm ds-agent panel
pnpm ds-agent retry <ticketId>
pnpm ds-agent status
pnpm ds-agent metrics
pnpm ds-agent emit im --thread bug-login --text "login still 500"
pnpm ds-agent emit github --pr 42 --text "CI failed on auth test"
Demo (real channels)
pnpm demo is the acceptance path and it uses real channels only:
| Scenario | Real inbound Source | Real outbound Outbox |
|---|---|---|
01-parallel-github |
three real GitHub issues pulled via gh api |
one issue comment per ticket |
02-spill-github |
one real issue body + two real comments | Router replies as issue comments |
03-watchdog-github |
one real issue pulled via gh api |
acknowledgement issue comment |
Each run creates fresh issues on DS_AGENT_GH_REPO (default LofiSu/deepseek-super-agent), waits for the live model, posts real comments, then re-reads those comments from the GitHub API as proof. Closing is best-effort: it runs after each scenario's main work, a failed close is ignored, and a throw or an early return before the close leaves issues open. DS_AGENT_GH_KEEP=1 skips the close. Check afterwards for open issues labeled ds-agent-demo. Logs and JSON proofs land in /tmp/ds-agent-live-e2e-logs/demos/.
export DS_AGENT_API_BASE=http://127.0.0.1:3425/v1
export DS_AGENT_API_KEY=magpie
export DS_AGENT_API_MODEL=workbuddy/deepseek-v4.1-flash
export DS_AGENT_GH_REPO=LofiSu/deepseek-super-agent
gh auth login
pnpm demo # all three scenarios
pnpm demo -- --only watchdog # one scenario
DS_AGENT_GH_KEEP=1 pnpm demo # keep the real issues open
pnpm demo:local runs the legacy in-memory fixture baseline; it is not the channel acceptance path. pnpm demo:feishu exercises the real Feishu message API when FEISHU_APP_ID/FEISHU_APP_SECRET/FEISHU_CHAT_ID are set. pnpm test:live runs the live-model tests when a key is already in the environment.
Extension domains
The functional domains keep the T45–T51 ids: evaluation and metrics, extensions, long-term memory, product layer, interop, and security and privacy. The extension services are no longer behind a feature flag; Runtime.create always constructs them:
runtime.routerShards—src/ingress/shards.ts; configure withDS_AGENT_SHARDS(JSON) orRuntimeOptions.routerShards. The default shard always exists.runtime.workerMesh—src/harness/mesh.ts;DS_AGENT_MESH_CAPACITYorRuntimeOptions.meshCapacity.runtime.longTermMemory—src/memory/long-term.ts; one entry per finished ticket.runtime.lifecycle—src/core/lifecycle.ts; read-model events for panels and CLI views.runtime.a2aRouter/runtime.sendA2A—src/channels/a2a.ts; the Runtime registers its instance as the local recipient.
DS_AGENT_INSTANCE_ID sets the local A2A address and mesh node id. See docs/MODULES.md for the module reference.
DS_AGENT_INSTANCE_ID=alpha pnpm ds-agent chat "fix the login timeout"
DS_AGENT_SHARDS='[{"id":"github","filter":"source:github"}]' pnpm ds-agent chat "CI failed"
Models
Both DS_AGENT_API_BASE and DS_AGENT_API_KEY win over the presets below. Omit the model and that pair sends deepseek-chat. For V4.1 Flash, set deepseek-flash.
| Variable | Meaning |
|---|---|
DS_AGENT_API_BASE |
OpenAI-compatible base. DeepSeek: https://api.deepseek.com. Local Magpie: http://127.0.0.1:3425/v1. |
DS_AGENT_API_KEY |
API key. On Magpie, this is the gateway token, not the DeepSeek key. |
DS_AGENT_API_MODEL |
Model id. deepseek-flash is DeepSeek V4.1 Flash. On Magpie use deepseek/deepseek-flash. |
A provider key alone fills in the base and default model. The first matching row wins. DS_AGENT_PROVIDER picks one. Aliases: xai/grok, moonshot/kimi, zhipu/glm, gemini/google, anthropic/claude.
| Provider | Environment variable | OpenAI-compatible base | Default model |
|---|---|---|---|
| DeepSeek | DEEPSEEK_API_KEY |
https://api.deepseek.com |
deepseek-flash |
| OpenAI | OPENAI_API_KEY |
https://api.openai.com/v1 |
gpt-4o-mini |
| OpenRouter | OPENROUTER_API_KEY |
https://openrouter.ai/api/v1 |
deepseek/deepseek-chat |
| xAI / Grok | XAI_API_KEY or GROK_API_KEY |
https://api.x.ai/v1 |
grok-4.7 |
| Moonshot / Kimi | MOONSHOT_API_KEY or KIMI_API_KEY |
https://api.moonshot.cn/v1 |
kimi-k3.1-pro |
| Zhipu / GLM | ZHIPU_API_KEY or GLM_API_KEY |
https://open.bigmodel.cn/api/paas/v4 |
glm-5.3 |
| Gemini | GEMINI_API_KEY or GOOGLE_API_KEY |
https://generativelanguage.googleapis.com/v1beta/openai |
gemini-3.8-flash |
| Anthropic | ANTHROPIC_API_KEY |
https://api.anthropic.com/v1 |
claude-opus-5-5 |
HttpOpenAI posts to {base}/chat/completions with Authorization: Bearer. Moonshot's international base is https://api.moonshot.ai/v1. Zhipu's overseas base is https://api.z.ai/api/paas/v4. Set those with DS_AGENT_API_BASE and DS_AGENT_API_KEY.
pnpm ds-agent chat calls createModelFromEnv() (legacy offline Mock only when no key). Demo and pnpm test call requireLiveModelFromEnv() / Magpie HttpOpenAI and refuse MockModel.
Use a small model for the Router and Watchdog. Use a stronger one for the Worker. The table is one model for the process.
Credits
Author: LofiSu. Co-written with Grokbot (CoderBot).
Live model tests
Measured on a local Magpie gateway (Asia/Shanghai) with workbuddy/deepseek-v4.1-flash:
export DS_AGENT_API_BASE=http://127.0.0.1:3425/v1
export DS_AGENT_API_KEY=magpie
export DS_AGENT_API_MODEL=workbuddy/deepseek-v4.1-flash
export DS_AGENT_GH_REPO=LofiSu/deepseek-super-agent
gh auth login
pnpm test
pnpm demo # real GitHub issues/comments + live model
pnpm test fills any missing DS_AGENT_API_* with those Magpie defaults before Vitest starts. test/setup-live.ts does the same only when the variables are still unset, and it skips that fill on CI. A provider key alone does not replace the three. Transcripts from the E2E cases land under /tmp/ds-agent-live-e2e-logs/; real-channel demo logs and proofs land in /tmp/ds-agent-live-e2e-logs/demos/. Update the pass/fail counts in this section after each live run.
License
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi