Agent Self-Extends in 10 Minutes: DeepSeek Harness's 7-Tool Plugin System

The author demonstrates how an AI agent uses DeepSeek Harness's seven tools to dynamically create, register, run, stop, and version plugins in a sandboxed environment, with syntax validation, append-only versioning, and guided error messages, embodying a 'prevent errors, not malice' philosophy.

Shuge Unlimited
Shuge Unlimited
Shuge Unlimited
Agent Self-Extends in 10 Minutes: DeepSeek Harness's 7-Tool Plugin System

01 A Kitchen That Accepts New Dishes | The Kitchen

Previously the author compared the model to a horse and Harness to the tack. Now imagine a running Harness as a busy kitchen: the stove is lit (process alive), orders keep coming (session ongoing), and a rack of knives and ladles hangs on the wall (tools the model can call). The chef is the model; all its skills come from that rack.

This kitchen has an unusual rule: the chef can invent new dishes. Seven official seals govern the process, with three read seals first: cordis_inspect_list, cordis_inspect_query, cordis_inspect_self for querying archives — the master index, a single page detail, and the chef's own registered dishes. Four write seals follow: cordis_define, cordis_run, cordis_stop, cordis_undefine for writing the recipe, firing the stove, stopping, and closing the case.

Read seals come first — the house rule: before acting, check what ingredients and rules exist. Querying is done by asking, not guessing.

The design document (Agent Note, 2026-07-08) records that the toolset originally had only three seals: inspect, mount, unmount — look, attach, detach. Today the source shows seven. The tools for agent self-modification evolved first: from crude "mount and run" to "query, write, review, run, stop, close". Dishes can be added; house rules can change. The kitchen's self-reconstruction began with the tools themselves.

02 Ten Minutes on the Stove | Live Test

All below is live-tested on 2026-09-03 in the author's own dsh web session.

First seal — query the archive. Before acting, clarify what exists and where to ask. cordis_inspect_list returns a directory: nine inspection providers (called Inspect Provider in source). Four on the kitchen side — service, event, built-in object, tool; five on the front-of-house (browser) side — service, event, built-in object shared with kitchen, plus UI slots and themes. "Tool" is kitchen-only. For a model about to write a plugin, this page is the map: callable services, mountable UI, swappable themes — all visible before acting.

Second seal — cordis_inspect_query . Drill into the directory: fifty-odd services, each with precise method signatures. Example: the timer service lists timeout, interval, throttle, debounce — four usages neatly laid out. A model writing a timer reads this page and knows exactly how to call; no guessing.

A "dictionary lookup" returns not a summary but the dictionary verbatim.

Deliberate sabotage. During recipe registration, the author inserted a TypeScript type annotation ( const label: string = ...) — valid TS but the system only accepts pure JS. The archive door stayed shut: rejected, no ID issued.

Register a clean recipe. System replies: registered, not yet running. Nothing executes at this point.

cordis_run — start. Receipt: running, ID run-1. No approval needed because this recipe only touches the kitchen; per docs, front-of-house changes require human approval.

cordis_stop — stop. Re-query archive: status stopped, recipe remains, version pointer unchanged.

cordis_undefine — close case. Dish, recipe, version all cleared.

Test recipe update. Register v1 with a deliberate typo in the label (name, not code). v1 runs fine, gets run-2. Without touching v1, append v2 with corrected spelling, switch via update, running ID becomes run-3. Archive now shows both versions side by side: v1 marked non-current, v2 current.

The old version is not overwritten; it steps back, retained as a rollback target by the versioning mechanism.

Ten minutes, two full cycles, one rejection. The feeling isn't just delegation — it's that every step is logged and gated, like someone guiding you rung by rung.

03 That Error Reads Like Grading Homework | An Error That Teaches

The rejection left an error line, reproduced verbatim:

Error: dynamic package `code.host` failed to parse:
cordis-dyn-code.host.js:3
const label: string = 'broken on purpose'
         ^^^^^

