Building a Mini DeepSeek Agent Runtime from Scratch with Cordis
Cordis's "everything is a plugin" model turns agent runtimes into composable assemblies where tools, prompts, and logging are independently swappable modules rather than hardcoded features. For developers building or customizing AI agents, this architecture means adding a new tool or modifying the system prompt requires writing a new plugin, not refactoring a monolith.
The tutorial constructs a mini version of the DeepSeek Harness runtime using the Cordis framework, where every capability—from LLM calling to tool execution—is an independent plugin. It starts with a single "hello world" plugin and progressively adds a chat service, a tool registry, and three concrete tools (bash, fetch, file search) that register themselves via dependency injection. A prompt plugin demonstrates how to modify system instructions through waterfall events without touching agent code, and a tracer plugin logs tool calls by listening to broadcast events, showing how observability can be added without coupling.
The Agent loop itself is a service that builds its prompt from an event chain, calls the model, parses JSON tool-call responses, executes tools, and feeds results back until a final answer is reached. The entire harness is assembled by mounting eight plugins in a flat list; startup order is derived automatically from declared dependencies. The piece closes by contrasting Cordis's lifecycle-level plugin model with Express's request-level middleware, and honestly catalogs what the mini version still lacks compared to the production Harness—streaming, conversation memory, native function calling, and security governance.
The tutorial's design choice to use a text JSON protocol instead of native function calling is a deliberate trade-off: it makes the mechanism transparent and debuggable, but the author openly notes the model sometimes mixes reasoning text with JSON, revealing the fragility of hand-rolled parsing in agent loops.
Cordis's two-layer middleware model—lifecycle-level plugins and dispatch-level event chains—is a useful mental model for understanding why the framework feels like Express but operates at a fundamentally different scope.
The pattern of returning tool errors as strings to the model rather than throwing exceptions is a practical design choice that treats the model as a decision-maker capable of recovering from failures, rather than a brittle pipeline that crashes on any misstep.