What Is the Core Architecture of DeepSeek-Reasonix? A Deep Dive into the Agent Framework
DeepSeek-Reasonix is a config- and plugin-driven coding agent built in Go that uses registry-based abstractions for providers, tools, and plugins, with a core execution loop that streams LLM completions, executes tool calls, and optionally coordinates between two models for planning and execution.
The DeepSeek-Reasonix project provides a lean, extensible framework for LLM-driven coding workflows. Written primarily in Go standard library, the architecture emphasizes modularity through registration-based registries that allow providers and tools to self-register without core code modifications.
Overview of the Layered Architecture
The DeepSeek-Reasonix core architecture consists of eight distinct layers, each responsible for specific concerns in the agent lifecycle. These layers communicate through well-defined interfaces rather than concrete implementations, enabling the system to remain agnostic to specific LLM providers or tool implementations.
The architecture follows this execution flow:
- Startup – The CLI in
cmd/reasonix/main.goparsesreasonix.toml, initializes the provider registry, and builds the tool registry. - Session creation – A
Sessionobject holds a slice ofMessagestructs, beginning with the system prompt from configuration. - Model streaming – The
Provider.Streammethod yieldsChunkstructs containing text, tool calls, or errors. - Tool execution – Incoming
ChunkToolCallvalues triggerTool.Executemethods after permission checks. - Loop continuation – Tool results append to the message history, and the request repeats until receiving
ChunkDoneor hitting step limits.
The Provider Registry: Abstracting LLM Endpoints
The Provider Registry (internal/provider/provider.go) abstracts any OpenAI-compatible or Anthropic-style LLM endpoint through a minimal interface. Providers self-register via init() functions, making the core completely unaware of concrete implementations until runtime.
The registry defines three key components:
Providerinterface – The contract for streaming completions and handling model-specific formatting.Factory– Creates provider instances from configuration blocks.RegisterandNew– Functions that populate the registry and instantiate providers by name.
In internal/provider/openai/openai.go, the OpenAI-compatible implementation (used for DeepSeek endpoints) parses configuration like this:
[[providers]]
name = "deepseek"
kind = "openai"
base_url = "https://api.deepseek.com"
models = ["deepseek-v4-flash", "deepseek-v4-pro"]
default = "deepseek-v4-flash"
api_key_env = "DEEPSEEK_API_KEY"
context_window = 1000000
When the program starts, the openai provider factory produces a provider instance capable of streaming Chunk values to the agent loop.
The Tool Registry and Plugin System
The Tool Registry (internal/tool/tool.go) manages both built-in file-system tools and external MCP (Model Context Protocol) plugins. Tools implement the Tool interface and register via RegisterBuiltin, while the Builtins map provides access to standard operations like read_file and write_file.
The Plugin System (internal/plugin/plugin.go and internal/plugin/transport.go) extends tooling through external processes. Plugins defined in reasonix.toml launch as stdio or HTTP subprocesses, exposing tools via JSON-RPC according to the MCP protocol:
[[plugins]]
name = "example"
command = "reasonix-plugin-example"
args = []
The plugin's advertised tools automatically adapt to the Tool interface, allowing the agent to invoke example_tool identically to built-in operations.
The Agent Loop: Core Execution Engine
The Agent Loop (internal/agent/agent.go) serves as the central execution engine. It coordinates between the provider streaming interface and the tool registry through a stateful Session struct.
Key abstractions in this layer include:
Session– Maintains conversation history and tool schemas.Run– The main execution method that handles the request-response cycle.Chunk– A discriminated union type representing text deltas, tool calls, errors, or completion signals.
When the provider returns a ChunkToolCall, the loop dispatches to the corresponding Tool.Execute method, appends the result as a new message, and continues the conversation.
Two-Model Collaboration with the Coordinator
When configuration specifies a planner_model distinct from the executor, the Coordinator (internal/agent/coordinator.go) manages two isolated sessions:
- Planner session – Runs the high-capability model to generate a structured execution plan.
- Executor session – Receives the plan as context and handles implementation details.
This separation preserves each model's cache-stable prefix while allowing specialized reasoning models to guide more efficient executors. The coordinator passes structured plans between sessions via RunPlanner and RunExecutor methods.
Context Management and Token Optimization
The Context Management layer (internal/agent/compact.go) monitors token utilization through a configurable compactRatio. When the conversation window exceeds this threshold, the compact.go module folds older assistant and tool messages into concise summaries while preserving user turns verbatim.
This compaction strategy maintains conversation coherence without hitting context window limits, crucial for long-running coding sessions with extensive tool outputs.
Permission Layer and Security
The Permission Layer (internal/permission/decision.go and internal/permission/policy.go) implements fine-grained access control through policy definitions. Before executing any tool call, the system evaluates a Decision against the configured Policy through a Gate construct.
Policies support three enforcement levels per tool:
- Allow – Execute immediately without confirmation.
- Ask – Prompt for interactive approval (integrates with the TUI).
- Deny – Block execution unconditionally.
Slash Commands and User Interface
The Slash-Command System (internal/command/command.go) parses /command and @ references, dispatching to custom markdown commands stored in .reasonix/commands/. These commands support argument interpolation and resolve local file references or MCP resources.
The Desktop UI (desktop/frontend/src/components/Composer.tsx) provides a Bubble Tea-based terminal interface featuring:
- Autocomplete menus for
@file references and/commands. - Modal overlays for permission decisions.
- Real-time streaming of LLM responses.
Summary
- Registry-based design – Providers and tools self-register via
init(), keeping the core agnostic to implementations. - Minimal dependencies – Built primarily with Go standard library for a single-binary deployment.
- Pluggable LLM support – The
Providerinterface ininternal/provider/provider.goabstracts any OpenAI-compatible or Anthropic endpoint. - MCP-compatible plugin system – External tools integrate via JSON-RPC without core code changes.
- Two-model coordination – Optional
Coordinatorseparates planning from execution when configured with distinctplanner_modelvalues. - Automatic context compaction – Token monitoring with configurable
compactRatioprevents context window exhaustion. - Fine-grained permissions – Per-tool policy enforcement with interactive approval workflows.
Frequently Asked Questions
How does DeepSeek-Reasonix handle different LLM providers without code changes?
The framework uses a registry pattern where providers implement the Provider interface and register themselves via init() functions in internal/provider/provider.go. Adding a new model requires only updating reasonix.toml with the endpoint configuration, as the concrete implementation (e.g., internal/provider/openai/openai.go) handles the protocol-specific details.
What is the difference between built-in tools and MCP plugins?
Built-in tools (registered via RegisterBuiltin in internal/tool/tool.go) are compiled into the binary and include file-system operations. MCP plugins (defined in internal/plugin/plugin.go) run as external processes communicating via JSON-RPC, allowing integration with tools written in any language without recompiling Reasonix.
How does the two-model collaboration feature work?
The Coordinator in internal/agent/coordinator.go creates two isolated Session instances when planner_model differs from the default executor. It first runs RunPlanner to generate a structured plan, then injects that plan as context into RunExecutor. This preserves each model's conversation cache while leveraging specialized capabilities for different reasoning phases.
Can I customize the permission policies for specific tools?
Yes. The Permission Layer (internal/permission/policy.go) supports per-tool configuration with allow, ask, and deny policies. When a tool call arrives, the Gate evaluates the Decision against the active policy, enabling interactive approvals for destructive operations like write_file while allowing automatic execution of read-only tools.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →