Sema Code: Decoupling AI Coding Agents into Programmable, Embeddable Infrastructure

Paper: arXiv:2604.11045 Code: midea-ai/sema-code-core Code reference: main @ 69f7dcc6 (2026-05-26)

1. Motivation (研究动机)

现有 AI coding agent 已经能完成代码搜索、编辑、测试、工具调用和多步推理,但大多以一个具体产品形态交付:CLI、IDE 插件、Web app 或托管聊天界面。论文认为这带来一个系统性瓶颈:能力被锁在产品壳里,企业或第三方系统很难把同一套 agent reasoning kernel 嵌入到自己的 IDE、消息机器人、CI/CD、内部平台或跨语言服务中,也很难替换底层模型、统一权限策略、复用上下文管理和工具生态。

Figure 1 解读:左侧代表传统 monolithic AI 系统,核心推理、UI、工具权限和运行时状态都绑定在同一个产品内;右侧代表 Sema Code 的目标,把“AI coding 能力”拆成可被任意客户端驱动的透明引擎。这个图不是在比较某个模型指标,而是在说明论文的主要问题定义:AI coding agent 应该像 SQLite 或 Chromium 一样成为可嵌入基础设施,而不是只能被用户手动打开的应用。

具体来说,论文要解决的是 agent engine 的产品形态解耦:同一个核心引擎既要能在 VSCode Extension Host 里运行,也要能作为服务器端 Node.js 进程支撑 Telegram、Feishu 等多渠道 agent 平台;客户端只负责渲染、通道转发和交互 UI,核心 agent loop、工具调度、权限控制、上下文压缩和多 agent 运行时都由 Sema Core 提供。

这个问题值得研究的原因是,一旦 AI coding agent 被设计成“可编程引擎”,上层系统就能像接数据库一样接入它:后端服务可以直接 import npm package,非 TypeScript 系统可以通过 WebSocket / gRPC 桥接,企业可以在同一套权限和审计策略下服务 IDE、Web、机器人和自动化工作流。论文的关注点因此不是提出新的 SWE-bench solver,而是把复杂 agent 产品中隐藏的基础设施能力抽象成可复用 runtime。

2. Idea (核心思想)

核心 insight 很直接:把 AI coding agent 从“端到端应用”改造成“可嵌入、可插拔、framework-first 的核心引擎”。Sema Code 将核心推理、工具调用、状态管理、权限和生态接入封装成无 UI 的 sema-core npm package;所有客户端只通过事件流和公开 API 与引擎通信。

关键创新不在单个算法,而在一组工程机制的组合:三层分离架构、多租户隔离、FIFO 输入队列与会话重建、自适应上下文压缩、多 agent 协作调度、ID-matched Todo 状态机、异步后台任务、四层权限决策,以及 MCP / Skills / Plugins 三层生态。它们共同回答一个问题:当 agent 不再只服务一个本地 CLI 用户,而要成为多客户端共享基础设施时,状态、上下文、权限和长任务如何仍然可控。

与 Claude Code、Cursor、GitHub Copilot 这类强产品化 agent 相比,Sema Code 的差异是交付边界:前者把能力封装在特定 CLI/IDE/Web 体验中,第三方只能“使用产品”;Sema Code 则暴露 engine API,第三方可以“嵌入能力”。与 AutoGen / LangChain 这类通用 LLM orchestration 框架相比,Sema Code 更贴近 coding agent runtime:它内置代码编辑、shell、权限、Todo、background task、context lifecycle,而不是只提供抽象 conversation graph。

3. Method (方法)

3.1 Overall framework: 三层分离架构

Figure 2 解读:Sema Code 被拆为 Client Layer、Core Engine Layer 和 Service Layer。Client Layer 可以是 VSCode extension、CLI、Web、Telegram/Feishu bot 或 gRPC client;Core Engine Layer 是 UI-free 的 sema-core,负责 agent loop、tool orchestration、session state、permission、memory/context;Service Layer 则对接模型 API、MCP server、Skills、Plugins、filesystem、shell、history 等外部能力。图中的关键点是所有客户端都只通过 event-driven public APIs 驱动同一核心引擎,客户端差异不应渗入 agent reasoning kernel。

直觉上,Sema Code 的架构把“agent 能力”和“产品体验”放在不同变化速率的层里:上层 UI/通道经常变化,底层模型和工具生态也会替换,但中间的 agent runtime 应稳定、可测、可嵌入。如果不这样拆分,任何新增客户端都要复制一套上下文压缩、权限、工具调度和任务管理逻辑;如果拆分成功,同一 engine binary 就能服务多个产品形态。