SyntaxError: Missing initializer in const declaration
Note: it runs as the BODY of an async function (line numbers are offset by the 1-line wrapper). Check bracket balance — ending the returned plugin object with `});` closes a call that was never opened; a plain `return { … }` ends with `}` (an optional `;`), never `)`.

(The final Note is a generic fallback for errors not hitting a dedicated branch; unrelated to the const error.)

Syntax gate: wrong code rejected, clean recipe accepted, 'grading homework' style annotation
Syntax gate: wrong code rejected, clean recipe accepted, 'grading homework' style annotation

Examine this output: the offending line, caret pointer, line number — all provided. It even warns that line numbers are offset because the code is wrapped in an async function. A bracket-balance explanation follows, dissecting the classic extra-parenthesis mistake. The reader is not a human but the model itself.

The define gate contains a compile-time pre-check: code passes a syntax compile first; if it fails, no ID issued, no archive entry — error caught before entry. Fix and re-register; trial cost near zero. Error text is crafted teaching copy. Source also handles a TypeScript pattern: if the error line matches as, a "remove type annotation" correction hint is attached. The author's : string didn't hit that branch, got the generic hint, still fixable at a glance.

The design doc frames this as three correctness problems: on-the-spot registration validation, API-first dictionary, clean teardown on mount. The syntax gate just seen answers the first — errors blocked at the door, model can fix and retry.

Even the token bill was calculated. Docs state: check results rendered as text JSON, re-sent before context compression so lifecycle confirmations compress to one short line; tool directory prefixes stay stable when unchanged, enabling KV cache reuse. Designers counted tokens per context round — compressing confirmations to one line makes repeated reads cheaper.

04 Recipes Only Appended, Never Overwritten | Define Is Not Run

The system assumes you'll write wrong, so it makes writing wrong cheap. Versioning serves that purpose. define only registers — validates params, passes syntax gate, archives source — then explicitly says: not running yet. Whether to run, when, and which version is run 's job.

Putting a recipe in the archive and firing the stove are separate acts. Between them lies "human can change mind" and "version can be chosen".

A dish (plugin) holds multiple recipe versions (packages). Each registration becomes an immutable archive page: no editing mistakes, only append new pages. The author's two coexisting recipes demonstrate this — v1 with typo stays archived, v2 corrected, a pointer marks current.

Why this design? Author's inference: mistakes are normal. First model code often has bugs; if every fix overwrites the old, a worse new version leaves no way back. Append-only insures trial-and-error — torn pages make history untrustworthy.

Mounted plugins aren't unmanaged. Live test shows: after stop, status stops, version retained; after undefine, plugin and its packages removed entirely. Source reveals finer cleanup: each dynamic dish hangs under a unified work unit (fiber). Starting opens the unit; stopping cancels it — borrowed stoves, ingredients, alarms all auto-returned, no manual cleanup. Startup failure likewise releases partial mounts before erroring. Cleanup is a side effect of cancelling the work unit — the "auto-cleanup on unplug" mentioned in the previous article, now seen in implementation.

Version switch: v1 kept, pointer moves to v2, old version instantly revertible
Version switch: v1 kept, pointer moves to v2, old version instantly revertible

05 Appliances Removed, Signposts Added | A Sandbox That Points

The most misunderstood term is "sandbox".

One hears "sandbox" and thinks confinement. Actually it's more like a small room partitioned in the kitchen corner (source: Node vm independent realm — two rooms whose globals don't see each other). A few common appliances are removed — require, setTimeout, fetch (Node environment entry points).

Per source: calling these throws an error whose message doesn't say "forbidden" but provides a signpost. Calling setTimeout yields: Node timers unavailable, use Cordis timer service — declare needed service (inject), check Service.listService for exact usage; these calls auto-attach to the work unit, cleaned up on stop. Network request? Points to web service. File, process? Point to fs and bash services. Files, network, processes, timers — four categories funneled to unified inspection providers, no wild paths.

