
Maka Runtime 核心架构解析Log Is the Runtime——用 Runtime Event Log 回放 Agent 的状态空间【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka本文是 Apache MakaIncubatingRuntime 架构系列的第一章。核心回答一个问题Maka 如何保存一次 Agent 运行真正经历过的状态空间并在下一轮、进程重启或新投影中重新得到它答案是Runtime Event Log模型循环负责产生事实factsEvent Log 负责保存事实而 Session、Run、UI、模型上下文和恢复逻辑都是这份有序日志的投影projections。读完本文你将掌握 Maka Runtime 的事件模型、执行主链各层职责、终止不变量terminal invariant以及如何按代码阅读地图定位主链实现——这对第一次进入 Maka Runtime 的工程师和需要修改运行主链的维护者都适用。文中描述的是截至 2026-08-23 已在生产主链中落地的实现历史设计文档中的阶段性计划不作为当前事实。从一个看似简单的请求开始假设用户对 Maka 说找出这个项目里失败的测试修复问题然后重新运行测试。如果 Maka 只是一个聊天应用执行路径只有三步把文字发给模型、等待回复、把回复显示出来。但 Agent 的真实执行过程远比这复杂模型先阅读项目和测试输出模型调用文件、搜索或终端工具某些工具需要用户授权运行暂时停住parking工具可能持续输出streaming也可能失败、超时或被取消工具结果回到模型模型决定下一步模型 → 工具 → 模型的步骤循环重复多次最后系统必须明确判断这次运行究竟完成、失败还是被用户中止。过程中界面需要实时显示文本和工具活动下一轮模型需要读到可信历史应用崩溃重启后系统不能永远停在运行中用户按下停止按钮后迟到的 provider 事件也不能把状态重新写成完成。所以Runtime 真正解决的问题不是怎样调用一次 LLM API而是如何把一个包含流式输出、工具副作用、用户介入和进程故障的开放式循环记录成一段可以重新解释和回放的事实历史。先说结论状态不是一张表而是日志的函数Maka Runtime 最核心的设计判断不是选择了哪个模型 SDK也不是把执行逻辑拆成了多少层而是Runtime Event Log 才是 Agent 交互的语义事实源semantic source of truth。系统在某一时刻的状态是这段有序日志经过某种投影之后的结果。可以把它写成一个简单的关系State(t) Project(RuntimeEvents[0..t], policy, runtime configuration)同一段日志可以被不同消费者解释成不同状态Model History Projector得到下一次模型调用需要看到的 messagesRuntime Read Model得到 UI 需要展示的对话、工具活动和 Turn 状态Terminal Fact Classifier得到一次 Run 的最终结果Recovery逻辑判断进程退出前哪些事实已经 durableContext Budget 与 compaction 策略得到一个更小但保留关键语义的工作上下文未来的调试器可以把读取位置停在任意事件边界观察当时的 Agent 状态空间。这张图从中间开始读Runtime Event Log是稳定事实其余节点是可以演进、重建或替换的派生视图。事件生产路径被刻意省略由后文解释。这与普通 application log 有本质区别。普通日志通常是在业务执行之后描述代码做过什么主要供人排障而 RuntimeEvent 本身就是业务语义的一部分。用户消息、模型回复、thinking、function call、function response、权限动作、usage 和 terminal status 都以强类型事实进入日志。删除这份日志系统就失去了可靠重建交互状态的基础。一条 RuntimeEvent 保存了什么RuntimeEvent不只是role text。它把一条事实拆成几组正交信息维度维度关键字段意义IdentitysessionId,invocationId,runId,turnId,branch这条事实属于哪段会话、调用、执行尝试和分支Orderingid,ts与 ledger 顺序这条事实在因果历史中的位置Sourcerole,author它在模型历史中扮演什么角色由谁产生Contenttext, thinking, function call/response, errorAI 交互本身的语义内容Actionsstate delta, permission, artifact, usage, end invocation它要求 Runtime 怎样改变控制状态或记录副作用Correlationtool call、provider event、step 与 artifact refs怎样把跨系统的同一件事重新配对Lifecyclepartial,status它是可替换的流式片段、持久事实还是终止事实在源码层面canonical 契约定义于 packages/core/src/runtime-event.ts。其核心接口RuntimeEvent见该文件第 665-695 行包含身份字段id事件 UUID用于重连/重放时的去重、invocationId持久的调用脊线 ID聚合一次请求的所有 run/turn、runId持久的操作运行身份、sessionId、turnId聚合一次 Agent Turn 的所有事件、tsUnix 毫秒时间戳、branch可选为未来多 Agent 树预留的代理泳道来源字段role在模型历史中的泳道取值为user/model/tool/system四种对应RUNTIME_EVENT_ROLES见第 115 行、author产生该事实的子系统、origin执行面旧版账本上可能缺失、modelVisibility显式的 provider 历史策略缺省时按旧版兼容视为可见生命周期字段partial布尔值true标记可被后续事件取代的瞬时流式分块、status对 invocation/turn 的生命周期断言普通 in-flight 内容事件上省略语义负载content文本/thinking/function call/function response/error 等类型化内容、actionsstate delta、权限、artifact、usage、end invocation 等控制状态变更、refs工具调用、provider 事件、step、artifact 的关联引用。一个关键的设计约束是partial: true的瞬时分块流式文本、进度会被后续 non-partial 事件取代模型历史 MUST 排除 partial 事件源码注释见第 661-663 行。这保证了下一轮模型请求永远不会把不完整的流式片段当作事实。这种结构保留的不是 UI 已经格式化好的聊天文本而是模型交互的原始语义。尤其是thinking 可以携带 provider 要求的 signatureRuntimeEventThinkingContent含signature字段tool call 与 tool result 通过稳定 ID 配对tool call 还能指向它所属的 assistant stepsandbox boundary 请求与决定是 action而不是一段伪装成聊天的文字terminal event 明确关闭一次 Run而不是靠最后一条消息看起来像回答来猜测。因此模型历史不需要从 UI transcript 反向解析。它可以从 RuntimeEvent 中选择 non-partial、model-visible 的事件保持顺序再根据 provider 能力物化成 text-only 或 provider-native messages。UI 同样不需要成为事实源它只是另一种 projection。回放状态空间究竟意味着什么这里的 replay 有三个层次需要精确区分。语义回放当前已经成立给定 RuntimeEvent ledgerMaka 可以重建用户/模型文本、thinking、工具调用与结果、权限动作、usage 和 terminal fact。下一轮模型历史与 completed Session read model 都已经优先从这份 ledger 构造。这意味着我们能回答在某个事件边界之前模型已经看到了哪些交互它调用过什么工具工具返回了什么哪些权限被请求或决定一次 Run 是否已经结束Provider-native 回放有能力门控不同 provider 对 tool history 和 signed thinking 的要求不同。Maka 不会把所有事件盲目塞回模型而是先建立 replay plan检查 partial、tool call/result 配对、step ID、thinking signature 和 provider 支持再决定走 provider-native、text-only还是明确降级路径。可回放不等于把 JSONL 原样发给任何模型。它意味着保留足够丰富的事实让投影器能够为具体 provider 生成合法的历史同时显式报告语义损失。Bit-exact wire replay不能只靠 message log 宣称RuntimeEvent 保存了 AI 交互的 canonical message semantics但当前并不等于每次 provider HTTP 请求的原始字节级快照。System prompt、工具 schema、provider options、模型实现版本以及 context selection/compaction policy 仍参与最终 request 的生成当前系统只记录了其中一些 identity、diagnostic 和 hash并没有把整个 wire request 复制进 RuntimeEvent ledger。因此状态空间回放首先是交互语义与 Runtime 状态的可重建性。如果未来要承诺 bit-exact deterministic replay还需要对运行配置、prompt、tool catalog、投影策略和 provider request shape 做版本化或快照化。这不是削弱 Event Log 的价值反而说明它提供了正确的基础message facts 保持稳定request materialization 可以独立演进。两条思想来源这个设计有两条明确的思想脉络。第一条来自 Google ADK。ADK 把 Session 看作带有时间顺序 Events 的事实容器Event 同时承载 content、author、invocation identity、partial 标记与 actionsSession state 通过事件中的 state delta 更新模型工作上下文则从事件历史选择和转换得到。Maka 借鉴的关键不是字段长得相似而是更深层的原则Session history 是事实working context 是计算出来的 projection。第二条来自分布式数据系统中的 log-first 思想。数据库 WAL、replicated log、event sourcing 和 Kafka 共享一个重要直觉不要把每个下游视图都当作独立真相先保存有序、不含糊的变化事实再让消费者重建自己的状态。只要事件顺序和提交边界可信缓存、索引、搜索视图乃至部分损坏的状态表都可以重新生成。Maka 并不是在进程内实现了 Kafka也没有声称 RuntimeEventStore 是一个分布式共识日志。借鉴的是更基础的设计原则Log is the source of truth; state is a materialized view.这一原则直接解释了后文最重要的 terminal invariant除了这次 Run 自己的 terminal RuntimeEvent没有别的东西能宣布它结束。三种生命周期身份加一个关联字段理解主链之前需要先分清三个经常被口语化混用的生命周期概念。概念它回答的问题当前实现中的身份Session这些对话和运行属于哪段长期交互sessionIdTurn用户界面中的这一轮问答是哪一轮turnIdRun这一次具体执行尝试是谁状态是什么runId/AgentRunRuntimeEvent 仍保留invocationId作为兼容与事件关联字段。从源码看packages/core/src/runtime-event.ts 第 654 行Phase 0-3 身份契约是一个invocationId对应一个runIdInvocation 标识 provider/工具执行Run 标识其持久的操作账本。生产主链把invocationId绑定到 Run 身份它不再对应单独的 Invocation 生命周期对象或 Runner 层。这里最重要的判断是Turn 不是 Run聊天消息也不是执行状态。一个用户可见的回合需要一个系统可追踪的执行封套否则系统只能知道出现过一些消息却无法可靠回答这次执行是否真正结束。围绕 Event Log 运转的执行主链所有 hosted execution 路径共用下面这条 Runtime 主链从左向右读这张图越靠左越接近产品入口和长期 Session越靠右越接近一次 provider 请求和具体工具副作用。存储投影和事件账本被省略后文单独解释。这不是为了把一个函数拆成很多类。更准确地说这些组件分担了 Event Log 的生产、规范化、提交和消费责任每一层都在保护一种不同的稳定性。SessionManager稳定的产品入口SessionManager.sendMessage()是外部调用者看到的门面。它现在很薄读取和管理 Session 的公共能力保留在这里真正的执行直接委托给RuntimeKernel.startTurn()RuntimeKernel的startTurn签名见 packages/runtime/src/runtime-kernel.ts 第 167 行实现见第 664 行。这个边界让桌面端、CLI、Bot 和 Eval 调用者通过 Runtime Host 工作不必理解 Run ledger、Flow 或 terminal fact。Runtime 内部可以在 Host 协议后演进。RuntimeKernel活跃执行的控制面RuntimeKernel把一条 Session 请求组织成一次可运行的 Run。它负责创建AgentRun创建或复用绑定到 Session 的 Backend注册活跃 Run并维护turnId → runId映射把停止和权限响应路由到正在运行的 Backend驱动 Backend 事件流并映射 RuntimeEvent统一处理 abort 路由、单终态terminal coalescing、终态后静默排空silent post-terminal drain和缺失终态失败missing-terminal failure让 RuntimeEvent 落盘后再把原有SessionEvent流交还调用者在 Backend 流收尾时确保AgentRun.finalize()被执行。它是 orchestration boundary而不是模型循环本身。Backend 不应该负责这个 Session 目前有哪些活跃 Run产品入口也不应该负责终止 RuntimeEvent 是否已经持久化。这些跨层协调都收敛在 Kernel。AgentRun一次执行的 Durable EnvelopeAgentRun让一次执行在持久世界里有身份和生命周期。开始运行时它会把这次 invocation 的开场事实opening fact作为 RuntimeEvent 提交对顶层 Run 写入用户消息和runningTurn 投影写入本轮初始用户RuntimeEvent锁定本 Session 的连接配置确保 Backend 已创建并注册为活跃 Run从此前的 RuntimeEvent ledger 构造模型历史。运行过程中AgentRun同时接收旧的SessionEvent与新的RuntimeEvent并把它们写入各自所属的投影或账本。结束时它注销活跃 Run、收敛 Session/Turn 状态并提交最终 Run 状态。可以把AgentRun理解成一次执行的耐久封套它不决定模型下一步调用哪个工具但它保证这次执行是谁、发生了什么、最后以什么状态结束。RuntimeKernel一个执行所有者一套终态协议Runtime 不再在AgentRun和AgentBackend之间插入通用 Runner/Flow 壳。RuntimeKernel直接拥有生产主链的协议AgentRun.begin()在 Backend dispatch 前持久化初始用户 RuntimeEventAgentBackend.send()前重新校验精确的活跃 Runabort signal 路由到绑定具体 Backend generation 的 stop 函数Backend 事件先映射并由AgentRun耐久接收再作为SessionEvent暴露第一个被接受的 terminal fact 获胜随后静默排空 Backend 流Backend 抛错或流结束时缺少终态都会收敛成结构化失败durable continuation 消费一次性 start-admission proof并且不伪造新的 user event。这些规则是生产生命周期不变量所以放在生产所有者RuntimeKernel中让调用图和权威边界显式化。SessionEvent Runtime mapper旧事件流与 Runtime 事实之间的桥当前模型/工具循环仍然由AgentBackend.send()产生 renderer-facingSessionEvent。packages/runtime/src/session-event-runtime-mapper.ts 中的mapSessionEventToRuntimeEvent()把被接受的事件逐个映射成 canonicalRuntimeEvent。源码第 104-128 行的注释完整列出了映射规则模型文本和 thinking →role model,author agenttool_startfunction call→role model,author agent工具进度/输出 delta →role tool,author toolpartialtool_resultfunction response→role tool,author toolsandbox_boundary_request→role system,author systemsandbox_boundary_decision_ack→role system,author user人在系统泳道里的决定token_usage→ runtime actionrole system,author systemerror、abort、complete → 明确的失败或终止事实terminal。从源码注释第 108 行可以确认mapper 是确定性的给定(event, ctx, memory)结果唯一且不携带任何 I/O——streaming、stop、dispose 或 admission 都不属于它。memory会在tool_start时记录toolName供tool_result读取从而在流式过程中保持一致的工具调用配对关系。生命周期决策全部属于RuntimeKernelmapper 只负责 Backend 事件入口的词汇转换。AgentBackend模型与工具循环真正发生的地方对默认的AiSdkBackend来说核心循环仍在send()内部。它会解析模型并准备本轮可见的工具集合从 RuntimeEvent 历史构造 provider messages并应用上下文预算context-budget策略组合 system prompt、当前用户输入和附件通过ModelAdapter启动 AI SDKstreamText()读取 text、thinking、step boundary、finish reason 和 usage让 AI SDK 在模型发起 tool call 时进入ToolRuntime将工具结果交回下一步模型请求重复模型/工具 step直到模型结束、达到上限、发生错误或被中止。step 上限是可选的maxSteps为undefined时不设限由模型自己决定何时收尾。若设置了上限而模型在上限处仍要求继续调用工具Runtime 会保留已经产生的工具结果并在没有最终文本时补充一条确定性的提示让用户可以在新 Turn 中继续而不是留下一个没有收尾文本的界面——UI 不会出现一条解释不清的孤立工具行。ModelAdapterpackages/runtime/src/model-adapter.ts隔离 provider 与 AI SDK 差异模型创建、stream 启动、chunk 归一化、usage 归一化和错误分类。ToolRuntimepackages/runtime/src/tool-runtime.ts则隔离工具执行的高风险部分工具可用性防守、权限、超时/中止传递、重复失败拦截、工具输出、遥测和 artifact 记录。模型循环是怎样向前推进的下面这张时序图聚焦一次包含工具调用的正常运行展示控制权如何在模型与工具之间转移AI SDK 的 step 是这个循环的自然节拍。Maka 会按 step 持久化 assistant text/thinking而不是把整个 Turn 压成一条最终 assistant message。工具调用会携带对应的 step ID使 thinking、文本和工具调用在 replay 时仍能重新组成原来的执行顺序。工具运行期间模型 provider 不会继续输出。ToolRuntime会暂停模型流的 idle watchdog因为这段安静是预期行为具体工具仍然可以有自己的超时而更外层的 Run 或评测系统继续充当最终 backstop。权限不是弹窗而是 Runtime 控制流当一次工具调用越过当前沙箱边界时工具不会静默失败Runtime 也不会由 UI 自行弹一个对话框把执行挂起。流程是这样的工具返回一个带sandbox_boundary_required与具体expansion的失败结果模型据此调用request_sandbox_boundary发起一次边界扩张请求运行停在一个有身份identity的位置上等待答复。等待期间Session 投影为waiting_for_user但 Run 仍然保留自己的执行身份——它没有结束只是停住了parked。用户的决定通过RuntimeKernel.respondToSandboxBoundary()路由回当前 Backend实现见 packages/runtime/src/runtime-kernel.ts 第 2126 行同一条路径上还有respondToUserQuestion()第 2155 行用于模型主动向用户提问的场景。两类请求在未答复期间都由RuntimeKernel登记为 active interaction因此一个错过了实时事件的界面可以重新拉取待答项而不会把运行晾在那里。这个设计的关键是权限不是 UI 自己暂停了一下。请求和决定都作为带类型的事实进入 Runtime 事实模型——它们没有content而是带actions.stateDelta的系统事件。因此重放、诊断和恢复都能解释运行为什么停住以及控制权如何回来。决定那条事实的role是system、author是user它在模型历史里属于系统泳道但产生它的是人这一对正交字段把这件事表达出来而不需要把用户决定伪装成一条聊天消息。此外RuntimeKernel在映射和持久化前丢弃permission_request/permission_answer_ack/permission_closure_ack/permission_decision_ack这组遗留词汇它们已被 sandbox boundary 事件取代不能再成为活的运行时事实。这一点在 mapper 源码中同样得到印证——session-event-runtime-mapper.ts 第 143-144 行会直接抛出is a legacy permission event and is not backend-mappable。一份语义事实两类辅助状态Maka 当前同时维护三类持久数据。它们不是三个地位相同的真相也不是重复保存同一份聊天。RuntimeEventStore是 AI 交互的 canonical semantic log另外两类存储承担产品投影以及 Runtime 做过什么的运维记录。存储主要内容它最适合回答的问题SessionStore用户、assistant、工具和 turn-state 等StoredMessageUI 与兼容接口要展示什么活跃流有哪些即时投影AgentRunStoreoperational Run events这次 Run 在哪个模型或工具阶段做了什么、又在哪里失败RuntimeEventStorecanonical RuntimeEvent 与有界 partial snapshotsAgent 交互发生过哪些语义事实其他状态应如何重建当前实现由SQLite承载而不是每个 Run 一个目录AgentRunStore与RuntimeEventStore都建立在同一份 operational state 数据库之上RuntimeEvents 落在runtime_events表。建表语句见 packages/storage/src/sqlite-runtime-schema.ts 第 49-60 行CREATE TABLE runtime_events ( event_id TEXT PRIMARY KEY, session_id TEXT NOT NULL, invocation_id TEXT NOT NULL, run_id TEXT NOT NULL, turn_id TEXT NOT NULL, event_seq INTEGER NOT NULL CHECK (event_seq 0), event_kind TEXT NOT NULL, payload_json TEXT NOT NULL, committed_at INTEGER NOT NULL, UNIQUE (invocation_id, event_seq) );顺序由该表的event_seq承担并以(invocation_id, event_seq)唯一约束保证一次 invocation 内序号不重复——有序日志在存储层就是这条约束。四个身份session/turn/run/invocation各占一列因此这个 Session 的这次 Run 的这个 Turn 发生了什么是一次索引查询runtime_events_by_run索引按(session_id, run_id, event_seq)建立。存储层还有一个值得注意的约束CREATE UNIQUE INDEX runtime_events_one_opening_per_invocation ON runtime_events(invocation_id) WHERE event_kind invocation_opened第 505-507 行——一次 invocation 只有一个开场事实为恢复路径提供了可靠的锚点。AgentRunStore的事件更像 operational index从 packages/core/src/agent-run.ts 第 43-90 行的AGENT_RUN_EVENT_TYPES可以看到这些操作事件的完整清单——model_stream_started、model_stream_completed、tool_started、tool_completed、tool_failed、permission_requested、permission_decided、sandbox_escalation_requested、abort_requested等。它们帮助快速诊断和管理 Run但不替代模型交互日志。RuntimeEventStore的事件才是可重建的语义事实用户内容、模型内容、function call/response、边界与提问动作以及 terminal fact。对于已经完成且 ledger 完整的 Run读取与下一轮模型 replay 优先依赖 RuntimeEvent。SessionStore仍然承担兼容投影和 in-flight 展示不能简单删除但它不再是 completed runtime 语义的唯一权威。流式 text/thinking partial不会被无限追加进账本。RuntimeEventStore 为可替换的流维护有界 partial snapshot最终 non-partial 事件到达后覆盖其语义位置。这既保留崩溃时已经展示的部分输出也避免 10,000 个 delta 变成 10,000 条长期账本记录。Log-first 的关键不变量先有终止事实再提交终止状态Runtime 最容易出现的一类故障是不同存储对是否结束给出不同答案。例如用户已经 stop但迟到的 complete 又把 Session 写回 activeBackend 流耗尽却从未说明它是成功还是失败已经结束的 Run又有第二个写入方想再结束它一次。Maka 当前保护的核心不变量是一个 Run 只结束一次而它的 terminal RuntimeEvent 是唯一说它结束了的事实。因为结果没有第二份记录要同步崩溃也就不可能留下一份说已完成、另一份说还在跑的状态。具体到实现没有终态的 Backend stream 会被合成为missing_terminal_event失败——runtime-kernel.ts 第 1867-1892 行的missingTerminalSessionEvents()在 Backend 耗尽且没有 terminal RuntimeEvent 时先发出code: missing_terminal_event的 error 事件再发出stopReason: error的 complete 事件重复终态由 Kernel 合并第一个被接受的 terminal fact 获胜状态不匹配、来自其他 Run 或标记为partial: true的 terminal event 都会被拒绝。这条不变量让恢复不必猜模型当时准备做什么。系统只需要判断哪些事实已经 durable然后把各个投影收敛到同一个可解释终态。Stop、错误与崩溃如何收敛用户停止RuntimeKernel.stopSession()会先把所有活跃AgentRun标记为 stopped再调用 Backend 的stop()。从 runtime-kernel.ts 第 1894 行的实现可以看到它先为每个 execution 设置stopIntent、调用execution.run?.stop(...)再触发abortController.abort(...)最后执行stopSessionAttempt()完成收敛。AiSdkBackend会中止 provider stream、结束正在等待的 sandbox boundary 或用户提问并产生 abort/complete 事件。即使 provider 随后发送迟到的 complete 或 errorRuntimeKernel与AgentRun也不会允许它覆盖已经确定的 aborted 语义。停止来源例如 renderer stop button会进入 terminal fact供诊断使用。Provider 或 Runtime 错误错误首先被规范化为非终止 error content随后由 failed terminal event 关闭 Run。RuntimeKernel不允许后续的 completed event 掩盖之前已经观察到的错误。若 Backend 直接抛出异常或流没有终态Kernel 会产生结构化失败而不是留下悬空运行。应用崩溃和启动恢复启动恢复不会重新执行模型请求或工具副作用。它扫描非终止 Run 与 RuntimeEvent ledger识别 stale model stream、tool tail、未答复的 interaction、损坏的 operational event 等情况然后保守地提交失败或取消状态并修复 Session/Turn 投影。这是状态修复不是 checkpoint resume它保留已经产生的部分输出把状态收敛到一个可解释的终态但不会在进程重启后自动从某个工具调用的下一行继续执行。继续执行是另一条路径。safe_boundary_continuation从一个经过校验的安全边界接着跑——边界之前的事实全部可信边界之后的不予采信。它同样不从被打断的那一行开始区别在于它有一个可验证的起点而崩溃收敛只是给一次执行下结论。两者差异详见 runtime-resume-architecture.zh-CN.md。这套设计换来了什么又付出了什么得到的能力产品入口不依赖具体 provider 或工具循环实现不同 Backend 通过 Kernel 共享 Run 与 terminal 语义UI 事件与模型可重放事实被明确区分用户停止、权限和工具副作用进入可诊断的控制流崩溃后可以依据 durable facts 收敛状态Runtime Host client、子 Agent 和调度器复用同一执行核心。当前代价迁移期同时存在SessionEvent、StoredMessage、RuntimeEvent和 operational Run events事件映射的维护成本较高AiSdkBackend仍然很重同时组织 history、context budget、tool availability、step loop、usage 与 telemetrySessionEvent Runtime mapper仍承担 legacy-to-canonical adapter 角色而不是 Backend 原生产 canonical eventsSessionStore与 RuntimeEvent projection 需要在 active/in-flight 场景中协同启动恢复是确定性终结与修复不是从任意位置热续跑。续跑走另一条路safe_boundary_continuation从一个经过校验的安全边界接着跑它在 invocation 开场事实里记着自己的续跑来源由RuntimeKernel完成准入和 dispatch。这些不是应该隐藏的实现细节而是当前架构的真实边界。未来拆分 Backend 或加入 checkpoint 时首要目标不是减少文件行数而是保持 request shape、工具可见性、事件顺序和 terminal invariant 不变。代码阅读地图建议按照下面的顺序阅读当前实现均为仓库内真实路径packages/runtime/src/session-manager.ts公共入口与恢复入口packages/runtime/src/runtime-kernel.tsRun/Backend 的活跃控制与主链组装packages/runtime/src/agent-run.tsDurable lifecycle、历史构造和终态提交packages/runtime/src/session-event-runtime-mapper.ts纯SessionEvent → RuntimeEvent映射packages/runtime/src/ai-sdk-backend.tsAI SDK 模型/工具 step looppackages/runtime/src/model-adapter.tsprovider stream 适配packages/runtime/src/tool-runtime.ts沙箱边界、工具执行和副作用边界packages/core/src/runtime-event.tscanonical RuntimeEvent 契约packages/core/src/agent-run.ts 与 packages/storage/src/agent-run-store.tsRun 与 RuntimeEvent 的账本契约与 SQLite 实现SQLite 建表细节见 packages/storage/src/sqlite-runtime-schema.ts。对应的关键测试集中在均为仓库内真实路径packages/runtime/src/tests/session-event-runtime-mapper.test.tspackages/runtime/src/tests/session-manager.test.tspackages/runtime/src/tests/session-manager-terminal-ledger.test.tspackages/runtime/src/tests/runtime-ledger-repair.test.ts小结Maka Runtime 的核心不在某一个类也不只是 AI SDK 的多步工具循环。核心是一个可以保留并回放 Agent 交互状态空间的Runtime Event Log执行协议围绕这份日志产生事实、提交事实并构造派生状态model/tool stepping engine → canonical RuntimeEvents → durable semantic log → model history / UI / Run state / recovery projectionsSessionManager稳住入口RuntimeKernel管理活跃执行与终态协议AgentRun提交耐久事实SessionEvent Runtime mapper把 Backend 事件翻译成 canonical facts而AiSdkBackend、ModelAdapter与ToolRuntime真正推进模型和工具循环。它们都围绕 Runtime Event Log 协作而不是各自保存一份局部真相。这套结构最终保护的是一件很朴素的事无论一次 Agent 工作经历多少模型 step、工具副作用、等待用户答复和异常Maka 都要先忠实记录发生过什么。只要这份有序事实仍在系统就能重新构造当时的交互状态生成新的视图并让下一轮从可信历史继续。【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考