cd /news/artificial-intelligence/deepseek-harness-cordis-and-the-case… Β· home β€Ί topics β€Ί artificial-intelligence β€Ί article
[ARTICLE Β· art-96545] src=kondasamy.com β†— pub= topic=artificial-intelligence verified=true sentiment=Β· neutral

DeepSeek Harness, Cordis, and the Case for Spatiotemporal Agent Architectures

DeepSeek AI and Peking University published a paper formalizing spatiotemporal composability for agent architectures, introducing the Cordis micro-kernel that powers DeepSeek Harness (dsh). The Cordis kernel, an open-source TypeScript engine, treats models, tools, sandboxes, session stores, and the agent loop as hot-swappable plugins, with revertible effects ensuring clean unloads. Cordis has run in production for four years in the Koishi chatbot ecosystem with over 4,000 community plugins.

read9 min views1 publishedAug 14, 2026
DeepSeek Harness, Cordis, and the Case for Spatiotemporal Agent Architectures
Image: Kondasamy (auto-discovered)

On this page #

DeepSeek AI and Peking University formalized agent modularity in a recent paper on spatiotemporal composability. Here is an engineering look at the Cordis kernel, revertible effects, and what this pattern means for self-modifying agents.

Most agent frameworks claim they are modular. In practice, they offer surface-level customization.

They give you a tool registry, a prompt template, and a model router. Then they hardcode the execution loop, the session state, the sandbox runtime, and the user interface into a fixed core. If you want to change how the loop handles retries, swap the session storage engine, or replace the sandbox environment, you end up forking the repository or hacking internal classes.

When DeepSeek released DeepSeek Harness (dsh

), they took a different approach. Alongside the codebase, DeepSeek AI and Peking University published a research paper: A Programming Paradigm for Spatiotemporal Composability.

The paper formalizes the architecture behind Cordis, the open-source TypeScript micro-kernel underneath DeepSeek Harness. Instead of building a monolithic agent runtime with hooks, they built an engine where models, tools, sandboxes, session stores, and even the agent loop itself are hot-swappable plugins.

%%{init: {"layout": "dagre"}}%%
flowchart TD
    subgraph Monolith["Typical Agent Framework (Fixed Core)"]
        M1[Hardcoded Agent Loop] --> M2[Built-in Session State]
        M1 --> M3[Built-in Terminal UI]
        M1 --> M4[Hardwired Sandbox]
        M1 -.->|Only customizable layer| M5[Custom Tools & Prompts]
    end

    subgraph CordisHarness["DeepSeek Harness on Cordis (Micro-Kernel)"]
        K[Cordis Kernel: Context + Events + Lifecycle]
        K --- P1["ctx.llm: Model Adapter"]
        K --- P2["ctx.agentLoop: Agent Driver"]
        K --- P3["ctx.sessions: Append-Only Log"]
        K --- P4["ctx.sandbox: Container / MicroVM"]
        K --- P5["ctx.tools: Tool Registry & MCP"]
        K --- P6["ctx.agents: Live Agent Registry"]
    end

This design did not start in the AI lab. Cordis ran in production for four years powering the Koishi chatbot ecosystem across more than 4,000 community plugins before DeepSeek applied it to agent harnesses.

I am still reading through the paper myself, working through the formal theory of effects and coeffects. Rather than declaring this pattern superior to simpler agent loops, let us examine how the mechanics work, what trade-offs they introduce, and what we can learn from this direction.

The Theory: Spatial and Temporal Composability #

The core argument of the DeepSeek and Peking University paper is that dynamic software systems fail at composability in two distinct dimensions: time and space.

%%{init: {"layout": "dagre"}}%%
flowchart LR
    subgraph Spatial["Spatial Composability (Coeffects)"]
        A[Plugin declares required services] --> B[Cordis resolves DAG]
        B --> C[Plugin activates only when context is ready]
    end

    subgraph Temporal["Temporal Composability (Revertible Effects)"]
        D[Plugin executes side effect] --> E[Runtime tracks inverse action]
        E --> F[Plugin unloads: effect unwinds with zero leftovers]
    end

1. Temporal Composability via Revertible Effects

In standard software, installing a capability is easy; removing it cleanly is hard. When you disable a plugin, it often leaves active interval timers, dangling event listeners, open network sockets, or stale prompt injections in memory.

