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:

  1. Startup – The CLI in cmd/reasonix/main.go parses reasonix.toml, initializes the provider registry, and builds the tool registry.
  2. Session creation – A Session object holds a slice of Message structs, beginning with the system prompt from configuration.
  3. Model streaming – The Provider.Stream method yields Chunk structs containing text, tool calls, or errors.
  4. Tool execution – Incoming ChunkToolCall values trigger Tool.Execute methods after permission checks.
  5. Loop continuation – Tool results append to the message history, and the request repeats until receiving ChunkDone or 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:

  • Provider interface – The contract for streaming completions and handling model-specific formatting.
  • Factory – Creates provider instances from configuration blocks.
  • Register and New – 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:

  1. Planner session – Runs the high-capability model to generate a structured execution plan.
  2. 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 Provider interface in internal/provider/provider.go abstracts any OpenAI-compatible or Anthropic endpoint.
  • MCP-compatible plugin system – External tools integrate via JSON-RPC without core code changes.
  • Two-model coordination – Optional Coordinator separates planning from execution when configured with distinct planner_model values.
  • Automatic context compaction – Token monitoring with configurable compactRatio prevents 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →