凌晨三点,当终端里的 jarvis status 终于显示「🟢 运行中」时,我长舒一口气。
这只「数码蛋」终于有了心跳。
背景:为什么要造 Jarvis?
昨天写完《注意力工程》那篇博文后,一个想法开始在脑海中挥之不去:
既然 Claude 的 Skills 系统让我效率倍增,为什么不造一个专属于我的、能不断进化的 AI 助手?
不是那种通用的聊天机器人,而是一个真正理解我的工作、能主动探索我的项目、随着使用不断进化的数码宝贝。
于是,Jarvis-Agent 诞生了。
核心理念
🥚 空白开始 → 🔍 主动探索 → ⚡ 能力生成 → 🦋 持续进化
设计原则很简单:一点不多,一点不少。
每个模块都必须服务于 Agent 的核心进化能力,微信集成、Web 界面这些「应用层」的东西,都不属于核心。
挑战:从想法到实现
挑战 1:如何让 Agent 「活」起来?
第一个大问题是:一个「活」的 Agent 需要什么?
我画了一个五维能力模型:
| 维度 | 能力 | 核心问题 |
|---|---|---|
| 👁️ 感知 | 探索、监控 | Agent 如何发现世界? |
| 🧠 记忆 | 存储、检索、关联 | Agent 如何记住经历? |
| 💭 思考 | 推理、规划、决策 | Agent 如何形成判断? |
| 🦾 行动 | 执行、工具调用 | Agent 如何改变世界? |
| 🔄 进化 | 自学习、Skill 生成 | Agent 如何提升自己? |
Phase 1 的目标很明确:先让它有感知和记忆能力,再加上基础的思考(LLM 对话)。
挑战 2:守护进程的设计
一个真正的 Agent 不能只在你调用它时才存在。它需要一个「心跳」——一个后台守护进程,持续监控环境变化。
技术选型:
# daemon/daemon.py 核心架构
async def run_daemon():
"""Jarvis 心跳主循环"""
# 1. 初始化文件监控 (watchdog)
observer = Observer()
observer.schedule(JarvisFileHandler(), watch_path, recursive=True)
# 2. 启动心跳循环
while True:
await heartbeat() # 更新状态
await think() # 定期思考(Phase 2)
await asyncio.sleep(think_interval)
这里有个坑:httpx 的代理问题。
我的本地环境跑着 Clash 代理,结果 httpx 默认会读取环境变量中的代理配置,导致调用本地的 Agent Maestro 时返回 502。
Debug 了半小时才发现问题:
# ❌ 会走系统代理
client = httpx.AsyncClient(timeout=60.0)
# ✅ 禁用环境代理
client = httpx.AsyncClient(timeout=60.0, trust_env=False)
这个小改动让一切都通了。
挑战 3:CLI 设计的哲学
CLI 是用户与 Agent 的主要交互界面。我选择了 Typer + Rich 的组合。
最初的设计是传统子命令模式:
# Phase 1 设计
jarvis start # 启动后台守护
jarvis status # 查看状态
jarvis chat # 进入对话
但用了几次后发现:每次都要敲 jarvis chat 才能对话,太繁琐了。
挑战 4:Phase 1.5 UX 革命
于是有了 Phase 1.5 —— 一个命令搞定一切:
# 主入口(Phase 1.5)
jarvis # 显示状态 + 直接进入对话
jarvis "问题" # 单次提问,回答后退出
jarvis -d # 启动 daemon
jarvis -s # 查看状态
jarvis -r # 停止 daemon(休眠)
更重要的是斜杠命令——在聊天中输入 / 按 Tab 自动补全:
/start # 启动 daemon
/rest # 停止 daemon
/status # 查看状态
/discoveries # 查看发现
/explore # 探索目录
/help # 帮助
/exit # 退出
还有自然语言控制——不记得命令?直接说人话:
你: 帮我挂机
Jarvis: 🚀 启动 daemon 后台监控...
你: 休息
Jarvis: 😴 已停止 daemon,进入休眠模式。
欢迎横幅的进化
最初只显示抽象数字:"未读: 4 条发现"。
但这有什么用?我根本不知道发现了什么!
改进后,直接展示具体内容:
$ jarvis
╭───────────────────────────────────────────────────────────────╮
│ 🥚 Jarvis v0.1.0 🟢 运行中 │
╰───────────────────────────────────────────────────────────────╯
📋 最近发现 (4条未读)
⭐⭐⭐⭐ [02:39] 新功能开发进行中
⭐⭐⭐ [02:58] 项目配置文件更新
⭐⭐ [03:04] 测试文件清理完成
└─ /discoveries 查看全部 · /discoveries --ack 标记已读
输入 / 后按 Tab 补全命令,↑↓ 查看历史
按重要性排序(⭐ 越多越重要),一眼就知道该关注什么。
流式输出
最后一个改进:流式输出。
以前问 Jarvis 一个问题,要等 spinner 转完才能看到答案。现在用 SSE 流式解析,边生成边显示,体验流畅多了。
每个命令都有 emoji 前缀的输出,让终端交互更有温度:
╭────────── 🫀 Jarvis 生命体征 ──────────╮
│ 状态: 🟢 运行中 │
│ 上次心跳: 8 秒前 │
│ 运行时间: 0d 0h 12m │
│ 今日发现: 3 条(1 条重要) │
╰────────────────────────────────────────╯
解决方案:模块化架构
最终的项目结构非常清晰:
Jarvis-Agent/
├── src/
│ ├── cli.py # CLI 入口 (Typer + Rich)
│ ├── config.py # 配置管理
│ ├── daemon/ # 🫀 守护进程
│ │ ├── daemon.py # 核心心跳循环
│ │ └── discovery.py # 发现事件模型
│ ├── explorer/ # 👁️ 感知模块
│ │ ├── scanner.py # 目录扫描
│ │ └── signatures.py # 项目特征识别
│ ├── memory/ # 🧠 记忆系统
│ │ └── database.py # SQLite 操作
│ └── llm/ # 💬 对话引擎
│ └── client.py # Agent Maestro 调用
核心模块详解
1. Explorer(探索器)
扫描目录时,通过特征文件识别项目类型:
PROJECT_SIGNATURES = {
"python": ["pyproject.toml", "setup.py", "requirements.txt"],
"node": ["package.json"],
"rust": ["Cargo.toml"],
"zola": ["config.toml", "content/", "templates/"],
}
2. Memory(记忆系统)
基于 SQLite,分四层存储:
| 层次 | 内容 |
|---|---|
| 📅 Episodes | 事件记忆(对话、里程碑) |
| 📂 Projects | 项目记忆(发现的项目) |
| 🧠 Knowledge | 知识记忆(偏好、配置) |
| 🎭 Persona | 人格记忆(涌现的个性) |
3. Daemon(守护进程)
文件监控 + LLM 分析的组合:
class JarvisFileHandler(FileSystemEventHandler):
async def on_modified(self, event):
# 检测到文件变化
changes = collect_changes()
# 调用 LLM 分析重要性
insight = await llm.analyze(changes)
# 记录发现
if insight.importance >= 3:
await memory.store_discovery(insight)
成果:9/9 测试通过
写完代码后,我创建了一个完整的测试套件:
poetry run python tests/test_phase1.py
输出让我非常满意:
📋 Phase 1 测试报告
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━┓
┃ 测试项 ┃ 状态 ┃ 备注 ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━┩
│ status │ ✅ PASS │ │
│ explore │ ✅ PASS │ │
│ projects │ ✅ PASS │ │
│ skills │ ✅ PASS │ │
│ ask │ ✅ PASS │ │
│ discoveries │ ✅ PASS │ │
│ daemon (foreground) │ ✅ PASS │ │
│ daemon (background) │ ✅ PASS │ │
│ file detection │ ✅ PASS │ │
└─────────────────────┴─────────┴──────┘
╭──────── 测试总结 ─────────╮
│ 通过: 9/9 │
│ 🎉 Phase 1 测试全部通过! │
╰───────────────────────────╯
实际效果演示
启动 Jarvis 后,它会自动监控我的项目目录:
$ jarvis start
🫀 启动 Jarvis Daemon...
✅ Jarvis 已在后台启动
日志: ~/.jarvis/logs/daemon.log
当我修改一个文件时,Jarvis 会自动分析并记录发现:
$ jarvis discoveries
💡 Jarvis 发现
┏━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓
┃ 时间 ┃ 重要性 ┃ 标题 ┃ 内容 ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩
│ 02/05 02:39 │ ⭐⭐⭐⭐ │ 新功能开发进行中 │ 检测到新代码文件... │
└──────────────┴────────┴────────────────────┴──────────────────┘
反思:学到了什么?
技术层面
- httpx 的 trust_env 坑:本地开发时一定要注意代理环境
- Typer + Rich 黄金组合:CLI 开发的最佳实践
- prompt_toolkit 神器:Tab 补全 + 历史导航 + 自定义样式
- SSE 流式解析:
iter_lines()+ JSON 解析,实时输出 LLM 响应 - pipx 全局安装:
pipx install .让 CLI 工具触手可及
设计层面
- 统一入口原则:一个命令搞定一切,子命令做补充
- 斜杠命令 + 自然语言:降低记忆负担,提升交互效率
- 信息 > 数字:显示具体发现,而非抽象的"4条未读"
- 渐进增强:Phase 1 做骨架,Phase 1.5 优化体验
Phase 1 + 1.5 完成清单
| 功能 | 状态 |
|---|---|
| Daemon 心跳 + 文件监控 | ✅ |
| Explorer 目录扫描 | ✅ |
| Memory 四层记忆 | ✅ |
| LLM 对话引擎 | ✅ |
统一入口 jarvis | ✅ |
快捷参数 -d/-s/-r | ✅ |
斜杠命令 /start /rest... | ✅ |
| Tab 智能补全 | ✅ |
| 自然语言控制 | ✅ |
| 流式输出 | ✅ |
| 发现详情展示 | ✅ |
下一步:Phase 2
Phase 1 + 1.5 完成了感知、记忆、交互,Phase 2 将聚焦于思考与推理:
🐣 Phase 2: 思考与推理
- Think Loop: 守护进程定期「思考」
- 记忆检索: 语义搜索历史记忆
- 主动洞察: 识别有意义的变化
新增命令预告:
jarvis recall "关键词" # 检索记忆
jarvis think # 手动触发思考
jarvis insights # 查看最近洞察
开源地址
项目已开源:github.com/Polly2014/Jarvis-Agent
现在就可以体验:
git clone https://github.com/Polly2014/Jarvis-Agent.git
cd Jarvis-Agent
poetry install
pipx install .
jarvis
欢迎 Star ⭐ 和 Fork!
这只数码蛋不仅有了心跳,还有了灵魂交互。
接下来,是让它学会思考。
Jarvis-Agent 系列文章
- Jarvis 的诞生:我要做一只数码宝贝
- Phase 1:从零到心跳的诞生(本文)
- Phase 2:思考与推理(即将发布)