3.1.1 Client Layer

Client Layer 不执行核心 reasoning,而是订阅事件流并把事件渲染为本地 UI:例如 VSCode 中的 diff preview、Todo board、background task panel、permission dialog;在消息机器人中则对应 inline button、消息线程和 Web 管理后台。论文强调客户端通过事件而非内部状态访问引擎,这让前端可以换形态而不改变 engine。

3.1.2 Core Engine Layer

Core Engine Layer 包含 Sema Core:agent loop、工具调用、状态管理、权限检查、context lifecycle、multi-agent runtime、Todo 和 background task。released code 中 src/core/SemaCore.ts 暴露进程级 API(session、models、marketplace、MCP、skills、plugins、cron 等),src/core/SemaSession.ts 暴露单会话交互 API,src/core/SemaEngine.ts 处理输入队列、消息构建和 query lifecycle。

3.1.3 Service Layer

Service Layer 对接模型、MCP、Skills、Plugins、shell、filesystem、history 和 marketplace。它让 Core Engine 不绑定某个 provider 或某个工具源:Anthropic 和 OpenAI-compatible adapters 被统一成 streaming protocol;MCP 是外部服务工具层,Skills 是行为/提示策略层,Plugins 是命令与 hook workflow 层。

3.2 Core engine mechanisms

3.2.1 Multi-tenant isolation

论文设定多租户场景:一个 Sema Core 进程可能同时服务 VSCode 单用户会话和 50-person team 的消息机器人。若所有 agent 实例共享全局 singleton state,则任意实例 写入共享状态 后可能被另一个实例 读到,导致 conversation history 泄露、权限信号串扰或 abort collision。

论文方案是给每个 engine instance 绑定独立 resource bundle:event bus、state manager、tool orchestrator、tenant config。论文称使用 Node.js AsyncLocalStorage 跨 async boundary 传播这些资源引用,从而避免每个函数都显式传参。

论文公式与 released code 实现差异:论文在 §3.2.1 明确写到 AsyncLocalStorage (ALS),但 main@69f7dcc6src/ 下没有 AsyncLocalStorage 字符串;released code 当前以 SemaCore + SessionPool + StateManager.session(sessionId) 管理会话,SemaCore.createSession() 委托 getSessionPool().createSession(opts),而非直接可见的 ALS resource bundle。笔记中的伪代码因此按论文机制解释 ALS,代码映射则按当前 repo 的实际文件锚定。

3.2.2 Hierarchical state partitioning

单个 session 内又可能有 main agent 和多个 sub-agent。论文把 session state 分成 agent-local 与 session-global 两层: 对任意 agent ,本地状态为: 其中 表示执行状态, 是独立 conversation history, 是该 agent 的 Todos, 是局部 file-read timestamps。S_{global} 则保存跨 agent 必须共享的控制量,例如全局 edit permission flag 和 centralized abort controller 。这样 sub-agent 的工具结果和中间推理不会污染 main agent context,但用户点击一次 cancel 仍能终止整棵 agent tree。

released code 中 StateManager.forAgent(agentId) 返回按 agentId 隔离的 accessor;clearAgentState(agentId) 会删除该 agent 的 states、messageHistory、readFileTimestamps、todos、todoTasks 和 fileLineEndings。src/tools/SubAgent.ts 在 foreground 子代理结束时调用 runtime.forAgent(taskId).clearAllState() 并移除 foreground agent,和论文的 agent-local 生命周期相符。

3.2.3 FIFO input queue and safe session reconstruction

当主 agent 正在处理请求时,用户可能继续发消息或输入 slash command。论文定义状态感知 dispatch: 普通文本消息在 dequeue 时会被 semantic batching 合并,减少 LLM round;slash command 则逐个执行,避免操作语义被混合。released code 中 SemaEngine.processUserInput() 若发现 main agent state 为 processing,会把输入按 trimmedInput.startsWith('/') 标成 commandinject 加入 pendingUserInputssrc/util/inputQueue.ts 提供 takeNextBatchStateManager.consumeInjectInputsBeforeNextCommand() 优先消费连续 inject 消息。

