Apache Maka 0.2 介绍与核心概念
介绍 Apache 孵化项目 Maka 0.2 的定位、local-first agent 工作区理念与核心概念,剖析九大子包架构、Runtime 事件模型、连接目录与凭证库设计。
Apache Maka 0.2 介绍与核心概念
项目状态说明:Apache Maka 正处于 Apache 软件基金会孵化器(Incubator)孵化阶段,尚未毕业。孵化期项目的发布物均为"候选"性质(如本文所述的 0.2.0-incubating),其 API、存储格式与命令行接口都可能在未来版本中发生变化,请勿用于生产环境。
一、项目是什么
1.1 一句话定位
Maka 是一个 local-first 的 AI agent 工作区(workspace)运行时。它把"让大模型在你的服务器上自主干活"这件事拆解为一套严谨的工程体系:模型通过工具调用读写你的文件、执行命令,而 Maka 负责把这一切完整地记录下来——每一条模型消息、每一次工具调用、每一个工具结果,都以事件形式持久化在本地存储中。官方对其核心能力的概括是:记录模型与用户的消息、工具调用与工具结果(record model and user messages, tool calls, and tool results),并在此之上提供会话恢复、多会话管理、使用量计量等能力。
"local-first"是理解 Maka 的关键词:所有数据(会话记录、连接配置、凭证、记忆)都保存在本机文件系统与 SQLite 数据库里,而不是云端。模型服务可以是云端 API,也可以是本地推理服务,但工作区状态永远在你自己的机器上。 把 local-first 放进当前的行业语境里,它的分量比字面更重。主流 agent 产品的会话历史、执行记录、上下文记忆几乎都存在服务提供方的云端,用户对自己数据的可见性止步于产品提供的界面,导出、审计、迁移都受制于人。对个人用户这是体验问题,对企业用户则直接是合规问题:agent 在公司代码库与生产服务器上执行过的每一条命令,都应当有可归属、可回放、可审计的完整记录,而这些记录的所有权必须属于企业自己。Maka 把整个状态层压到本机——事件库是一个普通的 SQLite 文件,可以用任何数据库工具直接查询;记忆是普通的文件目录,可以进版本库;连接配置是可导出的 JSON。数据形态的"可直读"保证了数据主权的"可验证",这是它区别于 SaaS 形态 agent 产品的根本设计立场。
local-first 同时带来一个工程上的红利:状态在本地意味着可以离线运行。模型走本地推理(ollama 类连接)时,整套系统可以在完全断网的服务器上完成"读取需求、调用工具、产出结果、落库记录"的闭环,这对涉密环境、边缘节点、以及把 agent 作为离线批处理引擎的场景都是关键能力。
1.2 孵化背景
Maka 于 2025 年进入 Apache 孵化器,其技术源头来自工业界的 agent 运行时实践。0.2.0-incubating 是孵化期内的重要里程碑版本:提供了 npm 发行包(maka-agent,含 nightly 渠道)、完整的 CLI 入口、以及从源码构建的全部工具链。与许多孵化期项目一样,Maka 的文档与发行渠道仍在建设中——例如 Apache 侧的发行目录目前提供源码包(本文实测使用的正是 0.2.0-incubating 源码包),而 npm 上的 maka-agent 包则以 nightly dist-tag 形式提供最新构建。
需要特别提醒的是:孵化期不等于"Apache 认可的成熟软件"。Apache 孵化器的设计目标是帮项目建立社区、治理与合规流程,孵化期产品的主要受众是早期评估者与开发者。如果你计划基于 Maka 做二次开发,请做好跟随 API 变更的准备。
1.3 它解决什么问题
直接使用 OpenAI SDK 或 LangChain 也能"跑一个 agent",但这类脚本化方案在工程上有几个老大难问题,Maka 针对性地给出了解法:
- 可追溯性:agent 干了什么、为什么这么干、改了哪些文件,事后能不能完整回放?Maka 把每一轮会话的事件(消息、工具调用、工具结果)写入本地事件存储,可审计、可恢复。
- 凭证安全:模型服务的 API key 需要保存与使用。Maka 用独立的凭证库(credential vault)文件管理密钥,与连接配置(connection catalog)分离。
- 工具边界:哪些工具可用、执行命令的权限边界(如 --yolo 全权模式与默认的确认模式)如何管理,Maka 在运行时层面做了内建的准入与记录。
- 多会话工作区:一个工作区(workspace)内可以有多个会话(session),会话之间共享项目记忆,互不串扰。 用一个对照可以看清 Maka 与"脚本调 API"的本质差异。典型的自研脚本大约长这样:读环境变量拿 API key,拼一份带工具定义的请求发出去,循环处理工具调用结果直到模型不再要求调用,最后打印答案。这个脚本在演示里能跑通,但它是无状态的:进程结束,除了终端上滚过的输出,什么都没留下;中途断了就要从头再来;两个任务并行时互相看不见对方的进展;脚本本身对"模型要求执行 rm -rf"没有任何防御。Maka 把脚本中"看不见的那一半"补齐为显式的工程组件:事件库负责状态与回放,会话恢复负责断点续跑,工作区负责并行隔离,权限模式与记录通道负责安全边界。换一种说法:Maka 是 agent 的"操作系统壳",你的模型与工具是"进程",二者各司其职。
二、技术栈与系统组成
2.1 一个重要的事实:它是 TypeScript 项目
初见 Maka 源码包的开发者容易从目录里的 Python 工具脚本产生误解,这里必须先澄清:Maka 0.2 是一个纯 TypeScript/Node.js 的 monorepo 项目,运行环境要求 Node.js 22.19 或更高版本(官方 CI 使用 Node 24)、npm 11,以及 ripgrep(Runtime 的 Grep 工具依赖它)。整个运行时没有任何 Python 组件。源码包根目录的 package.json 声明了 workspaces,npm workspaces 机制把九个子包统一管理。
2.2 九大子包
实测解包 0.2.0-incubating 源码后,packages 目录下共有九个子包,各自职责如下:
| 子包 | 职责 |
|---|---|
| cli | 命令行入口(maka 命令),非交互 print 模式与交互 TUI 模式 |
| core | 领域模型与编解码器(连接目录、凭证库、运行时策略的 codec) |
| runtime | agent 运行时:模型适配、工具执行、事件写入 |
| runtime-host | Runtime Host 托管与远程连接能力 |
| storage | 工作区存储层:runtime.sqlite 等文件的所有权管理 |
| ui | 前端界面(桌面端形态的一部分) |
| eval | 评估框架:声明式多臂实验(experiment)、subject 适配器 |
| mcp | MCP(Model Context Protocol)相关能力 |
| computer-use | 计算机操作类工具能力 |
对 CLI 使用者而言,最核心的三个包是 cli、runtime、storage;做二次开发还需要理解 core 中定义的领域对象。 九个子包的分层逻辑值得梳理,因为它决定了二次开发的切入路径。core 位于最底层,只定义领域对象与编解码规则,不依赖任何执行环境——连接目录、凭证库、运行时策略的 JSON 结构都在这里定义,schemaVersion 迁移逻辑也在这里;storage 居中层,负责把 core 的领域对象落到文件系统与 SQLite,工作区目录下每个文件的"所有权"归它管理;runtime 是执行层,向上接受任务、向下驱动模型与工具,事件写入也发生在这一层;cli 是最薄的入口,只做参数解析与模式选择,把真正的执行交给 runtime。剩下五个包挂在旁路:runtime-host 提供"把运行时托管出去远程连接"的形态,ui 提供图形界面,eval 提供批量评估,mcp 与 computer-use 各自扩展工具能力。理解了这条主干,读源码时就可以按"改哪个行为"直接定位到层:调整存储布局看 storage,调整工具准入看 runtime,新增一种模型协议则从 runtime 的模型适配层入手。
2.3 运行形态
Maka 提供两种运行形态:
- CLI(maka 命令):
maka run "<任务>"一键执行任务,交互式 TUI 里可以实时观察模型输出与工具调用;-p参数进入非交互 print 模式,适合脚本化集成与自动化流水线。 - 桌面应用:monorepo 内包含 Electron 依赖(npm ci 时会下载 Electron 二进制),构建后可得到桌面端。桌面端与 CLI 共享同一套工作区存储。
无论哪种形态,会话数据都落在同一个工作区目录(默认在用户配置目录下的 Maka Dev profile 内),这正是 local-first 的含义。 两种形态的选择建议:以自动化与集成为目标(定时任务、流水线节点、被其他程序调用)用 CLI 的 print 模式,输出可解析、退出码可判断;以人工监督为目标(交互式开发、演示、需要中途干预的探索任务)用 TUI 或桌面端,实时观察模型的每一步动作并在需要时打断。桌面端的定位可以理解为"给 agent 的 IDE"——它在 CLI 能力之上叠加了会话管理与可视化,但底层存储完全一致,同一工作区在两种形态间切换不丢失任何状态。实测中 CLI 是最稳的验证通道,本系列的部署篇与实战篇均以 CLI 为主线。
三、核心概念详解
3.1 工作区(Workspace)与存储布局
工作区是 Maka 的一切数据的根。实测 0.2.0 在完成一次运行后,工作区目录的文件构成如下:
connection-catalog.json 模型连接目录
credential-vault.json 凭证库(API key 等敏感信息)
runtime.sqlite 运行时事件库(消息、工具调用、事件流)
context-offload.sqlite 上下文卸载库
memory.sqlite / memory/ 项目记忆
runtime.sqlite 是整个系统的"黑匣子",实测其内部包含上百张表,核心的几组是:
- runtime_events:事件流主表,每条事件带 event_seq 序号、event_kind(如 function_call、tool_dispatch、function_response、text、completed、invocation_opened、aborted)与 payload_json 载荷;
- tool_operations:工具操作表,记录每次工具调用的 tool_name、current_state(实测一次成功的 Bash 调用终态为 outcome_committed)、provider_tool_call_id 等;
- core_agent_runs:会话运行实例;
- usage_llm_calls / usage_tool_invocations:使用量计量。 选 SQLite 作为事件库是一个值得琢磨的设计决定。替代方案无非三类:纯 JSON 行文件(写简单、查询难、并发写容易损坏)、嵌入式 KV(快但查询模型原始)、独立数据库服务(能力最强但违背 local-first 的零部署诉求)。SQLite 在四者中取得了罕见的平衡点:单文件即整个库,拷贝即备份;支持完整 SQL,审计查询不需要任何额外组件;WAL 模式下读写并发表现足以承载单机 agent 的写入强度;且 Node 22 起官方提供 node:sqlite 内置模块,运行时不必引入原生编译依赖即可使用——这也回应了为什么环境要求 Node 22.19 以上。上百张表的规模初看惊人,实际上是对事件 payload 按领域拆分的结果:消息、工具操作、用量、恢复点各有独立的表族,跨表关联靠 logical_call_id 与 provider_tool_call_id 这类标识串联,审计时用 SQL join 就能还原完整链路。
3.2 会话(Session)与事件模型
一次 maka run 会创建一个新会话。会话内的事件序列遵循固定模式,实测一次"让模型列目录"的最小会话在 runtime_events 中的事件序号为:
4 function_call 模型请求调用 Bash 工具
5 tool_dispatch 运行时派发工具执行
5 tool_dispatch (分派事件成对出现)
5 function_response 工具执行完成,产生结果
6 function_response (结果事件提交)
6 text 模型生成总结文本
7 text (文本事件提交)
7 completed 会话完成
这条链路就是 Maka 的核心卖点:模型行为全部落库。即便进程崩溃,事件流也保持一致(工具操作表有 state 机制支撑恢复),这也是为什么 tool_operations 中一次完成的调用终态是 outcome_committed。 对照业界术语,这套事件流就是 LLM 应用可观测性社区所说的 trace——Maka 选择了最彻底的形态:不外发、不采样、全量本地持久化。事件序号 event_seq 的单调递增保证了回放顺序的确定性;事件成对提交的模式(派发/响应各两条、文本两条)说明写入走的是"先记录意图、再确认结果"的两段式,这正是崩溃一致性技术的应用:进程在任何一步被打断,库里要么有意图无结果(恢复时标记中断),要么两者俱全,不会出现半条记录。对运维团队,这意味着事故复盘可以精确到"模型在第几步请求了什么、工具返回了什么、模型据此做了什么决策",而不是靠记忆与截图拼凑。
3.3 连接(Connection)与连接目录(Connection Catalog)
连接描述"模型服务在哪里、怎么连"。每条连接包含:connectionId(UUID)、slug(小写字母数字连字符的唯一标识)、name、providerType、baseUrl、enabled、enabledModelIds(启用的模型 ID 列表)、models(模型发现结果)等字段。
providerType 的合法值来自内置注册表,实测代码中可见的类型包括:anthropic、openai、openai-compatible(自定义中转,可指定 baseUrl)、openai-responses-compatible、ollama(本地推理)、google 系等。其中 openai-compatible 与 ollama 两个类型对本地实验特别有价值——它们允许把 baseUrl 指向任意 OpenAI Chat 兼容服务(本文实战篇正是用一个本地 stub 模型服务完成了无需外部 API key 的完整 agent 会话)。
连接目录以 JSON 文档形式持久化(connection-catalog.json),实测其结构为:
{
"schemaVersion": 2,
"revision": 1,
"defaultTarget": { "connectionId": "UUID", "modelId": "模型ID" },
"connections": [ 条目数组 ]
}
schemaVersion 字段说明连接目录有自己的版本化迁移机制,孵化期修改存储结构时靠它保证升级兼容。defaultTarget 记录默认连接与默认模型(connectionId + modelId),CLI 在未显式指定 --connection/--model 时使用它。
3.4 凭证库(Credential Vault)
凭证库与连接目录分离存放(credential-vault.json,schemaVersion 1)。每条凭证条目包含:locator(定位器:scope=connection + connectionId + kind=api_key)、credentialId(UUID)、revision、secret、updatedAt。kind 支持 api_key、oauth_token、request_headers 三种。这种"配置与密钥分离"的设计让 connection-catalog.json 可以被导出/版本化,而敏感信息单独管理。
3.5 工具与权限
Runtime 内置工具集包括 Bash(命令执行,参数仅接受 command、timeout_ms、run_in_background、pty 四个键,多一个键都会被严格校验拒绝——实测有真实报错为证)、Grep(依赖 ripgrep)、文件读写与补丁应用等。权限模型上,默认模式对敏感操作有确认环节;--yolo 参数给予任务完整的文件与网络访问权,跳过确认。所有工具调用都走统一的准入与记录通道(tool_operations 表),不存在绕过记录的"直通"路径。
参数严格校验这个细节值得放大,因为它揭示了 Maka 的工程取向:工具接口不做宽容解析,任何超出契约的键都直接拒绝,宁可报错也不猜测意图。这与运行时整个安全姿态一脉相承——模型生成的每一个工具调用都要经过模式校验、准入判定、执行记录三道关口,确认模式把"是否允许"的决定权留给人类,--yolo 则是把决定权明确移交的显式声明。生产化建议是:能把任务约束在只读工具内就不要开 Bash;必须开 Bash 时用默认确认模式配合人工值守;--yolo 只用于一次性、边界清晰、可整体回滚的任务环境,且事后审计事件库复核全部命令。工具调用全量落库这一事实让"事后追责"有据可依,但好的实践永远是让事前边界足够窄,让追责机制派不上用场。
3.6 使用量计量
usage_llm_calls 等表按逻辑调用(logical_call_id)记录每次模型调用的尝试:connection_slug、provider_id、model_id、latency_ms、status(如 failed)、error_class(如 stream_truncated、network)、token 用量。实测中即使一次失败的调用也会留下完整的错误分类记录,这对成本核算与故障排查都很实用。 计量表的设计同样遵循"配置与数据分离"的思路:每次调用的归属字段是 connection_slug 与 model_id 而非硬编码的服务名,这意味着切换模型供应商或调整连接配置后,历史用量数据仍然可以按维度完整聚合。error_class 的分类(stream_truncated、network 等)来自运行时对失败模式的归一化,不同供应商的同类故障在计量层呈现统一的类别,这为跨供应商的稳定性对比提供了干净的数据基础。
四、实测验证摘要
在 Ubuntu 22.04 服务器上的完整实测(详见本系列部署篇与实战篇)验证了以下关键结论:
- 源码包 21MB,SHA512 校验与官方发布一致;
- Node.js 22.19.0 + npm ci 构建路径可行,依赖安装约 1.4GB(含 Electron),构建产物齐全;
- CLI 版本回显为 0.2.0,与发行版本一致;
- 未配置连接时运行给出明确的 model_missing_default_connection 错误引导;
- 通过 openai-compatible 连接指向本地 stub 模型服务,无需任何外部 API key 即可完成完整的 agent 会话:模型消息 → Bash 工具调用 → 工具执行(exitCode 0)→ 工具结果回传 → 最终总结,CLI 输出 "The workspace contains 9 packages: cli, computer-use, core, eval, mcp, runtime, runtime-host, storage, ui.";
- runtime.sqlite 中事件链完整可查。
五、常见问题(FAQ)
1. Maka 和 Dify、LangChain 这类 agent 框架是什么关系? 定位不同。LangChain 是构建 agent 应用的编程框架,Dify 是低代码应用平台;Maka 则是一个"运行时 + 工作区"——它自己不提供模型,专注在"如何安全、可追溯地在你的机器上运行 agent"这一层。可以把 Maka 理解为 agent 时代的"终端 + shell 历史 + 权限系统"的组合体。
2. 孵化期能用在生产环境吗? 不建议。0.2.0-incubating 属于孵化期候选发布,README 明确说明 CLI 表面与存储格式仍在快速演进(例如连接目录文档已有 schemaVersion 1 到 2 的版本迁移),未来版本可能要求迁移或重置工作区。
3. 为什么需要 Node.js 22 以上? Runtime 使用了 Node 22 的若干新特性(如实验性的 node:sqlite 模块承载运行时事件库)。实测 Node 22.19.0 构建与运行正常;Ubuntu 22.04 apt 源中的 Node 版本过旧,需要从官方发行渠道安装新版。
4. 必须有 OpenAI/Anthropic 的 API key 才能跑起来吗? 不是。Maka 支持 openai-compatible 自定义中转与 ollama 本地推理两类连接,只要提供 OpenAI Chat 兼容的 /v1/chat/completions 服务(本地起一个也行)就能完成会话。本文实战篇用约 70 行的本地 stub 服务完整跑通了带工具调用的会话。
5. Maka 支持哪些模型协议? 内置注册表支持 anthropic、openai、openai-compatible、openai-responses-compatible、ollama、google 等类型。协议差异由 runtime 的模型适配层处理,对上层工具调用透明。
6. 会话记录能删除吗? 可以。工作区是普通文件:删除 runtime.sqlite 即清空会话历史;整个工作区目录删除即完全重置(连接配置与凭证也会一并删除,需重新配置)。
7. 数据真的不出本机吗? 工作区数据(会话、配置、凭证)全部在本机文件与 SQLite 中。出网的只有模型调用本身(若使用云端模型)与模型主动发起的网络访问(受权限模式约束)。local-first 指的是数据主权在本地,而非网络隔离。
8. eval 子包是做什么的? 评估框架:用声明式 spec 定义多臂(multi-arm)实验,每个臂指定 subject(被测的 agent 执行器)与任务集,自动并行运行(fleet 机制)并产出对比结果。适合在改 prompt/换模型后量化回归。
9. MCP 是什么角色? mcp 子包提供 Model Context Protocol 支持,使 Maka 可以接入 MCP 生态的工具服务,把外部能力挂到 agent 的工具列表中。
10. nightly 发行与 incubating 源码包有何区别? npm 上 maka-agent 的 nightly dist-tag 跟随主干构建,更新最快但未做发布级验证;downloads.apache.org 上的 0.2.0-incubating 源码包经过社区签名与校验(本文实测了 SHA512 一致性),适合作为评估基线。生产评估建议锁定具体版本源码自行构建。
11. 工作区可以自定义位置吗?迁移怎么办? 工作区本质是"一组约定布局的文件与 SQLite 库",通过 CLI 的工作区参数可指向自定义目录;迁移等于拷贝目录——事件库、连接目录、凭证、记忆随目录整体迁移,换机器不失状态。唯一需要注意的是凭证库文件包含敏感内容,迁移通道要保证传输与落盘的权限安全。
12. 记忆(memory)与会话记录是什么关系? 会话记录是完整的事件流,回答"发生过什么";记忆是提炼后的长期信息,回答"这个项目里需要一直记住什么"。实测工作区里两者分属 memory.sqlite(及 memory 目录)与 runtime.sqlite,互不混写。模型在会话中可读写记忆,跨会话形成连续性,这正是多会话共享项目记忆机制的落点。
六、参考链接
- Apache 孵化器项目页(Maka):https://incubator.apache.org/projects/maka.html
- 0.2.0-incubating 源码下载:https://downloads.apache.org/incubator/maka/0.2.0-incubating/apache-maka-0.2.0-incubating-src.tar.gz
- SHA512 校验文件:https://downloads.apache.org/incubator/maka/0.2.0-incubating/apache-maka-0.2.0-incubating-src.tar.gz.sha512
- 源码仓库:https://github.com/apache/maka
- npm 包页(maka-agent):https://www.npmjs.com/package/maka-agent
- Apache 孵化器说明:https://incubator.apache.org/policy/process.html
- Node.js 22 发行页:https://nodejs.org/dist/latest-v22.x/
- ripgrep 仓库:https://github.com/BurntSushi/ripgrep