五处文档此前停在 v1.0.0,而 v1.1.0/v1.1.1 都已发布并在现网运行。 本轮补齐三层记忆的媒体架构、模型工具的媒体参数、通信面 method 数, 以及冻结解除后的替代约束。 ## 中英双语 OVERVIEW.md 三层记忆段只写了 Context/Document/Graph 三层,而 v1.1.0 起图片/音频是 三层里的一类节点。补上媒体记忆的架构概要:CAS + 引用计数 GC + 标记格式 (描述文本才是持久语义记忆,blob 是可淘汰的缓存)+ 插件边界贯通。 ## 中英双语 ARCHITECTURE.md - 「记忆工具」表补 `memory_commit`/`doc_commit` 的 `media_digests` 与 `sentence_text`(后者从未暴露给模型,而它是媒体绑定链的必经环节) - 「三层记忆」段新增媒体记忆子节:CAS 设计表(寻址/完整性/写入原子性/引用/GC)、 标记格式、可选性(`enabled=false` 时整条链路静默退化) - 「三个通信面」从 51 改为 55 个 method,新增四个 media method 的说明 - 「SDK 四通道」代码示例补媒体注入三方法 + 与 SetToolBlocks 的区别 ## plugin-interface-matrix.md - 状态从「完成 v2」改「完成 v3」,v3 记录 v1.1.1 的接口扩展 - §二 A3 DocMemoryAPI 补 InsertWithMedia - §二 A4 补三个媒体注入方法 + 为何不能搭 SetToolBlocks 的车 - §二 A5 补 MediaAttachment 类型 + Triple/Doc/TextEvent 的扩展字段 - §六「新获得的能力」补 SetToolBlocks 已落地、媒体入记忆、插件主动发起 带媒体的对话 - §七 冻结检查点补第 5 条(冻结已解除,取代它的是 §九) - 新增 §九「v1.1.x 的接口扩展规则」:冻结解除后的三条硬约束 (只增不减签名不改 / 新增方法方向 / 模板接线六处失败链)+ 验证方式 (存量插件 17/17、旧产物 4/4 建链、模板断言、压测 -race) ## 为何分立两笔 commit 前一笔(SDK 仓 README + 内核 README)改的是给**插件开发者**看的文本, 本笔改的是给**架构师与维护者**看的技术文档。受众与改动层次不同, 放在同一个 commit 会让追溯时看不出"文档在哪一层跟上了代码"。
⚠️ AI-Assisted Programming Notice: Parts of this project's code, documentation, and commit history were generated or modified with AI assistance. Key changes have been human-reviewed, but please evaluate and verify before use.
HomeAgent
中文: README.md
An Agent framework designed around separation of core domain and application domain. The kernel enforces a zero-IO policy — all external interaction (WebUI, QQ, CLI, file operations, web search, memos, etc.) is handled by the plugin layer; the kernel performs no direct IO operations.
Combined with a three-layer memory architecture (Context → Document → Graph), it maintains contextual coherence across long-running single-conversation sessions through tiered storage and automated archival.
homed (kernel, zero IO) ← PluginSDK → plugins (all IO capabilities)
Since v1.0.0 external plugins are independent subprocesses, communicating with the kernel over
stdio JSON-RPC (control plane) + a shared memory segment (data plane) + an event ring (notification
plane). A plugin crash cannot take down the kernel and it restarts automatically; swapping
plugin.bin gives true hot-reload.
Design Principles
Separation of Core Domain and Application Domain — The kernel's responsibilities are limited to LLM orchestration, memory management, and knowledge retrieval; all IO capabilities (message send/receive, file read/write, network requests, hardware interaction, etc.) are implemented by plugins. This separation defines domain boundaries at the Agent framework level, with distinct responsibility scopes for the kernel and plugins.
Three-Layer Memory Architecture — Manages information retention in long-running agents through a tiered storage strategy:
- Context Layer: Pretrained word embedding / TF-IDF fallback relevance-scored event window, protects last 10 entries, maintains topK context entries
- Document Layer: Temporary memory with automatic cold data sinking, also supports user-initiated submissions
- Graph Layer: SQLite graph database, persists entity relationships and semantic memory, supports distillation pipelines to extract triples from conversations
Architecture Diagrams
1. Message Processing Sequence
sequenceDiagram
participant U as User/Plugin
participant IO as IOManager
participant EV as eventLoop
participant CTX as RelevanceContext
participant LLM as LLM+Tool Loop
participant ST as StageHost
participant MEM as Three-Layer Memory
U->>IO: InjectInput(type, payload)
IO->>EV: inputCh
rect lavender
Note over EV: processTextInput
EV->>ST: StageOnInput Plugin can rewrite/short-circuit
EV->>CTX: Prune(input,topK) StaticEmbedder/TF-IDF cosine pruning
CTX->>MEM: Low-score events archived to Document (original timestamp)
EV->>CTX: Append(input) CleanTemplateText→three-branch vector→5s write
end
rect lightgreen
Note over EV,LLM: process()
EV->>MEM: buildMemoryContext Indexer recalls from Graph (vector+jieba→BFS depth=2)
EV->>MEM: buildSystemPrompt DocQuery summary+Graph memory index+Persona+Skills
EV->>ST: StagePreAction Plugin can pre-intercept
loop Tool loop
LLM->>LLM: drainInterrupts
LLM->>LLM: LLM Chat
LLM->>ST: StagePostAction Plugin can modify/short-circuit
alt No tool call
LLM-->>EV: Returns response
else
loop Each tool
ST->>ST: StageBeforeToolcall Plugin can reject
LLM->>LLM: executeToolCall
ST->>ST: StageAfterToolcall
end
end
end
end
rect lightpink
Note over EV: emitResponse
CTX->>CTX: Append(response)
ST->>ST: StageBeforeOutput Plugin can rewrite
EV-->>U: ResponseCh CLI sync
EV-->>EV: Event bus WebUI SSE
ST->>ST: StageAfterOutput Read-only
EV->>MEM: emitMemoryCandidate
end
2. Stage Pipeline
flowchart LR
S1[① on_input] --> S2[② pre_action]
S2 --> S3[③ post_action]
S3 --> Q{Has tool?}
Q -->|Yes| S4[④ before_toolcall]
S4 --> T[executeToolCall]
T --> S5[⑤ after_toolcall]
S5 --> S3
Q -->|No| S6[⑥ before_output]
S6 --> S7[⑦ after_output]
style S1 fill:#e1f5fe
style S3 fill:#fff3e0
style S6 fill:#e8f5e9
3. Three-Layer Memory
flowchart TB
subgraph C[① Context Working Window]
RC[RelevanceContext]
A[Append] -->|CleanTemplateText→three-branch vector| RC
P[Prune StaticEmbedder/TF-IDF Cosine] -->|Low score original timestamp| D
P -->|Keep| TL[timeline→chronological→system prompt]
end
subgraph D[② Document File Memory]
DS[DocStore JSON+TF-IDF]
Q1[Query summary auto-inject] -->|[Related Memory Docs]| SP
Q2[doc_query LLM active recall] -->|Consume+delete source| DS
Q2 -->|Original timestamp write to context| RC
CD[FindColdDocs 72h] -->|docToTriples| G
end
subgraph G[③ Graph Database]
DB[(SQLite)]
IDX[Indexer vector+jieba→BFS depth=2] -->|[Memory Index]| SP
MEM[memory_recall/commit/merge/purge/edit]
SOC[person_query/set_trait]
end
subgraph H[④ Heartbeat Distillation]
REORG -->|Step3 Cold docs| CD
REORG -->|Step4 Bigram Jaccard| CONS[consolidation]
PIPE[Pipeline regex] -->|Name/Address/Likes/Age/Job| DB
end
SP[System Prompt] -->|Sequential assembly| LLM
LLM[LLM] -->|doc_query| Q2
LLM -->|memory_recall| MEM
See assets/docs/en/ARCHITECTURE.md for details.
Web Mascot
Quick Start
make build build-cli
./build/homed -data /tmp/ha
# Interactive mode
./build/waiter
# Or single message
echo "Hello, remember that I like coffee" | ./build/waiter
API keys are configured via WebUI http://localhost:8080 settings page, persisted in SQLite.
Code Structure
cmd/homed/ Daemon entry, assembles all subsystems
cmd/waiter/ CLI client (Unix socket)
internal/
├── agent/core/ Agent core: event loop, LLM tool loop, 7-stage pipeline
├── agent/api/ LLM Provider + 8 Lua adapters
├── memory/ Three-layer memory: Graph(SQLite) / Document(JSON+TF-IDF) / Text(JSONL) + StaticEmbedder(pretrained word embedding/TF-IDF fallback) + CleanTemplateText(de-template)
├── knowledge/ Knowledge base (filesystem + TF-IDF)
├── plugin/ Plugin registry + subprocess loader (stdio RPC + shared memory segment + event ring)
├── plugins/ 11 built-in plugins (webui/cli/timer/cmd/mcp/clawhubadapter/agentcli/healthcheck/pluginmgr/files/cfgmgr)
├── sdk/ PluginSDK (Tool/Stage/Event three channels)
├── config/ SQLite config center
├── events/ Event bus
└── internal/lua/adapters/ 8 LLM protocol adapter scripts
External plugin development: see [homeagent-sdk](https://gitcode.com/JianFeeeee/homeagent-sdk) repo, use `plugindev` toolchain, refer to Go and Lua examples in `example/`
Project Status
v1.1.0 — Binary/multimedia nodes in the memory system. All four tiers (L0 active context / L1 text / L2 documents / L3 graph) previously stored text only: an image or audio clip was turned into a description by a vision model and the original bytes were dropped, so "that purple-blue-red banded image" could never be retrieved again. This release adds a content-addressed media store (CAS, internal/memory/media): metadata in SQLite, blobs deduplicated on disk by sha256, with every tier holding only digests and reference counts maintained through media_refs, so the capacity cap is finally enforced by a background GC (referenced content is never deleted, even over the limit). The description text is the durable semantic memory; the blob is only a cache — descriptions persist across all tiers and stay searchable while raw bytes may be evicted, so months later a graph sentence still resolves back to that image (byte-for-byte if it survives). Descriptions are generated by a background loop through a vision source (off by default; at most 4 items per 30s when enabled, so it never competes with conversations for quota) — doing it inline would add tens of seconds to every image reply for no gain, since the model is looking at the image in that turn anyway. Five defects fixed as well: core.New never called rc.SetMediaStore, silently disabling L0→L2 reference transfer in production; references were released and the document deleted even when every triple was rejected by entity-name validation (data loss, reverse-verified); media entering the graph depended on the NLP extractor happening to produce valid triples and was therefore intermittent, now replaced by deterministic triples derived from media markers; L3 media lookup had no callers at all (stored fine, unreachable by the agent); and one data race each in the remotedevice gateway and the agentcli terminal. Ships with a -tags medialive auto-trigger integration test: a single injected image event drives all seven stages — CAS write, description, archival, graph binding, GC protection, second-turn recall — entirely through production code paths, and with a real vision model the agent names all three band colours and their approximate hex values in a second turn that includes no image. Plugin ABI unchanged (SDKCompatibleVersion stays 1.0.0); existing plugin.bin files need no rebuild.
v1.0.0 — External plugins moved from C ABI shared libraries to subprocess + shared memory. The first release that no longer loads .so/.dll, and it is incompatible with 0.9.x (existing plugins must be rebuilt into plugin.bin with the new plugindev, though business code needs zero changes). Eliminates 6 classes of defects that had caused production incidents: hot-reload silently failing (DF_1_NODELETE making dlclose a no-op), no crash isolation (a plugin panic took down homed), stage lost updates (35.8~36.8% loss under the copy model), uncancellable cgo timeouts (linear OS-thread leaks), output_send reporting false success (the model was told "sent" while the message never went out), and Windows capability degradation (only 3 stage fields visible, no write-back). Three communication planes: stdio JSON-RPC (control) + shared memory segment (data) + event ring (notification); the privilege gradient is now enforced by three explicit gates. RPC round-trip p50 24.1µs; crash-to-recovery under 1s.
v0.9.0 — C ABI v2: external plugin Stage callbacks can now write back (invoke_stage gained a result out-param; plugins may mutate RawMessage/LLMText/ToolResults etc. in OnInput/AfterToolcall/PostAction and have them synced to the core). ABI version now tracks core minor releases (v0.9.x → ABIVersion=2, version_min=1 keeps old plugins loadable). Also fixes the tool-loop zen-compat placeholder that wrongly fired on first-turn system context tail. The SDK ships an enhanced sanitizer example (bad-UTF-8 / U+FFFD / ANSI-escape scrub across the whole pipeline). This ABI retired with v1.0.0.
v0.8.0 — Core is functional, plugin system enhanced. 20+ built-in plugins. External plugin development via homeagent-sdk repo. Added input channel NoMemory/Cleaner, ChannelDef, plugin disable/enable system (CLI + WebUI), plugindev toolchain C ABI ChannelDef support.
Documentation
- Project Overview | 中文
- Technical Architecture | 中文
- Plugin Development Guide | 中文
- Lua Adapter | 中文
- Knowledge Base Demo
Downloads
Releases ship three variants:
| Variant | Contents | For |
|---|---|---|
| full | homed + waiter + desktop GUI + systemd unit | Single-machine, everything |
| server | homed + waiter + systemd unit | Servers (no desktop environment) |
| client | waiter + desktop GUI | Connecting to a remote HomeAgent |
- Linux:
.deb(amd64/arm64),.rpm(x86_64),.tar.gz - Windows:
HomeAgent_v1.1.0_{Full,Server,Client}_win64.exe(NSIS installer) - Portable:
homeagent-bin-<os>_<arch>.tar.gz(homed/waiter/initconfig) - Verification:
SHA256SUMS
The macOS homed requires a native macOS build (CGO + sqlite3), so release packages ship only waiter/initconfig.
Build
make build build-cli # Build daemon + CLI
make test # go test ./...
make install # Install to system
Dependencies: Go 1.25+, CGo (go-sqlite3), Linux/Windows.