安全会话重建的目标是避免 mid-execution 切换项目或 session 时留下残余状态。论文写法是把新 session id 放入 pendingSession,向 发送 abort;当前任务的 finally 检测 pending flag 后清理 并初始化新 session。released code 没有显式 pendingSession 字段,但 SemaEngine.interruptSession()StateManager.clearPendingUserInputs()clearAgentState() 和 session pool API 构成了相近的中断/清理路径。

3.2.4 Adaptive context compression

长时间 coding session 会持续积累消息、工具结果和文件片段。论文不用每轮重新计算整段上下文,而是从最近 assistant message 的 usage metadata(如 Anthropic input_tokens)读取累计输入 token,形成 监控。论文还声称在累计 usage 上加 8,000-token forward buffer,用于吸收下一轮 system prompt、user query、tool result 等开销;当 effective context 超过模型最大上下文 的 75% 时触发压缩。

压缩时先找最近真实 user message 作为 pivot ,把历史切成可压缩段 和当前轮保留段 ,避免破坏 tool_use / tool_result 配对。主路径让 LLM 生成摘要,可写成信息保留目标: 若摘要失败或超时,则降级为 deterministic truncation:扫描 usage metadata,截断到上下文上限的 50%,并只在 assistant message 边界截断以保持 API role alternation 合法。released code 的 src/util/compact.ts 与论文基本一致:AUTO_COMPACT_THRESHOLD_RATIO = 0.75autoCompact() 找最后一条非 tool_result 的真实 user message,executeAutoCompact() 用主模型生成摘要,失败时 truncateMessages(messages, contextLimit * 0.5)

论文公式与 released code 实现差异:论文描述了额外的 8,000-token forward buffer;main@69f7dcc6needsAutoCompact() 实际是 countTokens(messages).inputTokens >= getContextLimit() * 0.75,没有单独把 8,000 token 加到阈值判断中。代码确实支持 Anthropic input_tokens + cache_creation_input_tokens + cache_read_input_tokens 与 OpenAI prompt_tokens,但 buffer 机制在 released code 中不可见。

3.3 Agent runtime

Figure 3 解读:该图把 runtime 拆成三块:(a) background task execution,把长时间 Bash/Agent 任务移入后台并保留 timeout recovery;(b) multi-agent coordination,为 sub-agent 提供隔离 state space、生命周期管理和 shared abort signal;(c) adaptive context compression,在高压阈值触发 token reduction。它对应论文 §4 的三个运行时目标:并发分工、可观测进度、长任务不阻塞主对话。

3.3.1 Multi-agent collaborative scheduling

复杂代码任务通常需要不同能力:例如先搜索代码、再设计修改、再运行测试、最后 review。把所有子任务塞进 main agent 会出现两个问题:一是某个 Skill 的系统提示污染后续任务;二是 subtask history 和工具结果堆进主上下文,导致更早触发压缩。Sema Code 采用隔离 state spaces + shared interrupt control:sub-agent 与 main agent 不共享 conversation history 或 tool result,只共享 abort controller。

released code 中 src/tools/SubAgent.ts 会根据 agent config 构造独立 system prompt 和工具集;默认排除嵌套 agent/task 相关工具,避免递归失控;sub-agent 的 run_shell 不暴露 background 字段。foreground sub-agent 会注册到 TaskManager,用独立 AbortController 执行 ReAct,结束后清理本地状态;background sub-agent 则通过 spawnAgentTask 注册为后台任务。

3.3.2 Interrupt propagation and read-write-aware scheduling

论文把 interrupt boundary 分成多个阶段:post-inference dispatch、pre-execution verification、active execution monitoring、recursion termination。核心思想是中断不能只 kill 当前进程,还要保证 API message 结构仍合法:尚未执行的 tool_use 要有 cancellation placeholder,正在运行且支持 interrupt 的工具可以返回部分结果,不支持 interrupt 的工具要返回取消上下文。

released code 中 src/core/RunTools.ts 体现了这一点:工具开始前若 abort,直接返回 CANCEL_MSG;工具执行期间若 abort 且 reason 是 refuse,保留拒绝消息;若工具支持 supportsInterrupt()(如 RunShell),保留工具内部返回的部分结果;不支持中断的工具则返回取消 tool_result。调度方面,论文说 read-only 操作可并行,含写操作的 batch 必须串行,以避免 file edit / shell 带来的 race condition。

3.3.3 Intelligent Todo-based process management