A source-reading delight: process and Buffer (Node's process manager and binary bucket) are treated as "simply non-existent". Code often does typeof process probes — a gentle touch to decide path. If touching explodes, a harmless probe could crash the whole recipe. Designers anticipated how models probe the environment.

Signposts steer the model's instinctive Node code into inspectable, collectable, auditable official channels.

Sandbox signposts: require, setTimeout, fetch removed; timer, web, fs, bash signposts point to official channels
Sandbox signposts: require, setTimeout, fetch removed; timer, web, fs, bash signposts point to official channels

06 Boundary Checklist | Where It Stops

What it doesn't do matters equally.

Sandbox is not a security boundary. Docs state: trust level comparable to bash; granting this toolset requires same caution as granting bash. Addressing the previous question: removing require, setTimeout, fetch removes direct entry points for dynamic code — they're replaced with signposts to Cordis services. Host helper functions still reach Node. One governs "how far the model's hand reaches"; the other governs "is this a safe". Two separate concerns, no contradiction. Reason: the room only isolates "accidental global pollution".

Time limit covers only half. vmTimeoutMs (sync segment limit, example config 5000ms) constrains only synchronous execution; async body escapes this limit. Docs and source confirm.

Scope: session-bound, process-rooted. Recipes visible/controlable only in registering session, but kitchen shares one stove — running dishes may affect other sessions in same process. Author hasn't live-tested; per docs.

Restart wipes everything. All definitions live only in process memory: no repo files, no packages, no config changes. Process restart reclaims all day's recipes, no auto-restore. Author hasn't tested (didn't restart); based on docs and source. Interpretation: deliberate separation of "experiment" and "asset" — long-term keepers should follow proper plugin dev flow, not rely on a kitchen that zeroes at closing.

Live-test boundaries, disclosed honestly. Author tested only kitchen-side recipes. Front-of-house packages require approval: tool returns awaiting-approval, waits for human nod; approval can cover current version only or all future versions of that plugin. Untested: update failure rollback, runtime error "read-diagnose-fix-version-reupdate" loop, actual signpost error text.

Conflict of interest. Previous article praised its direction; this one praises its engineering. If you think the author was paid, you're right — only curiosity was collected.

Boundary checklist: not a security boundary, trust level near bash, sync time limit, restart clears all
Boundary checklist: not a security boundary, trust level near bash, sync time limit, restart clears all

07 Closing Thoughts | Cook Something

Prevent errors, not malice — those five characters shaped every section above.

To enable writing, a single eval (execute string as code) would suffice. Design substance lives on the error side: syntax errors blocked at the door, errors read like graded homework; versions append-only, trial-and-error always has a way back; side effects bound to work unit, cancellation equals cleanup; dangerous shortcuts removed, official channels plastered with signposts. As for malice — it honestly admits it doesn't handle that, leaving that question to whoever decides whether to grant bash.

Author's verdict: making errors cheap is more realistic than making malice impossible. A system that lets you err confidently, cheaply, and reversibly — that door truly opens.

To try it yourself, prepare the repo signposts: four READMEs under packages/extensions/ are the map set; docs/subsystems/extensions.zh.md is the full interface spec; docs/tool-catalog.zh.md 's cordis section tells which tools the model sees. Launch with one command:

pnpm dsh web --patch apps/cli/config/examples/cordis/cordis.yml

(bring your own model credentials). Remember, this toolset isn't shipped by default; must be explicitly mounted. The author's test environment was pre-mounted. Docs state the trust cost plainly: equivalent to granting bash.

Production: don't get trigger-happy.

Now the model holds a new thing: a tool to fix its own tools. Skills still green, recipes often wrong, but the mistaken page stays in the archive forever —

That's its learning-to-cook process, not a stain.

Go light a stove.

Then come back and hand in the homework.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AI Agentserror handlingversion controlTool Usedynamic pluginssandboxingDeepSeek Harnessruntime introspection
Shuge Unlimited
Written by

Shuge Unlimited

Formerly "Ops with Skill", now officially upgraded. Fully dedicated to AI, we share both the why (fundamental insights) and the how (practical implementation). From technical operations to breakthrough thinking, we help you understand AI's transformation and master the core abilities needed to shape the future. ShugeX: boundless exploration, skillful execution.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.