The paper formalizes revertible effects: every transformation applied to the shared execution context must have a mathematically defined inverse that the runtime tracks. When a plugin unloads, the runtime executes that inverse.

import { Context, Service } from 'cordis'

export class MonitoringService extends Service {
  constructor(ctx: Context) {
    super(ctx, 'monitoring', true)
  }

  protected start() {
    // Revertible effect: the returned closure is the tracked inverse
    this.ctx.effect(() => {
      const timer = setInterval(() => this.collectMetrics(), 10000)
      return () => clearInterval(timer)
    })

    // Event listener: automatically unbound on plugin unload
    this.ctx.on('tool/execute', (event) => {
      this.recordLatency(event)
    })
  }
}

When this plugin unloads, Cordis runs the cleanup closure and unbinds the event listener. The process returns to its exact prior state.

2. Spatial Composability via Reactive Coeffects

In type theory, effects describe what a program produces (e.g. logs, network calls, state mutations). Coeffects describe what a program requires from its environment to execute (e.g. specific services, configurations, credentials).

Cordis treats plugin dependencies as reactive coeffects. A plugin declares what it demands:

export class ToolExecutionPlugin extends Service {
  // Coeffect requirements: requires both ctx.tools and ctx.sandbox
  static inject = ['tools', 'sandbox']

  constructor(ctx: Context) {
    super(ctx, 'toolExecution', true)
  }
}

Cordis monitors the context tree. When ctx.tools

and ctx.sandbox

become available, the plugin activates automatically. If the sandbox plugin crashes or unloads, downstream plugins or deactivate until the dependency returns. There is no manual boot order to configure.

How DeepSeek Harness Implements the Model #

In DeepSeek Harness, the Cordis kernel contains zero AI logic. It does not know what an LLM token is. Instead, it exposes a typed Context

where packages register services and listen to events.

Package Responsibility Context Key
core/session Append-only SessionEvent log and store ctx.sessions
core/system-prompt Dynamic prompt-section and tool-schema assembly ctx.systemPrompt
core/tools Scoped tool registry and guarded execution pipeline ctx.tools
core/agent Live agent registry and lifecycle events ctx.agents
core/agent-loop Default execution driver implementing step turns ctx.agentLoop
llm/llm Model stream abstraction and provider adapters ctx.llm
core/sandbox Process isolation, container, and microVM boundaries ctx.sandbox

Four Typed Dispatch Modes

Communication across plugins relies on an event bus with four explicit dispatch modes:

Mode Awaited? Execution Order Return Value? Behavioral Semantic
emit No Registration order No Fire-and-forget notifications (telemetry, background logging).
waterfall No Around-middleware chain Yes Interception middleware ((...args, next) ). Can mutate, delegate, or short-circuit.
parallel Yes Concurrent (Promise.all ) No Awaited broadcast across independent listeners.
serial Yes Registration order Yes Decisive sequential gates (e.g. agent/turn-stopping ).

The waterfall mode allows plugins to wrap core decisions:

// Intercepting prompt messages before the model sees them
ctx.waterfall('agent/pre-step', async (session, messages, next) => {
  if (violatesPolicy(messages)) {
    // Short-circuit: stop the turn before calling the model
    return { status: 'rejected', reason: 'Blocked by policy' }
  }
  const sanitized = sanitize(messages)
  return next(session, sanitized)
})

The Turn and Step Lifecycle #

DeepSeek Harness defines a structured execution pipeline:

turn/start
  β”‚
  β”œβ”€ Claim queued input from inbox
  β”œβ”€ Assemble prompt sections + tool schemas (ctx.systemPrompt)
  β”‚
  β”œβ”€β–Ί agent/pre-step (waterfall) ──► [reject / enter(messages)]
  β”‚     └─ If rejected: close turn immediately (0 steps spent, logged)
  β”‚
  β”œβ”€β–Ί step/start
  β”‚     β”œβ”€ Append entered messages to session log as user/message
  β”‚     β”œβ”€ deriveMessages(): Project model history from the immutable log
  β”‚     β”œβ”€ agent/request (waterfall)
  β”‚     β”œβ”€ llm/stream (waterfall) ──► assistant/chunk* ──► assistant/message
  β”‚     β”œβ”€ tool/call* ──► tools/pre-execute ──► tools/execute ──► tools/post-execute ──► tool/result*
  β”‚     └─ step/end
  β”‚
  β”œβ”€ Check continuation: tools owe another request OR queued input arrived?
  β”‚     β”œβ”€ If YES: jump back to step/start (next step)
  β”‚     └─ If NO: proceed
  β”‚
  β”œβ”€β–Ί agent/turn-stopping (serial gate)