Todo 的目标不是“让 LLM 写一个列表”,而是让长任务进度可观测且稳定。LLM 常把同一个任务从 “Refactoring auth module” 改写成 “Refactor authentication module”,如果 UI 逐字替换会闪烁。Sema Code 给每个 task item 分配唯一 id、描述和 lifecycle state(pending / active / completed 等),并强制同一时刻最多一个 active subtask。

released code 中 StateManager.updateTodosIntelligently() 检查新 Todo 是否都是已知 id:如果是 subset update,只更新对应 id 的条目并保留原描述;如果出现未知 id,则全量替换注册新任务。这与论文“ID-matched Todo process management”一致,也解释了为什么 Todo 工具需要 id 而不仅是自然语言列表。

3.3.4 Background task execution

长时间 build/test 会阻塞同步 agent loop;普通 timeout 又会杀掉进程、丢失部分输出,并可能让 shell singleton 卡死。Sema Core 把 execution 与 observation 分离:长任务由 background manager 维护,主对话立刻恢复;后台任务有 running / completed / failed / stopped 等状态,输出被持续写入文件和内存缓冲,用户或 agent 可 later peek/stop。

released code 中 RunShell 有两个路径:background=true 时主 agent 直接调用 TaskManager.spawnRunShellTask(),返回 task id 和 output file;同步命令超时且不是 sub-agent 时,通过 onTimeout 调用 TaskManager.takeoverTask(),把 timed-out persistent shell 转交给后台。代码中默认 timeout 是 120,000 ms,最大 600,000 ms;TaskManager 每个 session 最多 5 个 running background tasks,保留 50 个 finished tasks。

3.4 Security and ecosystem

3.4.1 Four-layer permission decision

论文把权限按操作类型分成四层,而不是一个统一 allow/deny gate:

LayerOperation TypeFast-PassApproval TriggerGranularity
L1File editingEdit flag onFirst edit requestSession
L2Shell commandsPrefix in whitelistNot whitelisted / injectionProject
L3Skill invocationSkill authorizedFirst invocationProject
L4MCP operationsName authorizedFirst invocationProject

形式化地,权限函数为 。对 shell 命令,论文给出白名单规则: 其中 ,每个 sub-command head 都必须命中白名单 。若不命中,系统进入 request;若检测到 backtick、$(...)、破坏性 chain 等注入风险,则升级警告或 deny。

released code 中 PermissionManager.checkToolPermission() 分别处理 file edit、RunShell、Skill、MCP 和 FetchUrl。checkRunShellPermission()splitCommand() 并用 hasCommandInjection() 做 fail-closed 检测,再查 exact/prefix authorization;AutoRun 档位会调用 classifyActionSafety(),风险不明则转人工。与论文相比,released code 更偏 deterministic regex + optional LLM safety classification,而不是所有非白名单命令都先做 LLM-assisted static analysis。

3.4.2 Asynchronous approval protocol

当工具需要用户授权时,engine 不直接阻塞在某个 UI 模态框,而是向 event bus 发 authorization request,暂停当前 execution context。客户端可以用 VSCode dialog、Web UI 或 Feishu/Telegram inline button 处理;engine 只等待 concrete decision 或 global abort。返回路径包括 transient approval、persistent authorization、explicit rejection、user-guided correction。sub-agent 继承 parent permission boundary,避免多 agent 任务中重复弹窗。

3.4.3 Three-tier ecosystem: MCP / Skills / Plugins

Sema Code 把生态扩展分成三种粒度:MCP 是 infrastructure granularity,包装数据库、浏览器、API gateway 等外部服务;Skills 是 behavior granularity,用 Markdown + YAML frontmatter 改变 agent 的推理方式、约束和模型偏好;Plugins 是 workflow granularity,扩展 slash command 或 lifecycle hook,例如 /review/deploy、审计日志和自定义验证。论文认为三者不能合并,否则会让轻量提示策略拿到过高工具权限,或让基础设施集成失去持久连接和认证管理能力。

3.4.4 Multi-model adaptation layer

Sema Core 内置 Anthropic native 与 OpenAI-compatible adapters,把 Extended Thinking、Prompt Caching、tool-use schema 和 streaming events 归一到统一协议。released code 中 src/services/api/adapt/anthropic.tssrc/services/api/adapt/openai.ts 分别处理 provider-specific streaming;SemaCore.getModelAdapter() 通过 inferAdapter() 暴露适配能力。论文还列出可经 customBaseUrl 接入 Code Llama、DeepSeek-Coder、DeepSeek V3/R1、GLM-5、Qwen3-235B、Gemini 2.5 Pro 等模型。

