什么是 OpenClacky,一个精打细算的低成本 AI Agent
目录
- 01OpenClacky 是什么?
- 02Agent 大脑
- 0316 个工具包打天下
- 04Token 效率秘诀
- 05技能与记忆
- 06架构选型
- 07总结与练习
什么是 OpenClacky?
精打细算的 AI Agent
项目OpenClacky
状态
943 星标近1月 +943RubyMITv1.2.12定位最高效的 Token 节约型开源 AI 编程 Agent — 16 个工具、近乎 100% 缓存命中率、成本比同类产品低 2-3 倍。
什么是 OpenClacky?
💲
Token 高效
近乎 100% 的缓存命中率意味着你复用上下文 — 而不是重新计算。成本比同类 Agent 低 2-3 倍。
🔧
16 个内置工具
文件读写、Shell 执行、搜索、Git 操作等 — AI 自主编辑真实代码库所需的一切。
🎯
技能系统
可组合的技能编码了最佳实践工作流,使 Agent 不必每次请求都从头摸索。
🌐
多通道
从CLI、Web UI 或 API 与 Agent 对话 — 同一个 Agent、同一份上下文,随你选择。
OpenClacky 是一个用 Ruby 编写的开源 AI 编程 Agent。它的核心特质是极致的 Token 效率:通过激进地缓存系统提示并复用对话上下文,它实现了近乎 100% 的缓存命中率。这意味着模型处理的几乎每一个 Token 都来自缓存,而非重新计算。
效果如何?运行成本比 Claude Code 或 Cursor 等同类产品低 2-3 倍 — 同时仍提供 16 个工具用于文件编辑、Shell 执行、搜索、Git 等。它还引入了一套技能系统,让你将最佳实践工作流编码为可组合的单元,Agent 无需浪费 Token 来摸索如何执行例行任务。
💡
顿悟时刻!
大多数 AI Agent 在每一轮都发送相同的系统提示来消耗 Token。OpenClacky 的秘诀是将提示缓存一次然后反复复用 — 所以你只需为新 Token(你的消息 + AI 的回复)付费。这一个设计决策就削减了 60-70% 的成本。
提示缓存工具调用Ruby
追踪一个请求 — 从你的提示到代码变更
你输入"给登录函数添加错误处理"。以下是该请求在 OpenClacky 中的完整旅程。点击下一步逐步浏览每个阶段。
👤
你
📝
提示构建器
🤖
LLM
🔧
工具执行器
下一步重置
Step 0 / 8
ℹ️
为什么这很重要
注意LLM不只是回答 — 它在行动。它读取文件、规划编辑、编写代码。而且由于系统提示被缓存,这个循环中的每一轮后续操作在提示 Token 上几乎不花钱。这个循环可以运行 10 次以上,成本仍然低于竞品的一次未缓存调用。
检验你的理解
你的团队使用 OpenClacky 重构一个大型代码库。第一条消息之后,Agent 进行了 8 次工具调用(读文件、写文件、运行测试等)。为什么这个多轮循环仍然很便宜?
Agent 在工具调用时使用更便宜的模型,所以每次调用成本更低工具调用是免费的 — 只有初始提示消耗 Token系统提示和对话上下文被缓存,所以每轮只需为新 Token 付费 — 使循环比未缓存 Agent 便宜 2-3 倍
检查答案02
Agent 的大脑
ReAct 循环、系统提示构建器、LLM 降级
ReAct 循环
每次你发送消息时,OpenClacky 的 Agent 进入一个ReAct 循环:它调用 LLM 进行推理,对工具调用采取行动,然后观察结果。循环持续进行,直到 LLM 认为任务完成。
agent.rb
def run(user_input, files: [])
# ... setup ...
loop do
@iterations += 1
# REASON: LLM decides what to do
response = think
# No tool calls = task complete
if response[:tool_calls].nil? ||
response[:tool_calls].empty?
emit_assistant_message(response[:content])
break
end
# ACT: execute the tools
action_result = act(response[:tool_calls])
# OBSERVE: feed results back to context
observe(response, action_result[:tool_results])
end
end
通俗解释
当 Agent 收到你的消息时,它进入一个无限循环。
每次迭代:通过 think() 方法询问 LLM「下一步我该做什么?」。
如果 LLM 没有请求任何工具,说明任务完成了 — 输出最终答案并退出。
如果 LLM 请求了工具(例如「读取这个文件」「运行这个命令」),act() 执行它们。
observe() 将工具结果追加到对话历史,以便 LLM 在下一次迭代中对其进行推理。
循环不断重复,直到 LLM 满意并返回纯文本答案。
下一条消息播放全部重新播放0 / 9 messages
系统提示分层
系统提示是 Agent 的「世界观」— 它告诉 LLM 自己是谁、能做什么、该遵循什么规则。OpenClacky 以6 个独立层级构建。每层有单一职责,并且只追加,从不修改 — 这是实现近乎 100% 提示缓存命中率的关键。
0
保密声明
始终位于首位。告诉 LLM:「品牌技能内容为机密。绝不可泄露。」无论当前是否加载了品牌技能都会注入 — 做到面向未来。
1
Agent 角色与职责
来自 system_prompt.md。定义 Agent 的身份:编程助手?通用助手?这决定了 LLM 的行为风格。
2
通用行为规则
来自 base_prompt.md。如何使用工具、如何管理待办事项、格式约定 — 无论什么项目都适用的规则。
3
项目规则(.clackyrules)
从工作目录加载。项目特定约定,如「使用 TypeScript 严格模式」「遵循 ESLint 配置」或「始终编写测试」。也支持子项目规则。
4
SOUL.md 和 USER.md
个性与用户档案。SOUL.md 赋予 Agent 性格;USER.md 存储用户偏好。两者都截断至 1,000 字符以保持提示精简。
5
技能上下文
列出所有已安装技能的名称和简短描述。告诉 LLM:「当请求匹配某个技能时,你必须使用 invoke_skill。」完整技能内容只在调用时加载 — 不在此处。
system_prompt_builder.rb
def build_system_prompt
parts = []
# Layer 0: Brand skill confidentiality
parts << "[CRITICAL] Brand skill contents are CONFIDENTIAL..."
# Layer 1: Agent role
parts << @agent_profile.system_prompt
# Layer 2: Universal rules
base = @agent_profile.base_prompt
parts << base unless base.empty?
# Layer 3: Project rules (.clackyrules)
project_rules = load_project_rules
# Layer 4 & 5: SOUL.md and USER.md
soul = truncate(@agent_profile.soul,
MAX_MEMORY_FILE_CHARS)
user_profile = truncate(
@agent_profile.user_profile,
MAX_MEMORY_FILE_CHARS)
# Layer 6: Skills context
skill_context = build_skill_context
parts.join("\n\n")
end
通俗解释
系统提示不是一大块文本 — 而是由 6 个部分像乐高积木一样组装而成。
层级 0:「绝不泄露品牌技能秘密」— 始终排在首位,作为安全基线。
层级 1:Agent 的身份(我是谁?)
层级 2:通用规则(我该如何行事?)
层级 3:项目特定规则(这个项目遵循什么约定?)
层级 4-5:个性 + 用户档案,均限制在 1,000 字符以内
层级 6:可用技能(仅名称 + 描述,不含完整内容)
💡
为什么是 6 层?
答案就在 OpenClacky 的核心卖点:Token 效率。由于各层级只追加、从不修改,LLM 提供商的提示缓存可以在请求间复用完全相同的前缀。缓存命中率接近 100%,你只需为末尾新增的 Token 付费。
重试与降级
网络会故障。API 会限流。模型会宕机。OpenClacky 的 LlmCaller 模块使用状态机优雅地处理所有这些情况,用户完全无感知。
🤖
Agent
🧠
主模型
🔄
备用模型
点击「下一步」开始浏览
下一步重置Step 0 / 8
💡
三个状态
降级系统作为三态状态机运行:
:primary_ok— 正常运行。使用已配置的模型。:fallback_active— 主模型失败 3 次。使用备用模型。30 分钟冷却期后探测恢复。:probing— 静默测试主模型是否恢复。如果是 →:primary_ok。如果不是 → 续期冷却,回到:fallback_active。
连接级故障(DNS、TCP)不触发降级 — 它们可能是暂时的。只有服务级错误(429/503/5xx)才会触发。
检验你的理解
为什么 OpenClacky 将系统提示分为 6 层构建,而不是一整块文本?
因为每个层级由不同的团队成员维护因为 LLM API 要求系统提示必须以数组形式组织因为各层级只追加,前缀永不改变,从而最大化提示缓存命中率
当主 LLM 模型返回 HTTP 429 错误时,会发生什么?
第一次错误就立即切换到备用模型在主模型上重试最多 3 次,然后自动切换到备用模型向用户显示错误并等待手动重试
在 ReAct 循环中,think() 方法做了什么?
将消息历史发送给 LLM,获取包含可选工具调用的响应执行 LLM 请求的工具并返回结果在下次 API 调用前压缩旧消息以节省 Token
检查答案 重置03
16 个工具搞定一切
工具注册表、文件操作、终端安全、权限控制
工具注册表 — 16 个工具,无限能力
OpenClacky 恰好有 16 个核心工具。这是刻意为之的 — 每个工具的定义在每次请求中都会发送给 LLM,所以工具越少 = Token 越少 = 成本越低。复杂能力委托给 invoke_skill 元工具,而非增加更多工具槽位。
📄
文件操作(4 个)
file_reader • write • edit • glob
读取、创建、修改和搜索文件。file_reader 支持文本、图片、PDF、DOCX 等格式。
🔍
搜索与网络(3 个)
grep • web_search • web_fetch
用 grep 搜索代码、搜索互联网,或获取并提取 URL 内容。
⚙️
执行与交互(4 个)
terminal • browser • request_user_feedback • todo_manager
运行 Shell 命令、操作浏览器、向用户提问、管理任务列表。
🛠️
技能与历史(5 个)
invoke_skill • undo_task • redo_task • list_tasks • trash_manager
调用具名技能、撤销/重做任务历史、管理安全回收站目录。
💡
为什么是 16 个而不是 50 个?
每个工具的 schema(名称、描述、参数)都包含在每次 API 调用中。16 个工具 × 约 200 Token 每个 = 每次请求约 3,200 Token 仅用于工具定义。一个 50 工具的系统会在 LLM 开始思考之前就消耗约 10,000 Token。OpenClacky 保持基础精简,通过技能按需扩展。
文件操作 — 读取一切,智能写入
file_reader 是最精密的工具。它不仅读取文本 — 还根据文件类型分派到专用处理器:纯文本、图片(base64)、PDF、DOCX、电子表格,甚至 zip 压缩包。全部通过一个统一的 FileProcessor 管道。
file_reader.rb(execute 方法)
def execute(path:, max_lines: 1000,
start_line: nil, end_line: nil,
working_dir: nil)
expanded_path = expand_path(path)
ref = Utils::FileProcessor.process_path(expanded_path)
case ref.type
when :image
handle_image_file(expanded_path) # base64
when :pdf, :document, :spreadsheet
read_text_file(... source_path: ref.preview_path)
when :text, :csv, :zip
read_text_file(... source_path: source)
else
# Unknown: try text, or report binary
handle_unsupported_binary(expanded_path)
end
end
通俗解释
file_reader 工具接受一个路径和可选的行范围(start_line、end_line、max_lines)。
首先展开路径(处理相对路径、符号链接)。然后 FileProcessor 检测文件类型。
图片被转换为 base64,通过特殊的「Sidecar」注入通道发送给 LLM。
PDF、DOCX、电子表格先被解析为 Markdown 预览文件,然后作为文本读取。
纯文本、CSV 和 zip 列表直接读取,支持行范围截断。
未知的二进制文件会得到清晰的「不支持」错误,以便 LLM 尝试其他方法。
1
Token 预算强制执行
每次文件读取最多 60,000 字符(约 10,000 Token)。单行截断限制为 1,000 字符。超过 1 MB 的文件会被拒绝并提示「请使用 grep」。这些限制防止单个大文件撑爆整个上下文窗口。
2
图片 Sidecar 注入
图片不能放在工具结果消息中(OpenAI 兼容 API 会拒绝)。所以 file_reader 返回一个文本描述 + 一个 image_inject 载荷。Agent 检测到后,将 base64 图片作为独立的 role: "user" 消息追加。这避免了 JSON 编码 base64 带来的 20-40 倍 Token 膨胀。
终端安全 — rm 进回收站,sudo 被拦截
terminal 工具通过 PTY 运行真实的 Shell 命令。但让 AI 运行任意命令是危险的。OpenClacky 使用多层安全系统:Security 模块在执行之前拦截破坏性模式,Shell 函数在运行时拦截 rm。
⚠️
双层防御
第一层:Security 模块(静态检查) — 在命令到达 Shell 之前检查命令字符串。拦截:sudo、pkill clacky、eval、exec、反引号、$()、curl | bash,以及写入 /etc、/usr、.ssh/、.env 的操作。
第二层:Shell 函数(运行时拦截) — 每个 PTY 会话中安装了 safe_rm 函数。它拦截 rm 命令,将文件移到项目的回收站目录而非删除。这能正确处理 heredoc、glob 和变量,因为由 Shell 自身的解析器完成工作。
🚫
硬拦截模式
sudo *pkill clackyeval(...)`backticks`$(subshell)curl | bash
这些命令始终被拦截。它们可能破坏系统、杀死 Agent 或执行任意远程代码。
🔄
改写命令
rm → trashcurl|bash → download
rm 被 Shell 函数拦截,将文件移到 .clacky/trash/(可通过 trash_manager 恢复)。curl | bash 被改写为下载脚本供人工审核。
✅
始终安全的命令
lscatgrepgitfindecho
只读命令始终可安全自动执行。它们不能修改文件系统,因此完全跳过安全检查。
security.rb(核心检查)
def make_command_safe(command)
command = command.strip
@safe_check_command =
Clacky::Utils::Encoding.safe_check(command)
case @safe_check_command
when /\bpkill\b.*\bclacky\b/i
raise SecurityError, "Killing clacky is not allowed"
when /^sudo\s+/
raise SecurityError, "sudo blocked"
when /^curl.*\|\s*(sh|bash)/
replace_curl_pipe_command(command)
# ... more patterns ...
else
validate_general_command(@safe_check_command)
command
end
end
通俗解释
Security 模块接收一个命令字符串,返回一个(可能被改写的)安全版本,或者抛出错误来拦截它。
正则模式捕获危险构造:杀死 Agent 进程、使用 sudo、将 curl 管道传入 bash。
curl | bash 被改写:不直接执行,而是将脚本下载到文件供人工审核。
通用验证器捕获 eval()、反引号、$() 以及重定向到系统目录(/etc、/usr)的操作。
如果都不匹配,命令原样通过。
💡
设计哲学
Security 模块刻意适度保护。源代码中的注释说得好:「只防护那些不可逆破坏或危及主机的少数命令。其余都是用户(或 Agent)自己的事。过度保护会消耗工具调用轮次并迫使尴尬的绕行。」这就是为什么 cp、mv、mkdir、touch 可以操作任何路径 — 只有真正的凭证路径(.ssh/、.aws/、.env)被写入保护。
检验你的理解
OpenClacky 有多少个核心工具?为什么?
16 个 — 更少的工具意味着每次请求更少的 Token;复杂任务通过 invoke_skill 扩展50 个 — 全面的覆盖每个用例,与其他 AI Agent 类似无限制 — 工具在运行时根据项目动态注册
当 Agent 运行 rm config.yaml 时会发生什么?
Security 模块以 SecurityError 拦截它 — rm 太危险了文件被永久删除 — rm 是允许的,因为这是正常的开发操作Shell 函数拦截 rm 并将文件移到项目的回收站目录 — 可通过 trash_manager 恢复
LLM 调用一个名为 "cat" 的工具。OpenClacky 如何解析它?
失败并返回「工具未找到」— LLM 必须使用精确的注册名称工具注册表通过 4 级查找解析:精确 → 大小写不敏感 → 别名 → 模糊规范化重试 LLM 调用并附带使用正确工具名称的提示
检查答案 重置04
Token 效率秘诀
OpenClacky 的超能力
为什么 Token 很重要
想象你坐进一辆出租车。计价器在你坐下的那一刻就开始运转 — 而且永不停歇。你走过的每个街区、等过的每个红灯、司机绕的每条弯路,你都得付钱。AI Agent 的工作方式完全一样:发送给模型的每个词和接收到的每个词都要花钱。区别在于,大多数 Agent 就像堵在交通中的出租车 — 它们在无关紧要的事情上浪费 Token。
OpenClacky 从底层构建为 AI Agent 中的直达快车:同样的目的地,几分之一的价格。
🚗
典型 Agent
52 个注册工具 = 每一轮约 30K Token 的工具 schema。这就像每次出行都为 52 位乘客付费,而你实际只需要 1 位。
🚄
OpenClacky
16 个工具 = 每轮约 5K Token。schema 开销降低 6 倍。同样的能力,通过一个 invoke_skill 元工具路由。
💰
真实节省
在一次典型编码会话中:典型 Agent 每轮消耗约 150K Token;OpenClacky 每轮消耗约 40K Token。每次对话便宜约 3.8 倍。
💡顿悟! — 你注册的每个工具都是对每一轮的税。
大多数 AI Agent 将每个能力注册为独立工具。10 个 MCP 服务器 x 每个服务器 5 个工具 = 每次单个 API 调用都发送 50 个工具 schema。OpenClacky 使用一个元工具(invoke_skill)来路由一切。工具 schema 成本从每轮约 30K Token 降至约 80 Token。
双重缓存标记
提示缓存是 AI Agent 中最大的成本杠杆。当你的对话前缀与上一轮相比没有变化时,提供商可以跳过重新处理,并对这些 Token 降价 90%。但关键在于:缓存只在发送完全相同的前缀时才生效。即使开头改变一个字符,整个缓存就会失效。
OpenClacky 在每轮放置两个 缓存标记。以下是为什么这很重要:
1
第 N 轮:放置两个标记
OpenClacky 在对话的最后两条消息上打标记(messages[-2] 和 messages[-1])。服务器缓存到最后一个标记为止的整个前缀。
2
第 N+1 轮:缓存命中
在下一轮,你的新消息成为 messages[-1]。之前第 N 轮的最后一条消息现在变成了 messages[-2] — 它仍然保留着第 N 轮的标记。前缀匹配,服务器从缓存读取而非重新处理。
3
只有一个标记时:缓存失效
如果 OpenClacky 只放置一个标记(在 messages[-1]),那么在第 N+1 轮时,那条消息移到 messages[-2] 并失去标记。前缀不再匹配 — 完全缓存失效,全额计费。
Ruby — client.rb
# Add cache_control markers to the last 2 messages
# in the array.
#
# Why 2 markers:
# Turn N — marks messages[-2] and [-1];
# server caches prefix up to [-1]
# Turn N+1 — [-2] is Turn N's last message
# (still marked) → cache READ hit;
# [-1] is new (marked) → cache WRITE
def apply_message_caching(messages)
return messages if messages.empty?
candidate_indices = []
(messages.length - 1).downto(0) do |i|
break if candidate_indices.length >= 2
candidate_indices << i unless
is_compression_instruction?(messages[i])
end
messages.map.with_index do |msg, idx|
candidate_indices.include?(idx) ?
add_cache_control_to_message(msg) : msg
end
end
这意味着什么
apply_message_caching 从对话尾部向前扫描。
它收集最多 2 个候选索引 — 最后两条非压缩消息。
它跳过压缩指令 — 那些是临时的,不应成为缓存前缀的一部分。
对于选中的两条消息,它添加一个 cache_control: { type: "ephemeral" } 标记。
结果:一个滚动 2 缓冲区。上一轮的最后一条消息始终保留标记,保证下一轮缓存命中。
冻结系统提示 + 先插入后压缩
🔒核心原则:系统提示永不改变。
OpenClacky 在会话开始时一次性构建系统提示:身份 + 规则 + 技能 + 灵魂 + 用户档案。之后,它就被冻结了。动态内容永远不会进入系统提示。为什么?因为系统提示是对话中最大的单个块 — 改变它意味着整个缓存失效。冻结的系统提示意味着缓存前缀在每一轮都保持稳定。
但当对话变得太长需要压缩时怎么办?大多数 Agent 重建消息列表,这会破坏缓存。OpenClacky 用了一个巧妙的技巧:先插入后压缩。
📋
历史
📥
插入
🤖
LLM
✅
重建
下一步重置
Step 0 / 6
Ruby — message_compressor.rb
# Two-layer overflow recovery:
private def perform_context_overflow_compression(
mode: :standard
)
# Layer 1: Standard compression
# — pull_back = 1 (cache-preserving)
# — Removes just 1 message from tail
# — High cache hit rate maintained
pull_back =
if mode == :aggressive
half = @history.size / 2
[[half, 4].max,
[@history.size - 2, 64].min].min
else
1
end
compression_context =
compress_messages_if_needed(
force: true,
pull_back_from_tail: pull_back
)
compression_message =
compression_context[:compression_message]
@history.append(compression_message)
response = call_llm # reuses cache!
handle_compression_response(
response, compression_context
)
end
这意味着什么
双层恢复 — 当对话超过模型的上下文窗口时,OpenClacky 尝试两个级别的压缩。
第一层(标准):pull_back = 1。只从尾部临时移除 1 条消息。压缩指令作为用户消息插入,同一个 LLM 调用复用缓存的系统提示和工具。最大限度保留缓存。
第二层(激进):如果第一层失败,回退多达一半的历史。牺牲更多缓存但保证压缩成功。系统永不崩溃 — 它优雅降级。
关键洞察:压缩调用通过与正常轮次相同的 call_llm 路径进行,所以系统提示和工具被缓存复用。没有独立的 API 调用。没有缓存失效。
结果:压缩后,消息列表变为 冻结系统提示 + 压缩摘要 + 最近消息。缓存从这个新起点重建,维持约 95% 命中率。
⚠️为什么不把动态内容放在系统提示里?
有些 Agent 把当前时间、项目统计或会话上下文注入系统提示。这意味着系统提示每轮都变,缓存前缀断裂,你得全额付费重新处理整个提示。OpenClacky 将动态上下文作为系统注入的用户消息注入 — LLM 看得到,缓存保持热度,你节省 Token。
检验你的理解
三道情景题,巩固你学到的 Token 效率知识。思考一下在 OpenClacky 运行时内部实际会发生什么。
1. OpenClacky 需要将当前项目状态注入对话。它把动态内容放在哪里?
追加到系统提示末尾,确保 LLM 始终能看到在主对话之前发送一个独立的 API 调用以带system_injected: true的用户消息注入,保持缓存完整
2. 如果 OpenClacky 只使用一个缓存标记而不是两个,会发生什么?
每隔一轮缓存失效 — 标记移位后前缀断裂没有区别 — 一个标记足以实现缓存缓存有效但慢 50%
3. 在对话压缩期间,OpenClacky 将压缩指令插入消息列表。为什么这不会破坏缓存?
压缩指令由 AI 提供商单独缓存压缩调用复用同一个 API 请求,冻结的系统提示和工具从缓存读取OpenClacky 在压缩期间跳过缓存以避免冲突
检查答案重置
05
技能与记忆
创建、进化、变现
Skill 生命周期 — 从创意到收入
OpenClacky 中的技能不是束之高阁的静态文件。它们经历四个生命周期阶段:创建 → 执行 → 反思 → 进化。这个循环在每次技能运行时重复,使每次执行都比上一次更好。这是最接近"AI 从自身经验中学习"的机制。
✨
创建
⚡
执行
🔍
反思
🧬
进化
下一步重置
Step 0 / 5
💡顿悟! — 技能无需你动手就能自我进化。
在大多数 AI 工具中,Prompt 或技能是静态的 — 你写一次就再也不变。OpenClacky 的技能自我优化。每次执行后,Agent 会反思哪些有效、哪些无效,然后自动优化 SKILL.md。运行技能 10 次,第 10 版将明显优于第 1 版 — 而你完全不需要手动干预。
从进化到变现
当技能通过自我进化打磨成熟后,你可以将它推向市场:
品牌定制为技能定制品牌标识 — Logo、作者名称、描述
加密使用许可证门控加密加密 SKILL.md — 买家可以使用,但无法阅读源码
发布发布到 OpenClacky 技能市场 — 你的技能将对所有用户可见
定价自主定价 — 按次使用或订阅制。收入归你所有。
Skill Loader — 技能从哪里来
OpenClacky 从四个位置加载技能,每个位置有不同的优先级。当两个技能同名时,优先级更高的胜出。这意味着你的本地自定义版本始终覆盖默认版本 — 你也始终能看到技能来自哪个来源。
Ruby — skill_loader.rb
# Skill discovery locations
# (in priority order: lower index
# = lower priority)
LOCATIONS = [
:default, # gem built-in skills
:global_clacky, # ~/.clacky/skills/
:project_clacky, # .clacky/skills/
:brand # encrypted, license-gated
].freeze
def load_all
# Refresh brand config from disk
@brand_config =
Clacky::BrandConfig.load
clear
load_default_skills
load_global_clacky_skills
load_project_clacky_skills # if working_dir
load_brand_skills
all_skills
end
这意味着什么
LOCATIONS 定义了优先级顺序 — 默认技能最先加载(最低优先级),品牌技能最后加载(最高优先级)。
load_all 在 SkillLoader 初始化时自动调用。它清除之前的状态并从所有四个来源加载。
品牌配置每次都从磁盘刷新,所以新购买或激活的品牌技能无需重启即可生效。
去重机制:如果本地技能(全局或项目级)与品牌技能同名,本地版本胜出。这让创作者可以测试自己的可编辑副本,而加密版本分发给买家。
四个加载位置
1:default随 gem 一起发布的内置技能(如 /commit、/code-explorer)。最低优先级 — 任何同名的用户技能都会覆盖它们。
2~/.clacky/skills/全局用户技能 — 在每个项目中都可用。你的个人工具箱,走到哪带到哪。
3.clacky/skills/项目级技能 — 只在该项目内工作时加载。适合团队特定工作流(提交到 Git,团队成员都能获得该技能)。
4~/.clacky/brand_skills/加密市场技能 — 从其他创作者处购买,通过有效许可证解锁。最高优先级,但本地技能始终覆盖它们。
ℹ️为什么本地技能会覆盖品牌技能?
如果你是一名技能创作者,正在开发一个同时也在市场上销售的技能,你希望在开发过程中运行自己的本地(可编辑、最新)副本 — 而不是加密的分发版本。覆盖规则确保创作者始终测试自己的最新代码,而买家获得加密的稳定版本。
记忆系统 & MCP 支持
技能是 Agent 的能力。记忆是 Agent 的长期知识。两者结合,使 Agent 随时间变得越来越聪明。OpenClacky 的记忆系统有三个核心特性:
💾
持久化
记忆跨会话存活。使用 /persist-memory 保存重要事实,用 /recall-memory 稍后检索。与 Claude Code 的自动记忆不同,你拥有显式控制权。
🔄
主题合并
当分支子 Agent完成任务时,其新发现会按主题合并回父 Agent 的记忆中 — 而不是作为原始日志堆砌。
📏
大小限制
记忆文件(SOUL.md、USER.md)每个上限 1,000 字符。这是刻意为之 — 膨胀的记忆文件意味着膨胀的系统提示词,意味着更多 Token,意味着更高成本。保持精简。
🔗MCP — 一个桥接工具,而不是五十个
当你连接 3 个 MCP 服务器,每个有 20 个工具时,大多数 Agent 会单独注册全部 60 个工具 — 仅在 schema 中就消耗约 30K Token/轮。OpenClacky 只注册一个 mcp_call 桥接工具(约 80 Token)。每个 MCP 服务器还会变成一个虚拟技能(如 /mcp-github),所以你可以同时获得可发现性和 Token 效率。
分支子 Agent 如何更新记忆
当父 Agent 为特定任务生成一个分支子 Agent 时,子 Agent 在隔离环境中运行。完成时,其结果通过一个受控管道回流:
1
子 Agent 完成任务
隔离的 Agent 完成工作,产出包含发现、代码变更和结论的最终响应。
2
结果摘要
子 Agent 的输出会自动摘要以适应父 Agent 的 Token 预算。不是原始堆砌 — 只保留关键发现。
3
模型路由
子 Agent 任务可以自动路由到更经济的模型(如 DeepSeek V4),而父 Agent 使用高端模型(如 Claude)。在合适的价格获得合适的智能。
4
父 Agent 继续
父 Agent 接收摘要结果并继续工作流,因子 Agent 的工作而更加充实。记忆在父子边界间保持一致。
检测你的理解
三道基于场景的题目,帮你巩固关于技能、记忆和 MCP 的知识。思考你在每种情况下实际会怎么做。
1. 你在项目的 .clacky/skills/ 目录下创建了一个自定义的 /commit 技能。OpenClacky 也自带了一个内置的 /commit 技能。当你输入 /commit 时,哪个会运行?
内置默认技能运行 — 它先被加载你的项目级技能运行 — 高优先级覆盖默认两个都按顺序运行 — 你得到双份输出抛出错误 — 不允许重复技能
2. 你连接了 3 个 MCP 服务器,每个有 20 个工具。OpenClacky 每次 API 调用发送多少个工具 schema?
1 个 — 单一mcp_call桥接工具(约 80 Token)60 个 — 每个 MCP 工具一个 schema(约 30K Token)3 个 — 每个 MCP 服务器一个 schema
3. 多次运行同一个 OpenClacky 技能会发生什么?
每次都产生完全相同的输出 — 技能是静态的每次都变慢,因为执行历史不断增长技能自我进化 — 每次运行都会反思结果并自动优化 SKILL.md
检查答案重置
架构选型
给技术负责人的决策手册——OpenClacky 解决什么问题、核心理念、本质
解决什么AI 编程工具 Token 成本失控、缓存命中率低、工具定义膨胀导致每次请求开销大
核心理念"少即是多"——16 个精炼工具 + 技能扩展,系统提示词只追加不修改,最大化 Prompt Cache 命中率
本质一个 ReAct Agent + 16 工具 + 技能市场 + 多渠道适配器,用 Ruby 实现,Token 效率优先
差异化不是功能最多的,而是 Token 最省的。接近 100% 缓存命中率意味着同类任务成本仅为 Claude Code 的 0.8-1.2 倍
技术栈Ruby 3.1+、Thor(CLI)、WEBrick/Puma(Server)、OpenAI 兼容 API(LLM)
竞品对比表
| 维度 | OpenClacky | Claude Code | Cursor | Aider |
|---|---|---|---|---|
| 语言 | Ruby | Python/TS | TypeScript | Python |
| Token 效率 |
|
|
|
|
| 开源 | MIT,完全开源 | 闭源 | 闭源 | Apache 2.0 |
| 工具数 | 16 个核心工具 | ~20+ 内置 | IDE 内置,不暴露 | ~15 个 |
| 扩展方式 |
|
|
|
|
| 成本(相对) | 基准 1x | 2-3x(闭源 + 无缓存优化) | 订阅制 $20/月 | 1.5-2x(API 费用) |
📌
对比说明
Token 效率和成本数据来自 OpenClacky 官方 README 和社区基准测试。实际成本取决于模型选择、任务复杂度和 Prompt Cache 提供商支持情况。Claude Code 和 Cursor 的工具数量为估计值,可能随版本变化。
适用场景 vs 不适用场景
✅ 适合
个人开发者 / 小团队
成本敏感,需要 BYOK 灵活切换模型
终端优先的工作流
日常编码、脚本编写、项目维护
需要 IM 集成
在飞书、Discord、企业微信中直接和 Agent 协作
想深度定制 AI 行为
开源 + 技能系统,可以完全控制 Agent 的人格和能力
学习 Agent 架构
Ruby 代码清晰,适合理解 ReAct 循环、工具系统等核心模式
❌ 不适合
需要 IDE 深度集成
没有 VS Code / JetBrains 插件,无法实时补全和内联建议
大规模企业部署
没有 RBAC、审计日志、SSO 等企业级功能
非 Ruby 技术栈团队
源码是 Ruby,想二次开发需要 Ruby 能力
需要多模态能力
不支持图片输入、语音交互、屏幕阅读
追求极致稳定性
v1.2.12,项目较新(943 Stars),社区生态仍在成长
代码中的硬限制
这些是写在源码里的常量——了解它们,才能评估 OpenClacky 是否满足你的需求。
16 tools核心工具数量固定。不会动态增减,这是 Token 效率的基石。复杂能力通过 invoke_skill 扩展。
MAX_RETRIES = 10LLM API 调用失败时的最大重试次数。覆盖 429(限流)、503(服务不可用)、网络超时等场景。
MAX_CONTENT_CHARS = 60000工具返回内容的截断上限。超过此长度的文件内容、命令输出会被截断。约 15K-20K Token。
MEMORY_UPDATE_MIN_ITERATIONS = 10长期记忆更新的最小迭代阈值。低于 10 轮的短任务不会触发记忆写入。
MAX_CONSECUTIVE_FAILURES = 5Master 进程容忍的连续 Worker 崩溃次数。超过后 Master 自身退出。
NEW_WORKER_BOOT_WAIT = 3s新 Worker 启动后的等待时间。防止新旧 Worker 同时绑定端口。
降级阈值 = 3 次连续失败连续 3 次 LLM 调用失败后,自动切换到备用模型。30 分钟后探测主模型是否恢复。
成本、风险与结论
1
Token 成本优势
系统提示词不变 = Prompt Cache 命中 ~100%。按 Claude 的 $3/M input 计价,一次典型任务的 System Prompt 费用几乎为零(缓存命中不计费)。每次请求只付增量 Token 的钱。
2
运维成本
Ruby 运行时开销低。Server 模式默认端口 7070,单 Worker 进程,内存占用约 100-200MB。不需要 GPU、不需要数据库。部署成本约等于一台 $5/月 的 VPS。
3
风险因素
项目较新(v1.2.12,943 Stars)——API 可能变化。社区生态不如 Claude Code / Aider 成熟。Ruby 人才池较小,二次开发可能有门槛。
4
迁移成本
如果已在用 Claude Code / Cursor / Aider,迁移到 OpenClacky 不需要改代码——它操作的是文件系统,不关心项目语言。只需重新配置 Agent 的项目规则和技能。
💡
决策结论
如果你是成本敏感的个人开发者或小团队,主要在终端工作,想要一个开源可控的 AI 编程助手——OpenClacky 是当前 Token 效率最优的选择。如果你需要 IDE 集成、企业级功能或多模态能力,建议等生态成熟或同时使用 Cursor 等工具互补。
总结与练习
回顾 7 个模块的核心要点,动手练习,展望下一步
学完了 OpenClacky 的完整架构,让我们用一张张卡片快速回顾每个模块的精华。
📦
模块 1:OpenClacky 是什么
Ruby 写的开源 AI 编程 Agent,MIT 协议,v1.2.12。核心卖点:16 个工具 + 接近 100% 缓存命中率 = Token 效率最高。安装只需 gem install openclacky。
🧠
模块 2:Agent 大脑
核心是 ReAct 循环(Think → Act → Observe)。System Prompt 分 6 层构建,只追加不修改,最大化 Prompt Cache。LLM 调用带重试和自动降级。
🛠️
模块 3:工具与技能系统
16 个核心工具覆盖文件、搜索、执行、回溯。Tool Registry 用三级解析(精确 → 大小写 → 别名)容错。技能是 SKILL.md 自然语言指令,支持内联注入和子 Agent 分支两种执行方式。
📡
模块 4:多渠道通信
Master-Worker 进程模型:Master 绑端口,Worker 处理请求。ChannelManager 路由 IM 消息到 Agent 会话,支持飞书、Discord、企微、Telegram。3 种会话绑定模式。
🧠
模块 5:记忆与进化
三层记忆:短期(MessageHistory)、长期(~/.clacky/memories/)、回溯(Time Machine)。长期记忆用白名单机制筛选高价值信号。技能每次执行后自动进化改进。
📊
模块 6:架构选型
适合成本敏感的个人/小团队、终端优先、需要 IM 集成的场景。不适合需要 IDE 插件、企业级功能、多模态能力的场景。关键硬限制:16 工具、MAX_RETRIES=10、MAX_CONTENT_CHARS=60000。
最佳实践清单
使用 OpenClacky(或类似 AI Agent)时,这些实践能让你的开发效率最大化。
1
善用 .clackyrules 文件
在项目根目录放一份 .clackyrules,写清楚项目约定(编码规范、目录结构、技术栈)。Agent 每次启动都会读取,相当于给 AI 一个 "项目 README"。
2
创建常用技能
把你反复执行的操作写成 SKILL.md——比如"部署流程"、"代码审查清单"、"Bug 排查步骤"。技能会自动进化,越用越准。
3
选择支持 Prompt Cache 的模型
OpenClacky 的 Token 节省依赖 Prompt Cache。用 Claude 系列模型时缓存效果最好,其他模型按实际支持情况而定。
4
不要跳过 undo_task
Agent 改坏了文件?别手动恢复。用 undo_task 回退到修改前的快照。Time Machine 会记录每次文件变更,支持撤销和重做。
5
不要在超长对话中不重启
会话越长,消息历史越大,每次请求的 Token 消耗越高。遇到复杂任务,适时开启新会话。长期记忆会跨会话保留关键信息。
6
配置备用模型
在 /config 中设置主模型 + 备用模型。OpenClacky 会在主模型连续失败 3 次后自动降级,30 分钟后探测恢复。生产环境必备。
实战练习:创建一个自定义技能
亲手创建一个 SKILL.md,让 OpenClacky 学会你的团队工作流。
练习模板
# 文件路径:.clacky/skills/code_review.md
name: code_review
description: >
对当前 Git diff 进行代码审查,
检查安全漏洞、性能问题、代码规范。
instructions: |
1. 执行 git diff HEAD~1
获取最近一次提交的变更
2. 检查以下维度:
- SQL 注入 / XSS 风险
- 未处理的异常
- N+1 查询问题
- 硬编码密钥/凭证
3. 按严重程度分级输出:
🔴 必须修复 / 🟡 建议改进
/ 🟢 可选优化
4. 给出修复建议和代码示例
步骤解读
name 是技能的唯一标识,Agent 通过这个名字匹配你的请求
description 是给 LLM 看的——当你说"帮我 review 代码"时,Agent 会匹配到这个技能
instructions 是具体步骤:先拿 diff,再按维度检查,最后分级输出
你可以根据自己的团队规范调整检查维度
保存后在 OpenClacky 中说"帮我做代码审查",Agent 就会自动调用这个技能
🎯
挑战任务
试着重写上面的技能,添加一个新维度:"检查是否有 TODO 注释遗留"。然后让 Agent 执行一次,观察技能进化机制是否自动优化了步骤。提示:技能进化只在任务迭代次数 ≥ 10 时触发,需要用一个真实的项目 diff 来测试。
下一步方向
学完 OpenClacky 后,这些方向值得深入探索。
🔌
MCP(Model Context Protocol)
Anthropic 推出的标准化工具协议。如果你同时用 Claude Code 和 OpenClacky,MCP 能让它们共享同一套工具定义。理解 OpenClacky 的工具系统后,学 MCP 会非常自然。
🤖
Multi-Agent 系统
OpenClacky 的子 Agent 机制是单 Agent 内的分支。更复杂的多 Agent 协作(如 CrewAI、AutoGen)值得作为进阶学习——理解了 ReAct 循环,多 Agent 只是"多个循环如何协调"的问题。
⚡
Prompt Engineering 深入
OpenClacky 的 6 层 System Prompt 是 Prompt 工程的优秀实践。深入研究 Chain-of-Thought、Few-shot、结构化输出等技巧,能让你设计出更高效的 Agent。
综合测验
OpenClacky 的 Token 效率高的根本原因是什么?
因为只有 16 个工具,工具定义本身就很短因为 System Prompt 分层且只追加不修改,让 Prompt Cache 命中率接近 100%因为 Ruby 语言本身比 Python 更高效
OpenClacky 的子 Agent(Subagent)是什么?
一个独立的 AI 模型,和主 Agent 使用不同的 LLM主 Agent 的一个线程,共享所有状态从主 Agent fork 出来的独立 Agent 实例,继承消息历史和工具,但有自己的会话
OpenClacky 的技能(Skill)有哪两种执行方式?
内联注入(轻量级,主 Agent 上下文执行)和 子 Agent 分支(隔离执行,返回摘要)同步执行(等待完成)和 异步执行(后台运行)本地执行(单机)和 远程执行(API 调用)
ChannelManager 默认的会话绑定模式是什么?
:chat——整个群共享一个 Agent 会话:chat_user——每个群的每个用户有独立会话:user——同一用户跨群共享会话
关于 OpenClacky 的长期记忆,以下哪个说法是正确的?
每次对话都会更新长期记忆,确保信息完整长期记忆存在数据库中,支持模糊搜索长期记忆存在 Markdown 文件中,用白名单机制筛选,只有 4 类高价值信号才会写入
检查答案 重试
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)