Core Components of DeepSeek-Reasonix: A Modular Go-Based Coding Agent Framework

DeepSeek-Reasonix is a Go-based coding agent framework built around a modular architecture comprising Providers, Tools, Plugins, Agents, Coordinators, Permissions, and Commands that enable safe, extensible LLM-driven automation.

The esengine/DeepSeek-Reasonix repository implements a highly modular coding agent where core functionality is deliberately split into thin, interchangeable components. This design allows developers to swap LLM vendors, add new capabilities, or modify safety policies without modifying the core engine. The architecture follows a registry pattern that wires together ten primary building blocks to create a plug-and-play automation platform.

Provider: The LLM Abstraction Layer

The Provider component abstracts individual LLM vendors behind a unified interface. Each provider implements the Provider interface defined in internal/provider/provider.go, which requires a Stream method that returns token deltas as a channel.

Providers are self-registered via init() functions using the provider.Register factory pattern. This allows the framework to support OpenAI-compatible APIs, Anthropic, and custom endpoints without hard-coded vendor logic.

// File: internal/provider/custom/custom.go
package custom

import (
    "context"
    "github.com/esengine/DeepSeek-Reasonix/internal/provider"
)

type SimpleProvider struct{ cfg provider.Config }

func (p *SimpleProvider) Name() string { return "custom" }

func (p *SimpleProvider) Stream(ctx context.Context, req provider.Request) (<-chan provider.Chunk, error) {
    // Implementation that streams tokens from your model
    return nil, nil
}

func init() {
    provider.Register("custom", func(cfg provider.Config) (provider.Provider, error) {
        return &SimpleProvider{cfg: cfg}, nil
    })
}

Tool: The Action Interface

Tools encapsulate any callable action within the Reasonix ecosystem, from file I/O to shell execution. The Tool interface in internal/tool/tool.go requires four methods: Name(), Description(), Schema(), and Execute().

Built-in tools reside under internal/tool/builtin, while external tools are injected through the plugin system. Tools declare their JSON Schema to enable LLM function calling, and their Execute method handles the actual operation.

// File: internal/tool/builtin/hello.go
package builtin

import (
    "context"
    "encoding/json"
    "github.com/esengine/DeepSeek-Reasonix/internal/tool"
)

type helloTool struct{}

func (t *helloTool) Name() string        { return "hello" }
func (t *helloTool) Description() string { return "Greets the user." }
func (t *helloTool) Schema() json.RawMessage {
    return json.RawMessage(`{"type":"object","properties":{}}`)
}
func (t *helloTool) Execute(_ context.Context, _ json.RawMessage) (string, error) {
    return "Hello, Reasonix user!", nil
}

func init() { tool.RegisterBuiltin(&helloTool{}) }

Plugin: Extending via MCP

The Plugin system enables out-of-process extensions using the Model Context Protocol (MCP) over JSON-RPC. Defined in internal/plugin/plugin.go, plugins can expose additional tools or prompts that run in isolated processes.

Plugins support multiple transport types including stdio, http, and sse, allowing Reasonix to integrate with remote tool servers or language-specific runtimes without embedding them in the main binary.

Agent: Session Orchestration

The Agent component manages a single LLM session from start to finish. Located in internal/agent/agent.go, the agent builds requests containing conversation history and available tool schemas, then streams responses via the configured provider.

When the LLM generates a ChunkToolCall, the agent:

  1. Looks up the tool in the registry
  2. Validates permissions through the Gate
  3. Executes the tool
  4. Feeds the result back into the conversation as a new message

This loop continues until the step limit is reached or the session completes naturally.

Coordinator: Two-Model Collaboration

The Coordinator implements advanced two-model collaboration patterns in internal/agent/coordinator.go. This component orchestrates a low-frequency planner model and a high-frequency executor model.

The planner runs in a read-only session to generate strategies, while the executor handles actual file modifications and tool execution. This separation keeps each model's prompt cache stable and reduces token costs for complex multi-step tasks.

Permission: Safety Gating

