从零到一,用 10 步构建一个面向 Coding Agent 的 CLI 可观测运行时,项目地址:weak-claw,欢迎各位读者点Star⭐。
写在前面
你有没有好奇过 Claude Code、Cursor Agent、Copilot Workspace 这些 AI 编程工具背后的 Agent Runtime 是怎么实现的?
- 它怎么管理上下文,让 100+ 步的长任务不崩?
- 工具调用震荡(反复读目录→读文件→再读目录)怎么防?
- 日志、指标、代码审查这些旁路逻辑怎么不侵入主流程?
如果你也有这些疑问,这个项目就是为你准备的。
Myclaw 是一个面向 Coding Agent 的 CLI 可观测运行时,技术栈为 TypeScript + Node.js + Oclif + OpenAI SDK + EventBus。我把整个实现过程拆成了 10 个递进式步骤,每一步都有完整的代码和配套学习文档,帮你从"调通一个 API"走到"构建一个工程化的 Agent 系统"。
这个项目解决什么问题?
在多轮 Coding Agent 任务中,三个核心痛点几乎不可避免:
| 痛点 | 表现 | 后果 |
|---|---|---|
| 上下文膨胀 | Agent 多轮工具调用快速打满上下文窗口 | 早期关键信息丢失,任务失败 |
| 工具调用震荡 | 陷入"读目录→读文件→再读目录"死循环 | Token 白白消耗,无实质产出 |
| 运行时与监控强耦合 | 日志、指标散落在业务逻辑各处 | 每次加监控都要改核心代码,迭代成本高 |
围绕 稳定性与可观测性 两个目标,本项目落地了三大核心能力:
1. 多级上下文管理
构建"跨会话长期记忆 + 压缩摘要块(Summary Blocks) + 滑动窗口"分层记忆架构:
┌─────────────────────────────────────────┐
│ Layer 1: 全量消息 (session.messages) │ ← 完整保留,不删除
├─────────────────────────────────────────┤
│ Layer 2: 压缩摘要 (Summary Blocks) │ ← 每 20 条消息批量压缩
├─────────────────────────────────────────┤
│ Layer 3: 滑动窗口 (最近 20 条) │ ← 实际发给模型的上下文
└─────────────────────────────────────────┘
通过路径索引实现无损压缩与按需回溯,兼顾 Token 成本与长任务逻辑连续性。压缩比约 20:1,长任务从"20 步超限崩溃"变成"100+ 步稳定运行"。
2. 异步代码审查闭环
设计写后异步代码审查旁路——Agent 写完代码后,后台自动跑语法检查和 ESLint,失败结果在下一个循环步骤自动注入,触发模型自修复:
Agent 写文件 → write_completed 事件
↓
EslintCheckSubscriber(后台异步)
├── Node.js 语法检查 (node --check)
├── Python 语法检查 (python3 -m py_compile)
└── ESLint 软门禁 (npx eslint)
↓ 失败
CheckGate(全局消费式队列)
↓ Agent 循环下一步 popFailures()
注入 tool_result → 模型自动修复
不阻塞主流程,审查异常不打断 Agent 执行。
3. 运行时与监控解耦
引入 EventBus + Subscriber 模型,Agent 循环只负责发射事件,所有旁路逻辑(日志、指标、代码审查、用户档案提取)通过 Subscriber 订阅处理:
Agent 循环 → emitEvent() → EventBus
↓
┌──────────────┬──────────────┬──────────────┐
│ SessionLog │ Metrics │ EslintCheck │
│ (JSONL 日志) │ (运行指标) │ (代码审查) │
└──────────────┴──────────────┴──────────────┘
新增监控需求?写一个 Subscriber 即可,零侵入核心逻辑。
项目架构全景
┌────────────────────┐
│ CLI Layer │
│ (Oclif Commands) │
│ chat / run / hello │
└────────┬───────────┘
│
┌────────▼───────────┐
│ Config Layer │
│ Zod Schema │
│ + cosmiconfig │
│ + dotenv │
└────────┬───────────┘
│
┌──────────────────────▼──────────────────────┐
│ Agent Core (agent.ts) │
│ │
│ ┌──────────┐ ┌───────────┐ ┌──────────┐ │
│ │ Session │ │ ReAct │ │ Context │ │
│ │ Manager │ │ Loop │ │ Manager │ │
│ └──────────┘ └───────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌───────────┐ ┌──────────┐ │
│ │ Tool │ │ JSON │ │ Safety │ │
│ │ Executor │ │ Fallback │ │ Guard │ │
│ └──────────┘ └───────────┘ └──────────┘ │
└──────────┬─────────────────────┬───────────┘
│ │
┌──────────▼──────┐ ┌──────────▼──────┐
│ Provider Layer │ │ EventBus │
│ Mock / OpenAI │ │ (publish) │
└─────────────────┘ └────────┬────────┘
│
┌────────────────────────┬┴───────────────┐
│ │ │
┌───────▼───────┐ ┌─────────▼──────┐ ┌─────▼────────┐
│ SessionLog │ │ Metrics │ │ EslintCheck │
│ Subscriber │ │ Subscriber │ │ Subscriber │
│ (JSONL 日志) │ │ (运行指标) │ │ (代码审查) │
└───────────────┘ └────────────────┘ └──────────────┘
10 步学习路线
本项目采用 递进式构建 —— 每一步在前一步基础上增量添加新能力,最终拼合成完整系统。
| 步骤 | 主题 | 学习文档 | 关键知识点 |
|---|---|---|---|
| 1 | 项目脚手架 + 类型定义 + Mock Provider | 01-scaffolding.md | Oclif CLI 框架、LLMProvider 接口抽象、三层配置系统(Zod + cosmiconfig + dotenv) |
| 2 | 最简 Agent 循环(单轮,无工具) | 02-basic-agent-loop.md | 会话管理(InMemorySessionStore)、系统提示词构建、Agent 单轮执行流程 |
| 3 | 工具定义与执行 | 03-tools.md | JSON Schema 工具定义、6 个工具实现(read/write/patch/list/search/shell)、路径安全验证 |
| 4 | 多轮 ReAct 循环 + 工具调用链 | 04-multi-turn-tools.md | ReAct 循环(for step < maxSteps)、JSON Fallback 三级降级解析、振荡检测(repeatRatio/noveltyRatio) |
| 5 | EventBus + 基础 Subscriber | 05-eventbus.md | 发布/订阅模式、AgentEvent 联合类型(15+ 种事件)、Subscriber 异常隔离、Promise 链写入 |
| 6 | 会话持久化与恢复 | 06-session-persistence.md | JSONL 追加写入、两轮遍历状态重建、readPaths/compressedCount 精确恢复 |
| 7 | 上下文管理(滑动窗口 + 压缩摘要) | 07-context-management.md | 三级分层记忆、孤立 tool 消息裁剪、压缩触发策略、路径索引 |
| 8 | 异步代码审查闭环 | 08-check-gate.md | CheckGate 消费式队列、EslintCheckSubscriber 三类检查、异步非阻塞设计 |
| 9 | 用户档案系统 | 09-user-profile.md | 被动信号提取、跨会话持久化、system prompt 融入 |
| 10 | OpenAI Provider + 完整 CLI | 10-complete-cli.md | OpenAI SDK 接入、超时+重试+取消机制、交互式 readline Chat 命令 |
两种学习方式
方式一:跟着代码动手做
- 克隆仓库,从 Step 1 开始,对照每一步的文档和源代码逐步实现
- 每一步都可编译运行验证,确保理解后再进入下一步
- 适合想深入理解每行代码的同学
方式二:只看文档快速了解
- 直接阅读
docs/目录下的 10 篇学习文档 - 每篇文档包含:本步目标、新增文件说明、核心概念、关键代码解读、设计决策分析
- 适合想快速掌握 Agent 系统架构思想的同学
技术栈
| 技术 | 作用 |
|---|---|
| TypeScript | 类型安全的开发语言 |
| Node.js | 运行时环境 |
| Oclif | CLI 框架,命令自动发现与注册 |
| OpenAI SDK | LLM 调用(兼容 OpenAI API 格式的后端均可使用) |
| Zod | 配置 Schema 校验 |
| cosmiconfig | 多来源配置加载 |
| EventBus(自研) | 事件驱动架构,~50 行代码,轻量可控 |
快速开始
# 1. 克隆仓库
git clone https://github.com/<your-username>/weak-claw.git
cd weak-claw
# 2. 安装依赖
npm install
# 3. 编译
npm run build
# 4. Mock 模式体验(无需 API Key)
MYCLAW_PROVIDER=mock node ./bin/dev.js run "用 TypeScript 写一个 hello world"
# 5. 交互式聊天(Mock 模式)
MYCLAW_PROVIDER=mock node ./bin/dev.js chat
# 6. 接入真实模型(需要 OpenAI API Key)
cp .env.example .env
# 编辑 .env 填入 OPENAI_API_KEY
node ./bin/dev.js chat
学完之后你能收获什么?
工程能力提升
- Agent 系统全链路理解:从 CLI 入口 → 配置加载 → 会话管理 → ReAct 循环 → 工具执行 → 上下文管理 → 事件驱动,掌握 Coding Agent 系统的完整工程架构
- 设计模式实战:Provider 工厂模式、发布/订阅模式、策略模式(上下文压缩)、消费式队列、Promise 链顺序写入等,每个模式都有真实场景驱动
- 防御性编程:路径安全验证、写前必读机制、循环兜底、振荡检测、监控异常隔离——这些都是生产级 Agent 系统必须考虑的问题
知识体系构建
- 上下文管理:理解为什么简单的"截断"不够用,分层记忆架构如何在 Token 成本和信息完整性之间取得平衡
- 可观测性工程:EventBus + Subscriber 如何实现"加监控不改业务代码",以及 JSONL 日志为什么比数据库更适合 CLI 场景
- LLM 工程化:JSON Fallback 解析、多模型兼容、超时重试取消——这些是 LLM 应用从 demo 到生产的关键差距
面试加分项
项目中附带了一份详细的 面试准备指南,包含:
- 2-3 分钟项目介绍话术
- 三大核心能力的深入展开
- 4 个真实技术难点与解决方案
- 8 个高频面试追问及参考回答
- 项目架构全景图(白板讲解用)
面试项目介绍(精简版)
Myclaw 是一个面向 Coding Agent 的 CLI 可观测运行时。
做这个项目的背景是:在多轮 Coding Agent 任务中,我发现三个核心痛点——上下文膨胀、工具调用震荡、运行时与监控强耦合。
针对这三个问题,我落地了三大核心能力:
- 多级上下文管理:构建"全量消息 + 压缩摘要块 + 滑动窗口"三级分层架构,压缩比 20:1,长任务从 20 步崩溃到 100+ 步稳定运行
- 异步代码审查闭环:写后自动触发语法/lint 检查,失败结果通过消费式队列注入 Agent 循环,触发模型自修复,全程异步不阻塞
- EventBus 解耦:Agent 只管发射事件,日志/指标/审查/档案都通过 Subscriber 订阅,新增监控零侵入核心逻辑
技术栈是 TypeScript + Node.js + Oclif + OpenAI SDK + 自研 EventBus,核心代码约 3000 行。
更多面试细节请查看 面试准备指南。
项目结构
src/
├── commands/ # CLI 命令
│ ├── chat.ts # 交互式多轮对话
│ ├── run.ts # 一次性任务执行
│ └── hello.ts # 测试命令
├── config/ # 配置系统
│ ├── schema.ts # Zod Schema 定义
│ ├── load-config.ts # 三层配置加载
│ └── paths.ts # 路径管理
├── core/ # Agent 核心
│ ├── agent.ts # 会话管理 + ReAct 循环 + 上下文管理(~1300 行)
│ ├── event-bus.ts # EventBus 实现
│ ├── session-store.ts# 内存会话存储
│ ├── check-gate.ts # 审查消费式队列
│ ├── user-profile.ts # 用户档案读写
│ └── subscribers/ # 4 个 Subscriber
│ ├── session-log-subscriber.ts
│ ├── metrics-subscriber.ts
│ ├── eslint-check-subscriber.ts
│ └── user-profile-subscriber.ts
├── providers/ # LLM Provider 抽象
│ ├── types.ts # 接口定义
│ ├── mock-provider.ts# Mock(开发测试)
│ └── openai-provider.ts # OpenAI(生产)
└── tools/ # 工具实现
├── filesystem.ts # 文件操作(read/write/patch/list/search)
└── shell.ts # Shell 命令执行