How Multica Unifies 13 AI Coding Tools Behind a Single Backend Interface

Multica integrates thirteen disparate AI coding tools—Claude Code, Codex, Cursor, Copilot, Gemini, Hermes, Kimi, Kiro, OpenCode, OpenClaw, Pi, Antigravity, and CodeBuddy—by defining a single Go Backend interface, sinking differences into per‑tool adapters and an ExecOptions struct, while preserving graceful degradation and a capability matrix for product decisions.

Hacker Afternoon Tea
Hacker Afternoon Tea
Hacker Afternoon Tea
How Multica Unifies 13 AI Coding Tools Behind a Single Backend Interface

Multica needs to support thirteen AI coding tools that differ in session recovery, MCP handling, skill‑path injection, and model selection. Writing separate scheduling logic for each would create a massive switch statement, so the author examined the server/pkg/agent/ adapters and discovered a classic solution: a unified interface with differences sunk into adapters.

Unified Backend Interface

The core of the adaptation layer is a single Go interface defined in server/pkg/agent/agent.go:

type Backend interface {
    // Execute runs a prompt and returns a Session for streaming results.
    Execute(ctx context.Context, prompt string, opts ExecOptions) (*Session, error)
}

Each of the thirteen tools implements this Execute method in its own .go file. The daemon schedules tasks by calling backend.Execute(ctx, prompt, opts) without caring which tool is behind the call, and receives a Session to read streamed messages and the final result.

ExecOptions – Centralizing Differences

Differences are not ignored; they are collected into a single ExecOptions struct. Every adapter picks the fields it needs and silently ignores the rest:

type ExecOptions struct {
    Cwd               string
    Model             string
    SystemPrompt      string
    ThreadName        string
    MaxTurns          int
    Timeout           time.Duration
    ResumeSessionID   string // session recovery
    ExtraArgs         []string
    CustomArgs        []string
    McpConfig         json.RawMessage // MCP config
    ThinkingLevel     string // inference level
    OpenclawMode      string // OpenClaw‑specific
}

The design deliberately omits methods like IsClaude(); each adapter decides which fields to honor. For example, the ThinkingLevel comment notes it is honored by Claude, Codex, and OpenCode, while other backends ignore it silently, enabling graceful degradation instead of hard failures.

Capability Matrix

When making product decisions, developers need to know each tool’s capabilities. The author extracted a matrix from code and documentation, summarizing key features:

Claude Code : session recovery ✅, MCP ✅, skill path .claude/skills/, static model selection with flag.

Codex : session recovery ⚠️ (logic present but CLI unreachable), MCP ✅, skill path $CODEX_HOME/skills/, static model selection.

Cursor : session recovery ⚠️, MCP ✅, skill path .cursor/skills/, dynamic model discovery.

Copilot : session recovery ✅, MCP ❌, skill path .github/skills/, static (account‑based) model selection.

Gemini : no session recovery, no MCP, fallback skill path .agent_context/skills/, static model selection.

Hermes : session recovery ✅, MCP ✅, fallback skill path, dynamic model discovery.

Kimi : session recovery ✅, MCP ✅, skill path .kimi/skills/, dynamic model discovery.

Kiro : session recovery ✅, MCP ✅, skill path .kiro/skills/, dynamic model discovery.

OpenCode : session recovery ✅, MCP ✅, skill path .opencode/skills/, dynamic + variant model selection.

OpenClaw : session recovery ✅, MCP ✅, fallback skill path, binds to agent.

Pi : session recovery ✅, MCP ❌, skill path .pi/skills/, dynamic model discovery.

Antigravity : session recovery ✅, MCP ❌, skill path .agents/skills/, dynamic model discovery.

CodeBuddy : session recovery ✅, MCP ✅, custom skill path, dynamic model discovery.

This matrix explains why a user might see a skill work on one tool but not another: three tools (Gemini, Hermes, OpenClaw) use a generic fallback path .agent_context/skills/, and each tool decides whether to read from that location.

ThinkingLevel Mapping

The most technically involved part is handling the inference‑level parameter ( ThinkingLevel). Each tool uses different flag names and value sets (e.g., Claude: low|medium|high|xhigh|max, Codex: none|minimal|low|medium|high|xhigh, OpenCode: model variant). Multica stores a unified level internally and translates it per tool in server/pkg/agent/thinking.go via mapping tables, e.g.:

// server/pkg/agent/thinking.go
var codebuddyEffortLabel = map[string]string{ ... }
// each tool gets a map: unified level → native flag
// unsupported tools simply omit the flag in Execute

Thus the scheduler always sets one ThinkingLevel; adapters handle the translation or ignore it if the tool does not support the concept.

Design Takeaways

The pattern repeats across the whole adaptation layer: the scheduler speaks a single language, adapters translate to each vendor’s dialect. Adding a new tool only requires a new .go file implementing the interface, without touching the core scheduling logic. The article concludes with a teaser for the next part, which will cover Multica’s task state machine and timeout handling.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Goadapter patternai coding toolsbackend interfaceexecoptions
Hacker Afternoon Tea
Written by

Hacker Afternoon Tea

You might find something interesting here ^_^

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.