3.5 Pseudocode based on released code

Code reference: main @ 69f7dcc6 (2026-05-26) — pseudocode and mapping based on this commit

3.5.1 FIFO dispatch and batched query start

from collections import deque
from uuid import uuid4
 
class SessionRuntime:
    def __init__(self):
        self.state = "idle"
        self.pending_inputs = deque()
        self.abort_controller = None
 
    def process_user_input(self, text: str, silent: bool = False):
        input_id = str(uuid4())
        text = text.strip()
        if self.state == "processing":
            kind = "command" if text.startswith("/") else "inject"
            self.pending_inputs.append({"id": input_id, "text": text, "type": kind, "silent": silent})
            emit("input:received", queued=True, inject=(kind == "inject"))
            return
        self.start_query([{"id": input_id, "text": text, "silent": silent}])
 
    def start_query(self, inputs: list[dict]):
        self.state = "processing"
        self.abort_controller = AbortController()
        ctx = AgentContext(agent_id="main", abort=self.abort_controller, tools=get_available_tools())
        try:
            process_query(inputs, ctx)
        finally:
            self.state = "idle"
            next_batch = take_next_batch(self.pending_inputs)
            if next_batch:
                self.start_query(next_batch)

3.5.2 Adaptive context compression

AUTO_COMPACT_THRESHOLD_RATIO = 0.75
 
def needs_auto_compact(messages: list[Message], context_limit: int) -> bool:
    if len(messages) < 3:
        return False
    input_tokens = count_tokens(messages).input_tokens
    return input_tokens >= context_limit * AUTO_COMPACT_THRESHOLD_RATIO
 
def auto_compact(messages: list[Message], llm: LLM, context_limit: int) -> list[Message]:
    pivot = find_last_real_user_message(messages)  # skip user tool_result messages
    if pivot is None:
        return messages
    history, current_turn = messages[:pivot], messages[pivot:]
    if len(history) < 2:
        return messages
    try:
        summary = llm.summarize(history, prompt=COMPRESSION_PROMPT, tools=[NULL_TOOL])
        compacted_history = [compression_notice(), assistant_summary(summary)]
    except Exception:
        compacted_history = truncate_at_assistant_boundary(history, target_tokens=context_limit * 0.5)
    return compacted_history + current_turn

3.5.3 ID-matched Todo update

def update_todos_intelligently(current: list[Todo], new: list[Todo]) -> list[Todo]:
    if not new:
        emit("todos:update", [])
        return []
    known_ids = {todo.id for todo in current}
    subset_update = all(todo.id and todo.id in known_ids for todo in new)
    if subset_update and current:
        by_id = {todo.id: todo for todo in new}
        updated = [by_id.get(todo.id, todo) for todo in current]
        emit("todos:update", new)  # UI receives changed states; text remains stable
        return updated
    emit("todos:update", new)
    return new

3.5.4 Shell permission check

def check_run_shell_permission(command: str, allowed_tools: list[str], autorun: bool) -> Permission:
    command = strip_initial_cwd_prefix(command)
    subcommands = split_command(command)
    if any(has_command_injection(cmd) for cmd in subcommands):
        return request_permission(command, show_persistent_allow=False, severe=True)
    if exact_match(command, allowed_tools) or saved_prefix_match(command, allowed_tools):
        return Permission.allow()
    if autorun:
        if classify_action_safety(command) == "safe":
            return Permission.allow()
    prefix = infer_command_prefix(command)
    return request_permission(command, suggested_prefix=prefix)

3.5.5 Background shell execution and timeout takeover

def run_shell(command: str, timeout_ms: int = 120_000, background: bool = False, is_subagent: bool = False):
    timeout_ms = min(timeout_ms, 600_000)
    if background and not is_subagent:
        task_id, output_path = task_manager.spawn_run_shell_task(command)
        return f"Command running in background. Task ID: {task_id}. Output: {output_path}"
 
    transfer = {"task_id": None, "path": None}
 
    def on_timeout(ctx: TimeoutTransferContext):
        if is_subagent:
            return None
        transfer["task_id"], transfer["path"] = task_manager.takeover_task(ctx, command)
 
    result = persistent_shell.exec(command, timeout_ms=timeout_ms, on_timeout=on_timeout)
    if result.code == -1 and transfer["task_id"]:
        return f"Command timed out after {timeout_ms}ms, moved to background: {transfer['task_id']}"
    return format_stdout_stderr(result)