Permission rules enforce per-tool gating through the Gate interface in internal/permission/permission.go. Each tool can be configured with allow, ask, or deny policies.

Before any tool executes, the permission engine evaluates configured rules against the current context. This ensures safe autonomous operation by requiring explicit approval for destructive operations while permitting safe actions to run unattended.

Command: Interactive Controls

The Command system handles slash-commands entered through the TUI. Defined in internal/command/command.go, commands can be:

  • Built-in: Native commands like /new and /clear
  • Custom: Markdown files stored in .reasonix/commands/
  • MCP Prompts: Remote prompts accessed via /mcp__ prefix

This architecture allows teams to extend the CLI interface without rebuilding the binary.

Configuration and Data Types

Reasonix uses a TOML-based configuration system centered on reasonix.example.toml. Configuration resolution follows a strict hierarchy: CLI flags override project reasonix.toml, which overrides user config, which overrides defaults.

Core data types including Message, Chunk, Request, and ChunkToolCall drive the streaming protocol between agents and providers. These structures are defined in internal/provider/provider.go and enable type-safe communication across the modular boundary.

CLI and Registry Wiring

The CLI entry point in cmd/reasonix/main.go initializes the entire system through the registry pattern. At startup:

  1. The CLI parses TOML configuration
  2. Provider factories register via provider.Register
  3. Built-in tools register via tool.RegisterBuiltin
  4. Plugins initialize their MCP connections
  5. internal/agent.NewRunner constructs a *Registry containing enabled tools and plugins

# Use the default DeepSeek provider configured in reasonix.example.toml

$ reasonix run "Write a Python function that computes Fibonacci numbers."

When running, the agent automatically invokes suggested tools (e.g., write_file, bash) and streams output to the terminal.

Summary

  • DeepSeek-Reasonix exposes ten core components that interact via a registry pattern to enable modular LLM automation.
  • Providers abstract LLM vendors through a streaming interface in internal/provider/provider.go.
  • Tools implement the Tool interface in internal/tool/tool.go to expose callable actions.
  • Plugins extend functionality via MCP/JSON-RPC in internal/plugin/plugin.go.
  • Agents orchestrate sessions while Coordinators manage two-model collaboration in internal/agent/.
  • Permissions enforce safety gates before tool execution in internal/permission/permission.go.
  • Commands provide interactive extensibility through the TUI in internal/command/command.go.
  • Configuration flows from CLI flags → project file → user config → defaults, enabling flexible deployment.

Frequently Asked Questions

What is the registry pattern in DeepSeek-Reasonix?

The registry pattern is the central wiring mechanism that connects components at runtime. Providers register their factories via provider.Register in init() functions, while tools register via tool.RegisterBuiltin. When the CLI starts in cmd/reasonix/main.go, it constructs a *Registry instance that contains all enabled providers, tools, and plugins, allowing the agent to look up capabilities by name without hard-coded dependencies.

How does the two-model Coordinator improve performance?

The Coordinator in internal/agent/coordinator.go separates planning from execution by running two distinct models. A low-frequency planner model generates strategies in a read-only session, preserving its prompt cache. The executor model then handles actual file modifications and tool calls. This prevents the executor from evicting the planner's cached context, reducing token costs and maintaining coherent long-term strategy across multiple execution steps.

What is MCP and how do Plugins use it?

MCP (Model Context Protocol) is a JSON-RPC standard for extending LLM capabilities. The Plugin system in internal/plugin/plugin.go implements an MCP client that connects to external tool servers via stdio, http, or sse transports. This allows Reasonix to integrate tools written in any language or running on remote hosts, treating them as first-class citizens alongside built-in tools without embedding their code in the main binary.

How are permissions enforced in Reasonix?

Permissions are enforced by the Gate interface in internal/permission/permission.go. Before any tool executes, the agent calls permission.Gate.Decide with the tool name and context. Rules configured in reasonix.toml specify allow (automatic execution), ask (prompt user for confirmation), or deny (block execution). This per-tool gating ensures destructive operations require explicit approval while safe operations proceed automatically.

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 →