四个不那么常见的设计决定
++ 大多数框架先写功能再补边界。HomeAgent 反过来:先把 + 边界和调度定死,再往上加能力。 +
+ +内核零 IO
++ 内核不直接读写任何外部世界。收发消息、文件操作、网络请求、硬件交互 + 全部由插件经 PluginSDK 实现。于是「内核有多可信」与「某个插件有多安全」 + 成为两个可独立评估的问题。 +
+插件是独立进程
++ 外部插件编译成普通 Go 二进制,由内核 spawn 为子进程,经 + stdio JSON-RPC(控制)+ 共享内存段(数据)+ 事件环(通知)通信。 + 插件崩溃不影响内核,换掉 plugin.bin 即真热重载。 +
+输入是有级别的
++ 输入先进调度器,分「排队」与「中断」两类,中断再按“有多不能等”分 L1–L4。 + 高优先级可抢占并保存现场,同级不抢占。L4 只归内核 + —— 所以“停止”按钮真的能立刻停下。 +
+忙时有人顶班
++ 主 agent 执行长任务时,后来的消息不会干等十几分钟:内核把积压交给 + 临时分诊助手 —— 简单的直接办完,需要主 agent 的立刻回 + 「忙碌中,请稍候」。 +
+三层记忆:从「刚才说了什么」到「三年前说过什么」
++ 不是一个向量库包打天下,而是三层各司其职、逐层衰减与整合。 + 品牌的蓝 / 青 / 金三色,对应的就是这三层。 +
+ +① Context工作窗口
++ 内存中的事件窗口,按与当前输入的相关性评分排序(预训练词向量 → 余弦相似度, + TF-IDF 回退),并保护最近若干条。低分事件自动下沉。 +
+② Document文件记忆
++ JSON + TF-IDF 索引的中间层。支持显式提交与隐式归档; + 冷数据按时间下沉,蒸馏成三元组进入图谱。 +
+③ Graph图数据库
++ SQLite 持久化实体与关系,BFS 遍历召回。蒸馏管道从对话里提取三元组, + 越用越准;这是“几个月前的事还记得”的落点。 +
+媒体也是一等节点
++ 图片/音频不是附件,而是三层里的一类节点:内容寻址存储(相同字节只存一份)、 + 引用计数 GC(有引用绝不删)。 +
+描述才是持久语义
++ 视觉模型生成的描述以 [mime digest] 描述 写进纯文本记忆并参与检索; + blob 只是可被淘汰的缓存。所以几个月后“那张三色图”仍能搜到。 +
+统一多模态空间
++ 文本与图像落在同一向量空间(默认 Chinese-CLIP), + 因此可以用一句话搜图,也可以用图找相关记忆。 +
+一条消息进来之后
++ 输入先过调度器,再进处理管道;管道有 7 个阶段钩子,插件可在此改写或短路。 +
+ ++ 外部输入(QQ / WebUI / CLI / 邮件 / 设备 …) + │ + ▼ + 输入调度器 两类别 · 四级中断 L1–L4 + │ ├─ 同级不抢占 → 入队列 + │ ├─ 更高级 → 抢占(现场压入中断栈,稍后恢复) + │ └─ 忙太久 → 转投 临时分诊助手 + ▼ + 处理管道 on_input → pre_action → post_action → before/after_toolcall → before/after_output + │ 记忆召回 + 人格注入 + LLM 调用 + 工具循环 + ▼ + 三层记忆 Context → Document → Graph + │ + ▼ + 输出通道 可寻址到具体 agent(父 ↔ 驻留子) ++
核心组件
+homed常驻内核进程:LLM 编排、记忆管理、输入调度、插件生命周期PluginSDK四通道:注册工具 / 挂阶段钩子 / 订阅事件 / 声明输出通道inputch最基本的输入路由单位,可划给某个 agent(含驻留子)Stage7 个处理阶段钩子,插件可改写或短路消息流resident驻留子 agent:独立调度器 + temp 图记忆,父可查看/收发/压缩/回收hmapdev插件工具链:生成工程、构建 .hmap、安装跑起来
++ 依赖 Go 1.25+ 与 CGo(sqlite3)。内核需 Linux —— Windows 上 + homed 跑在 WSL2 里,只构建 waiter.exe。 +
+ ++ WebUI 与 API 密钥在 http://localhost:8080 配置,持久化在 SQLite。 +
+ +开箱可用的插件
+外部插件经 hmapdev 构建为独立二进制,可单独安装、卸载、热重载。
+常见问题
+这些是设计上最容易引起误解的地方。
+ +「内核零 IO」是不是意味着内核很简单?
++ 恰恰相反——零 IO 是为了让内核能专注做难的部分:输入调度(四级中断、 + 抢占与现场保存)、上下文预算、三层记忆的蒸馏与召回。 + 把 IO 挪出去之后,这些才有清晰的所有权。 +
+插件崩了会不会把 Agent 带崩?
++ 不会。从 v1.0.0 起外部插件是独立子进程,与内核只通过 + stdio JSON-RPC、共享内存段、事件环三个面通信。插件崩溃后内核摘除其 + 注册面(工具/阶段/通道)并按退避重启它,其余插件与内核不受影响。 +
+为什么消息会「排队」而不是立即处理?
++ 因为同一时刻只应该有一个任务在改上下文。同级中断不抢占同级任务—— + 抢了会让两边都做一半。需要立刻插队的场景请用更高级别的中断 + (如 L4:内核与内核级插件),而不是让所有消息都变成抢占者。 +
+长任务会不会让用户等很久?
++ 这正是「分诊助手」要解决的。主 agent 忙超过阈值(默认 5 分钟)且积压够多时, + 内核会拉起一个临时驻留子接手积压:能直接办的办完并回复, + 需要主 agent 的立刻回一句「忙碌中,请稍候」。 +
+记忆会不会无限膨胀?
++ 不会。三层是迁移关系而不是复制:上下文事件被裁剪后归档成文档, + 文档冷掉后蒸馏成图谱三元组。图谱有去重与 UNIQUE 约束, + 媒体则靠引用计数 GC 回收无主内容。 +
+能换 LLM 吗?
++ 可以。内核不绑定任何厂商:每个 LLM 源对应一个 Lua 脚本负责请求/响应转换, + 仓库内置 10 个适配器(OpenAI、Anthropic、Gemini、DeepSeek、Groq、Ollama 等), + 也可以自己写一个接任意兼容 API。 +
+
+