DeepSeek Harness Python
English | 中文
DeepSeek Harness Python is a plugin-first agent harness with two cooperating Cordis runtimes. PyCordis owns backend plugins and the Python Agent Spine. The original TypeScript Cordis remains in the browser and owns page plugins. A versioned Browser Bridge connects them through explicit JSON RPC and Events.
The goal is a stable harness where new product behavior is normally delivered as a plugin, without changing the Agent Loop or either lifecycle kernel.
Architecture
One logical plugin has one root identity and may contain a backend contribution, a client contribution, or both:
plugin.toml
backend.py
frontend/
package.json
src/
dist/client.js
protocol/api.schema.json
plugin.toml is authoritative. Nested Python or frontend package files are build inputs and cannot redefine the Plugin ID or version.
| Plugin form | Runtime | Typical use |
|---|---|---|
| Backend only | PyCordis | Tools, LLM providers, storage, workflows, policy |
| Client only | Cordis TS | Panels, commands, page state, browser integrations |
| Full stack | Both | UI backed by Python services through RPC and Events |
The two runtimes do not share objects or lifecycle state. The Dynamic Plugin Manager computes one content Revision from the manifest and declared artifacts, starts the backend Fiber, publishes the exact client bundle, and projects the desired graph to connected pages. Each page then mounts one Cordis TS child Fiber for the same Plugin ID and Revision.
flowchart LR
M["plugin.toml"] --> PM["Dynamic Plugin Manager"]
PM --> PY["PyCordis backend Fiber"]
PM --> AR["Revisioned client artifacts"]
AR --> BB["HTTP / WebSocket Browser Bridge"]
BB --> TS["Cordis TS page Fiber"]
PY <--> |"Revision-qualified RPC / Events"| BB
Enable, update, rollback, and disable are live operations. An update disposes the old backend registrations and asks pages to unload the old client Fiber before activating the replacement. Stale Revision calls lose authority. Disable removes publication, backend Effects, page Fiber contributions, and outstanding page-owned calls.
Backend plugins receive their exact Manager-owned identity through the isolated PLUGIN_RUNTIME_IDENTITY Service. Browser modules that export createPlugin(api) receive a revision-bound PluginChannel from reconciliation. Plugins never calculate or accept their own runtime Revision as user configuration.
Browser readiness is derived separately from publication. The Host defaults to requiring every connected page to activate a required client contribution; deployments may select any_connected globally or per Plugin ID. A required client plugin stays WAITING until a page connects, can recover from FAILED without republishing, and reports page-qualified diagnostics through the Manager snapshot.
Author plugins
The supported Python author API is harness.sdk. Backend-only plugins use define_backend_plugin; plugins that need the Browser Bridge use define_bridge_backend_plugin and identity-free RPC/Event descriptors:
from harness.sdk import define_bridge_backend_plugin, rpc_method
DESCRIBE = rpc_method("describe")
async def setup(ctx):
await ctx.channel.register_rpc(DESCRIBE, lambda arguments: arguments)
plugin = define_bridge_backend_plugin(setup)
Client plugins use the matching TypeScript SDK. defineClientPlugin binds every call, Event, listener, and custom Effect to the reconciled Plugin ID, Revision, and Cordis TS Fiber:
import { defineClientPlugin, rpcMethod } from '@deepseek-harness/browser-bridge-client'
const describe = rpcMethod<{ value: string }, { value: string }>('describe')
export const createPlugin = defineClientPlugin(async (ctx) => {
const result = await ctx.call(describe, { value: 'ready' })
document.body.dataset.plugin = result.value
return () => { delete document.body.dataset.plugin }
})
Production factories never accept Plugin ID or Revision. Test-only harnesses under harness.sdk.testing and @deepseek-harness/browser-bridge-client/testing inject fixture identity while exercising the same public lifecycle paths.
Create a complete backend-only, client-only, or full-stack project with the scaffolder:
uv --directory python run deepseek-harness-plugin create \
--kind full-stack \
--plugin-id com.example.echo \
--destination plugins/echo
uv --directory python run deepseek-harness-plugin validate plugins/echo
python -m harness.scaffold is equivalent. Generation is deterministic, refuses every existing destination, and installs no dependencies. Client templates pin the TypeScript SDK package; until that package is published, repository development links the workspace package as shown by the template acceptance tests.
Repository layout
frontend/
python/
harness/
tests/
pyproject.toml
uv.lock
docs/specs/
docs/source-notes/
The distribution name is deepseek-harness-python; the only supported import root is harness inside the python/ workspace. There is no src/ tree or deepseek_harness compatibility package.
Implemented foundation
- PyCordis Services, isolated Realms, dependency-driven Fibers, reversible Effects, and Event modes.
- Append-only Session Events, scoped Prompt/Tool/LLM registries, and a multi-Step Agent Loop.
- Dynamic backend-only, client-only, and full-stack plugin install, enable, update, rollback, disable, and uninstall.
- Content-addressed client publication, normative Browser Bridge Schema, RPC, Event forwarding, cancellation, and stale-message rejection.
- aiohttp HTTP/WebSocket transport and a real Cordis TS browser adapter with SHA-256 verification and Fiber cleanup.
- Runnable Host assembly with catalog activation, browser bootstrap delivery, startup rollback, and deterministic shutdown.
- Real Chromium coverage for full-stack activation, RPC, bidirectional Events, update, stale-call rejection, disable, and teardown.
- Python and TypeScript authoring SDKs with immutable direction-safe descriptors, injected identity, lifecycle-owned registrations, and in-memory test harnesses.
- Deterministic backend-only, client-only, and full-stack scaffolding with atomic no-overwrite generation and runtime validation.
- Multi-page readiness aggregation with
all_connectedandany_connectedquorum, connection-generation fencing, structured diagnostics, recovery, and disable drainage. - A DeepSeek-compatible streaming provider adapter, FIFO Session invocation service, cancellable Host API, and HTTP invocation CLI.
- A responsive browser chat surface backed by DeepSeek-compatible Chat Completions JSON and SSE routes.
See implementation progress, the productization roadmap, and the foundation completion specification for acceptance evidence and intentional exclusions.
Run the Host
Build the browser runtime, then point the Host at one or more catalog directories whose immediate children contain plugin.toml:
pnpm --dir frontend install
pnpm --dir frontend run build:browser
uv --directory python run deepseek-harness-python \
--port 0 \
--plugins ./plugins \
--client-quorum all_connected \
--client-quorum-override com.example.preview=any_connected \
--browser-runtime ../frontend/dist/browser.js
The command prints the effective URL. --plugins is repeatable, and uv --directory python run python -m harness accepts the same arguments. Omit --browser-runtime for a backend-only Host without the bootstrap routes.
To activate the built-in DeepSeek-compatible route, provide the credential through the environment and configure an exact provider/model pair:
export DEEPSEEK_API_KEY='...'
uv --directory python run deepseek-harness-python \
--llm-provider deepseek \
--llm-model deepseek-chat \
--port 8765
uv --directory python run deepseek-harness-python invoke \
--url http://127.0.0.1:8765 \
'Reply with one short sentence.'
The provider consumes SSE internally so raw chunks remain in the Session log, while the invocation API returns only the terminal Assistant message. Turns for the process-lifetime Session run in FIFO order. The API key is read only when provider activation is requested; the invoke command never reads or sends it directly.
For a product-style local run, persist the Session Log and inspect its deterministic projection after restart:
uv --directory python run deepseek-harness-python \
--session-id default \
--session-db .data/sessions.sqlite \
--llm-provider deepseek \
--llm-model deepseek-chat \
--port 8765
curl http://127.0.0.1:8765/api/v1/sessions/default
SQLite persistence is optional. It stores the append-only event envelopes before they enter the in-memory snapshot; corrupt or incompatible state fails startup instead of being silently discarded.
The browser page uses the same Chat Completions contract as DeepSeek-compatible clients:
curl http://127.0.0.1:8765/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"Hello"}],"stream":false}'
The /v1/chat/completions alias is also available. The page renders the active Session projection and keeps the API key on the Host process.
Enable the loopback Plugin Control API when you need live lifecycle operations. The API is disabled by default and refuses non-loopback listeners:
uv --directory python run deepseek-harness-python --control --plugins ./plugins --port 8765
uv --directory python run deepseek-harness-python plugin --url http://127.0.0.1:8765 list
uv --directory python run deepseek-harness-python plugin --url http://127.0.0.1:8765 enable com.example.echo
uv --directory python run deepseek-harness-python plugin --url http://127.0.0.1:8765 update com.example.echo
Catalog watching is opt-in and uses the same serialized lifecycle coordinator as HTTP operations. A watcher can install new roots, hot-update valid revisions, and apply explicit create/delete policies:
uv --directory python run deepseek-harness-python \
--control \
--plugins ./plugins \
--watch-plugins ./plugins \
--watch-debounce 0.5 \
--watch-create install_disabled \
--watch-delete disable
The control API is intended for trusted local development. It has no authentication, package download, dependency installation, signatures, or untrusted-code isolation. Use uv --directory python run deepseek-harness-plugin sdk export PATH to copy the bundled Browser SDK tarball; client scaffolds vendor that exact digest with a relative file: dependency and a frozen lockfile.
Development
uv --directory python sync
uv --directory python run playwright install chromium
uv --directory python run python -m unittest discover -s tests -v
uv --directory python run ruff check harness tests
uv --directory python run pyright
pnpm --dir frontend install
pnpm --dir frontend run typecheck
pnpm --dir frontend run test
pnpm --dir frontend run build
The current in-process Python Backend Host is for trusted local plugins. Authentication, package distribution, persistent inventory and Sessions, dependency installation, signatures, and process isolation for untrusted plugins remain product or deployment work. The current Agent Session is memory-only and does not claim restart recovery. New product phases start with a normative specification under docs/specs/ and update implementation progress with executable evidence.
No comments yet. Be the first to write one.