> your AI agent picks dependencies from memory; give it dated facts — try starlog.dev ↗ vet your agent's deps ↗ vibe-coding is fine. vibe-importing isn’t. — try starlog.dev ↗ vibe-importing isn’t fine ↗ your agent has never seen your private packages — try starlog.dev ↗ facts for private packages ↗ a linter for the dependencies your AI agent picks — try starlog.dev ↗ a linter for agent deps ↗ whois is redacted, cdns mask the rest — get the real operator — try whoisgeni.us ↗ who really runs that domain ↗ domain attribution that shows its work — full evidence chain — try whoisgeni.us ↗ domain intel w/ evidence ↗

← Back to Articles

DeepSeek Harness: Hot-Swappable AI Agents Through Dependency Injection

[ View on GitHub ]

DeepSeek Harness: Hot-Swappable AI Agents Through Dependency Injection

Hook

What if you could swap your agent's LLM mid-conversation, replace its retrieval backend without restarting, or inject new tools into a running workflow—all while preserving state? DeepSeek Harness makes this possible through an architecture that treats everything, including the runtime itself, as a hot-swappable plugin.

Context

Traditional agent frameworks like LangChain and LangGraph compile your agent workflows into static execution graphs. You define your chains, configure your tools, wire up your LLM calls, and deploy. Need to change something? Rebuild, redeploy, and lose all conversation state. This works fine for stateless request-response patterns, but it breaks down for long-running agents—research assistants that maintain context across hours, autonomous systems that evolve their capabilities, or production deployments where you need to A/B test different reasoning strategies without downtime.

DeepSeek Harness emerged from DeepSeek's internal need to build compositional agent systems for their R1-style reasoning models. Instead of configuring an agent runtime, you compose the runtime itself from plugins. Built atop Cordis—a dependency injection framework designed for hot-swapping components—it implements what the academic literature calls 'spatiotemporal composability': plugins maintain spatial isolation (separate dependency graphs) while providing temporal guarantees (deterministic startup and shutdown ordering). With 148K GitHub stars, this represents a frontier lab's answer to the fundamental question: how do you build agent infrastructure that's as dynamic as the agents themselves?

Technical Insight

Load/Unload Plugins

Register Services

Dependency Injection

Dependency Injection

Dependency Injection

Provide 'llm' Service

Provide 'retriever' Service

Emit Events

agent:query

Consume 'retriever'

Topological Init/Dispose

Web UI :3080

Plugin Registry

Cordis DI Container

Plugin: LLM Provider

Plugin: Retriever

Plugin: Agent

Event Bus

System architecture — auto-generated

At its core, DeepSeek Harness inverts the typical agent framework pattern. Rather than instantiating a framework that hosts your agent code, you instantiate plugins that collectively become the framework. Cordis manages a plugin registry where each plugin declares services it provides and dependencies it consumes. When you load a plugin, Cordis analyzes the dependency graph, initializes components in topological order, and wires service references automatically. When you unload a plugin, it traverses the graph in reverse, disposing dependents before dependencies.

Here's what a minimal plugin looks like:

import { Context, Schema } from 'cordis'

export const name = 'llm-provider'

export interface Config {
  apiKey: string
  model: string
}

export const Config: Schema<Config> = Schema.object({
  apiKey: Schema.string().required(),
  model: Schema.string().default('deepseek-chat')
})

export function apply(ctx: Context, config: Config) {
  // Provide a service to the plugin ecosystem
  ctx.provide('llm', {
    async complete(prompt: string) {
      // Implementation using config.apiKey and config.model
      return callDeepSeekAPI(prompt, config)
    }
  })

  // Consume services from other plugins
  ctx.on('agent:query', async (query) => {
    const retriever = ctx.get('retriever')
    const context = await retriever.search(query)
    const llm = ctx.get('llm')
    return llm.complete(`Context: ${context}\n\nQuery: ${query}`)
  })

  // Cleanup on plugin disposal
  ctx.on('dispose', () => {
    // Close connections, release resources
  })
}