3.6 Code-to-paper mapping

Code reference: main @ 69f7dcc6 (2026-05-26) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
UI-free embeddable core APIsrc/core/SemaCore.tsSemaCore, createSession, model / MCP / Skill / Plugin APIs
Per-session public interfacesrc/core/SemaSession.tsSemaSession.create, processUserInput, interrupt, event methods
Session lifecycle and FIFO input queuesrc/core/SemaEngine.ts, src/util/inputQueue.tsprocessUserInput, startQuery, takeNextBatch
Session and agent-local statesrc/manager/StateManager.tsSessionRuntime, forAgent, clearAgentState, pendingUserInputs
Context compressionsrc/util/compact.ts, src/prompt/compact.tsneedsAutoCompact, autoCompact, compactMessages, COMPRESSION_PROMPT
Multi-agent schedulingsrc/tools/SubAgent.ts, src/tools/PlanToAgent.tsSubAgent, PlanToAgent, foreground/background agent task paths
Todo process managementsrc/manager/StateManager.ts, src/tools/CreateTodo.ts, src/tools/UpdateTodo.ts, src/tools/ListTodos.tsupdateTodosIntelligently, Todo CRUD tools
Background task executionsrc/tools/RunShell.ts, src/manager/TaskManager.ts, src/tools/PeekBgJob.ts, src/tools/StopBgJob.tsspawnRunShellTask, takeoverTask, waitForTask, stopTask
Permission decision layerssrc/manager/PermissionManager.ts, src/util/commands.tscheckToolPermission, checkRunShellPermission, hasCommandInjection
MCP / Skills / Plugins ecosystemsrc/services/mcp/MCPManager.ts, src/services/skills/skillsManager.ts, src/services/plugins/pluginsManager.tsMCP server config, Skill config loading, marketplace plugin APIs
Multi-model adapterssrc/services/api/adapt/anthropic.ts, src/services/api/adapt/openai.ts, src/util/adapter.tsAnthropic/OpenAI-compatible streaming adapters, inferAdapter

4. Experimental Setup (实验设置)

这篇论文不是模型训练或 benchmark paper;它的“实验设置”是 deployment validation:用同一个 Sema Core engine 支撑两个不同产品形态,验证 decoupled engine 是否真的能跨客户端复用。因此没有训练集、学习率、batch size、GPU 数或 supervised/RL training steps。论文未详细说明任何 SWE-bench / HumanEval / pass@k 实验。

Datasets / deployments

  • VSCode Extension:单用户、in-process 部署,运行在 VSCode Extension Host;覆盖长 session 的 adaptive context compression、四层权限系统、background task execution、MCP/Skill/Plugin marketplace。
  • SemaClaw multi-channel agent platform:服务器端 Node.js 进程,多用户、多渠道部署;接入 Telegram、Feishu 等 messaging channels 和 Web UI 管理界面;覆盖 multi-tenant isolation、FIFO input queue 和 asynchronous approval protocol。
  • 规模说明:论文用“50-person team”作为多租户动机场景,但 deployment validation 没有给出真实并发用户数、请求量、延迟、吞吐或故障率数据。

Baselines / compared systems

论文没有做数值 baseline comparison,而是在 Related Work 中按系统类型对比:

GroupSystemsContrast
End-user coding productsClaude Code, Cursor, GitHub Copilot能力强但绑定 CLI / IDE / plugin form factor,核心能力难以作为第三方 engine 复用
Agentic coding frameworksSWE-agent, OpenHands, Agent-Computer Interface, Agentless更关注 solve GitHub issue 或 repository repair 流程,通常仍绑定特定 execution harness
Multi-agent / orchestrationAutoGen, LangChain, MetaGPT, ChatDev通用或流程化协作框架,不内置 coding-agent-specific 权限、Todo、background shell、context lifecycle
Memory / context systemsMemGPT, YaRN解决长上下文或 paging,但不是 embeddable coding agent runtime

Evaluation metrics

