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.
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 ExecuteThus 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