The magic happens in ctx.provide() and ctx.get(). When this LLM provider plugin loads, it registers a service named 'llm' in the global registry. Other plugins can consume this service without knowing which concrete implementation provides it. You could swap this DeepSeek provider for an OpenAI provider, Anthropic provider, or a local llama.cpp provider—as long as they expose the same service interface, dependent plugins continue working without modification.

The spatiotemporal composability becomes critical when you're hot-swapping components. Imagine you're running an agent conversation and want to switch from DeepSeek to GPT-4 for testing. In a traditional framework, you'd kill the process, update configuration, restart, and lose all conversation history. With DeepSeek Harness:

// Unload the DeepSeek provider
await harness.unloadPlugin('llm-provider-deepseek')

// Load the OpenAI provider
await harness.loadPlugin('llm-provider-openai', {
  apiKey: process.env.OPENAI_KEY,
  model: 'gpt-4'
})

// Conversation state persists, next query uses new LLM

Cordis handles the complexity: it stops routing events to the old plugin, waits for in-flight operations to complete, disposes the DeepSeek provider's resources, initializes the OpenAI provider, and registers its 'llm' service. Plugins that depend on 'llm' don't restart—they simply receive references to the new implementation. The dependency graph updates atomically.

The Web UI at localhost:3080 exposes this plugin orchestration visually. You can browse available plugins, inspect their dependency relationships, configure service parameters through generated forms (using those Schema definitions), and hot-reload components through a GUI rather than code. This positions DeepSeek Harness as tooling for interactive agent development—you're building and debugging agents in a live REPL-like environment rather than treating them as compiled artifacts.

The event-driven communication model means plugins coordinate through messages rather than direct calls. When an agent receives a query, it emits an agent:query event. Plugins that registered listeners for this event respond, potentially emitting their own events that trigger cascading workflows. This decouples plugins temporally—they don't need to exist simultaneously for workflows to be defined—and enables sophisticated patterns like middleware chains, event replay for debugging, and conditional plugin loading based on runtime context.

Gotcha

The architectural elegance comes with sharp edges that make production adoption risky. DeepSeek Harness is explicitly marked as a developer preview with breaking changes expected, and that's not defensive legal language—it's a genuine warning. Cordis itself is relatively obscure outside this project, with limited Stack Overflow coverage and few production battle stories. If you hit a bug in the dependency injection layer or encounter edge cases in plugin lifecycle management, you're debugging novel infrastructure without a community safety net.

The TypeScript-only implementation creates a painful barrier for the Python-dominant ML community. There's no foreign function interface for writing plugins in Python, no bindings for calling PyTorch models directly, and no obvious path to integrate with the Transformers ecosystem that most practitioners live in. You're either rewriting your Python agent code in TypeScript or building awkward HTTP bridges between Node.js plugins and Python services. For a tool targeting AI agent development, being TypeScript-exclusive fragments it from where 80% of ML practitioners actually work. The documentation situation compounds this—the README truncates quickly with pointers to external Cordis docs and academic papers. There are no cookbook recipes, no example agent implementations, and no clear migration path from existing frameworks. You're expected to read the spatiotemporal composability paper to understand the programming model, a steep ask when competing frameworks have 'get started in 5 minutes' tutorials.

Verdict

Use if: You're building research-grade agent systems where runtime flexibility trumps ecosystem maturity—swapping reasoning strategies mid-execution, composing heterogeneous toolchains dynamically, or developing agents that evolve their capabilities without restarts. This is valuable for agent infrastructure teams at labs or companies building custom agent platforms where hot-reloading and compositional architecture justify the TypeScript investment and the risk of debugging immature tooling. Skip if: You're shipping production agents in Python, need battle-tested stability with semver guarantees, want rich integrations with the ML ecosystem (LangChain's 700+ connectors, AutoGPT's plugin marketplace), or require enterprise features like multi-tenant deployments and observability out of the box. For most teams, LangChain provides better ecosystem support, CrewAI offers simpler Python-native patterns, and Temporal delivers production-grade orchestration without the Cordis learning curve. DeepSeek Harness is DeepSeek's internal tooling open-sourced early—powerful if you need exactly what it provides, but premature for general adoption.