论文的评价指标是架构性而非统计性:

  • Engine modification count:两个产品是否需要修改 Sema Core;论文报告为 zero engine modifications。
  • Mechanism coverage:两个部署合起来是否覆盖八个核心机制;论文报告 VSCode 与 SemaClaw 互补,together cover all eight mechanisms。
  • Client-side integration effort:客户端是否只需 event stream rendering、channel adapter、permission UI 或 multi-session manager,而不需要理解内部 state/compression/permission 机制。
  • Delivery-agnostic behavior:同一 engine binary 是否在不同 UI、通道和拓扑下运行,无 feature flags 或 conditional code paths。

Implementation / training config

  • Released packagepackage.json 中 npm package 为 sema-core,version 2.0.3,main entry dist/index.js,types dist/index.d.ts,license MIT
  • Build scriptsnpm run build 调用 tscnpm run lint 调用 eslint src/**/*.tsprepublishOnly 会先 build。
  • Runtime config from codeRunShell 默认 timeout 120000 ms,最大 600000 ms;TaskManager 每 session 最多 5 个 running background tasks,保留 50 个 finished tasks;compact.ts 自动压缩阈值为 context limit 的 0.75,失败降级截断到 0.5 context limit。
  • Model/provider config:repo 依赖 @anthropic-ai/sdkopenai,并通过 Anthropic native / OpenAI-compatible adapters 支持 Prompt Caching、Extended Thinking 与 tool-use schema 的差异归一。

5. Experimental Results (实验结果)

Main deployment findings

ClaimEvidence reported in paperExact status
Same engine supports different product formsVSCode Extension and SemaClaw both import the same Sema Core npm package2 deployments
Client-specific behavior stays outside engineUI rendering, channel routing, permission dialogs, deployment topology live in client layerzero engine modifications
Mechanisms compose without interferenceVSCode stresses context compression/background tasks; SemaClaw stresses multi-tenant isolation/FIFO/async approvaltogether cover all 8 mechanisms
Integration boundary is cleanVSCode implements event stream rendering and UI components; SemaClaw implements Telegram/Feishu adapters and multi-session managerclients use public API + typed event stream

Key findings

  1. Decoupling is feasible at product level:论文报告两个不同交互模型的产品共用同一个 engine binary,没有 feature flags 或 per-product conditional path。这支持“engine-first”架构主张。
  2. 机制覆盖互补:VSCode 单用户场景主要验证长上下文、权限和后台任务;SemaClaw 多用户消息场景主要验证多租户隔离、输入队列和异步 approval。两者合起来覆盖论文列出的八个 mechanisms。
  3. 代码实现支持主要机制,但与论文描述存在差异:repo 确实包含 session API、permission manager、context compression、sub-agent、Todo、background task 和 MCP/Skill/Plugin manager;但当前 commit 没有可见 AsyncLocalStorage,也没有论文中 8,000-token forward buffer 的实现。

Ablation studies

论文未提供传统 ablation table,也没有逐项移除机制后的数值退化。可从系统设计推断每个组件的 failure mode,但这不是实验测量:移除 FIFO 会导致 message burst 丢失或命令混合;移除 Todo id matching 会导致 UI flicker;移除 background takeover 会让长 build/test 阻塞主对话;移除四层权限会在 shell/MCP/Skill 之间混淆风险边界。

Limitations

作者明确列出五类限制:

  • 只验证了两种产品形态;CI/CD pipeline、Jupyter notebook embedding 等其他 form factor 尚未证明。
  • 当前部署没有做大规模 stress testing;数百并发用户的生产负载可能暴露性能瓶颈。
  • context compression 质量依赖底层 LLM 的 summarization 能力;高密度代码上下文可能在摘要中丢失关键细节,而 truncation fallback 会牺牲连贯性换可用性。
  • WebSocket / gRPC 跨语言接口虽然功能完整,但没有 benchmark streaming throughput 或 adversarial network 下的 error recovery。
  • 当前部署使用单个 Sema Core 进程;横向扩展到多个 engine instance 会引入 state synchronization 问题,当前架构未解决。

Overall conclusion

Sema Code 的主要贡献是把 AI coding agent 从“产品功能”提升为“可编程基础设施”。它没有证明自己在 SWE-bench 上超过某个 agent,而是证明一套 coding-agent runtime 可以被拆成可嵌入核心:同一 Sema Core engine 通过事件流服务 VSCode extension 和多渠道 SemaClaw,同时保留上下文压缩、多 agent、权限、Todo、后台任务与生态扩展能力。对读者最重要的 takeaway 是:如果要在企业内部构建多个 agent 入口,不应复制多个 monolithic agent,而应先定义一个 delivery-agnostic engine boundary。