turn/end

Capability Seams and Append-Only Logs #

Two additional engineering choices stand out in the architecture:

1. Capability Seams

A seam separates a Service Definition (interface), a Service Provider (implementation), and Consumers (tools).

Because file access (ctx.fs

), subprocess execution (ctx.subprocess

), and terminals (ctx.terminals

) share a common seam, changing the provider from local Node.js to a remote microVM moves all tools, file reads, and language servers into the container simultaneously. Consumer code remains untouched.

2. β€œModel-Visible Means Logged”

The harness enforces an invariant: anything that reaches the LLM must be reconstructable from the append-only event log.

  • The runtime does not mutate an in-memory chat array. The deriveMessages()

function computes context directly from immutableSessionEvent

records. - Sub-agents branch cleanly via ctx.sessions.fork(parentSessionId, boundaryEventId)

without cloning process heaps. - Deterministic replay allows developers to step through historical execution runs event by event.

Why This Pattern Matters: The Self-Modifying Agent #

Why go through the trouble of building formal spatiotemporal composability into an AI agent harness?

The most compelling answer is runtime self-modification.

In a traditional agent framework, if an agent writes a new tool or scripts an integration during a long-running task, it cannot mount that tool without restarting its process. Restarting wipes ephemeral memory, drops open network sessions, and resets execution state.

Under Cordis:

  • The agent writes a new TypeScript tool plugin.
  • The harness loads the plugin into the live context at runtime.
  • Cordis checks the plugin’s coeffects, mounts the tool, and automatically updates the system prompt assembly for the next step.
  • If the tool fails or finishes its purpose, the agent unloads the plugin. Cordis unwinds the effect tree with zero leftover memory or socket leaks.

The agent modifies its own runtime in-flight while preserving active session history.

Open Questions and Engineering Trade-Offs #

While the architecture is elegant on paper, it introduces real trade-offs that teams should weigh:

Dimension Monolithic Loop (e.g. Pi / Minimalist Harness) Spatiotemporal Micro-Kernel (Cordis / dsh)
Conceptual overhead Low: read one linear loop file High: understand contexts, seams, and dispatch modes
Debuggability Simple stack traces and breakpoints Non-linear event graphs across waterfall chains
Dynamic safety Compile-time static guarantees Runtime dependency resolution in TypeScript
Extensibility Fork or subclass internal code Declarative plugin mounting via config patches
Self-modification Difficult without process restart Native support for in-flight tool mounting and unwinding

Three practical questions remain as this pattern encounters production adoption:

Debugging Indirection: When behavior is distributed across multiple waterfall listeners, tracing why a prompt was altered or a tool call was rejected requires dedicated event-graph tooling.Language Boundaries: Cordis is written in TypeScript. Bringing this level of dynamic effect unwinding to environments like Python or Rust requires different runtime primitives (e.g. explicit RAII guards or actor systems).Complexity Budget: For focused coding agents with fixed tool sets, a 200-line linear loop like HuggingFace’s Tau remains significantly easier to audit and reason about.

The Bottom Line #

DeepSeek Harness and the Cordis paper represent a deliberate shift in agent system design: treating agent harnesses not as static scripts around an LLM API, but as dynamic operating systems for hot-swappable capabilities.

I am still working my way through the mathematical details and operational calculus in the paper. We do not need to rush to declare this architecture superior or inferior to simpler, linear agent loops. Instead, we should wait and watch where these patterns head: whether dynamic plugin trees become the standard foundation for self-modifying agents, or if linear simplicity remains the preferred choice for production stability.

For now, the paper gives us a clear vocabulary for understanding what true modularity in agent runtimes requires.

Observing how agent architectures evolve, or experimenting with plugin runtimes for autonomous systems? I would love to hear your perspective. Reach out on LinkedIn.

── more in #artificial-intelligence 4 stories Β· sorted by recency
── more on @deepseek ai 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/deepseek-harness-cor…] indexed:0 read:9min 2026-08-14 Β· β€”