agentmemory on NAS 完整部署文档(Tailscale + DeepSeek 压缩 + 局域网 viewer)

已对照 rohitg00/agentmemory 源码核对(npm 最新 0.9.26,引擎锁定 iii v0.11.2,Apache-2.0)。

架构 :NAS 跑一个 全功能 agentmemory 服务器(数据在 /data 卷)。

  • API(3111):经 Tailscale sidecar 接入 tailnet → 多设备/远程访问,不暴露局域网/公网。
  • viewer(3113):发布到 NAS 局域网 → 同一内网用浏览器直接打开。
  • 压缩 LLM :走 OpenAI 兼容通道接 DeepSeek deepseek-v4-flash
  • 每台开发机只装 Claude Code 插件 + 轻量 MCP shim,经 tailnet 指向 NAS,共享同一份记忆。

⚠️ 安全须知 :viewer(3113)是免密特权界面 (它代理请求时自动附带你的 AGENTMEMORY_SECRET)。

绑到局域网意味着同一内网任何设备都能全权读写你的记忆。家庭内网可接受;公共/办公网请改用 SSH 隧道(见附录 B)。


下面是整体架构图,帮你快速理解各组件之间的关系:
#mermaid-svg-e3TSNShAR81RzPBy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-e3TSNShAR81RzPBy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-e3TSNShAR81RzPBy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-e3TSNShAR81RzPBy .error-icon{fill:#552222;}#mermaid-svg-e3TSNShAR81RzPBy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-e3TSNShAR81RzPBy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-e3TSNShAR81RzPBy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-e3TSNShAR81RzPBy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-e3TSNShAR81RzPBy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-e3TSNShAR81RzPBy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-e3TSNShAR81RzPBy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-e3TSNShAR81RzPBy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-e3TSNShAR81RzPBy .marker.cross{stroke:#333333;}#mermaid-svg-e3TSNShAR81RzPBy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-e3TSNShAR81RzPBy p{margin:0;}#mermaid-svg-e3TSNShAR81RzPBy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-e3TSNShAR81RzPBy .cluster-label text{fill:#333;}#mermaid-svg-e3TSNShAR81RzPBy .cluster-label span{color:#333;}#mermaid-svg-e3TSNShAR81RzPBy .cluster-label span p{background-color:transparent;}#mermaid-svg-e3TSNShAR81RzPBy .label text,#mermaid-svg-e3TSNShAR81RzPBy span{fill:#333;color:#333;}#mermaid-svg-e3TSNShAR81RzPBy .node rect,#mermaid-svg-e3TSNShAR81RzPBy .node circle,#mermaid-svg-e3TSNShAR81RzPBy .node ellipse,#mermaid-svg-e3TSNShAR81RzPBy .node polygon,#mermaid-svg-e3TSNShAR81RzPBy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-e3TSNShAR81RzPBy .rough-node .label text,#mermaid-svg-e3TSNShAR81RzPBy .node .label text,#mermaid-svg-e3TSNShAR81RzPBy .image-shape .label,#mermaid-svg-e3TSNShAR81RzPBy .icon-shape .label{text-anchor:middle;}#mermaid-svg-e3TSNShAR81RzPBy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-e3TSNShAR81RzPBy .rough-node .label,#mermaid-svg-e3TSNShAR81RzPBy .node .label,#mermaid-svg-e3TSNShAR81RzPBy .image-shape .label,#mermaid-svg-e3TSNShAR81RzPBy .icon-shape .label{text-align:center;}#mermaid-svg-e3TSNShAR81RzPBy .node.clickable{cursor:pointer;}#mermaid-svg-e3TSNShAR81RzPBy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-e3TSNShAR81RzPBy .arrowheadPath{fill:#333333;}#mermaid-svg-e3TSNShAR81RzPBy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-e3TSNShAR81RzPBy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-e3TSNShAR81RzPBy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-e3TSNShAR81RzPBy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-e3TSNShAR81RzPBy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-e3TSNShAR81RzPBy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-e3TSNShAR81RzPBy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-e3TSNShAR81RzPBy .cluster text{fill:#333;}#mermaid-svg-e3TSNShAR81RzPBy .cluster span{color:#333;}#mermaid-svg-e3TSNShAR81RzPBy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-e3TSNShAR81RzPBy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-e3TSNShAR81RzPBy rect.text{fill:none;stroke-width:0;}#mermaid-svg-e3TSNShAR81RzPBy .icon-shape,#mermaid-svg-e3TSNShAR81RzPBy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-e3TSNShAR81RzPBy .icon-shape p,#mermaid-svg-e3TSNShAR81RzPBy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-e3TSNShAR81RzPBy .icon-shape .label rect,#mermaid-svg-e3TSNShAR81RzPBy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-e3TSNShAR81RzPBy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-e3TSNShAR81RzPBy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-e3TSNShAR81RzPBy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 云端
NAS 局域网
Tailscale Tailnet
NAS(群晖/任意 Linux)
http://NAS_LAN_IP:3113
OpenAI 兼容
agentmemory 服务器

API(3111) + viewer(3113)
Tailscale sidecar

ts-agentmemory
/data 卷

记忆持久化
开发机 A

Claude Code + MCP shim
开发机 B

Claude Code + MCP shim
浏览器

访问 viewer(3113)
DeepSeek API

deepseek-v4-flash

0. 前置准备

bash 复制代码
# 在 NAS 上(SSH;需 Docker / Container Manager / Portainer 能跑 compose)
cd /volume1/docker            # 群晖示例,换成你的路径
git clone --depth 1 https://github.com/rohitg00/agentmemory.git

Tailscale auth key :登录 https://login.tailscale.com/admin/settings/keys → Auth keys →

Generate auth key,设置:

  • Reusable:(容器重建可再次认证)
  • Ephemeral:(NAS 是常驻节点,别让它离线被清除)
  • Expiration:默认 90 天即可(只在首次认证用一次)
  • Tags:可不打

生成的 tskey-auth-xxxx 一会儿填进 .env

收尾 :容器连上后,去 Tailscale 后台 Machines → 找到 agentmemory 节点 → Disable key expiry ,

否则约 180 天后节点会因 node key 过期掉线。

DeepSeek API key (用于压缩):登录 https://platform.deepseek.com → API keys → 创建,得到 sk-xxxx

(key 必须你自己申请;别人无法提供。)


1.(推荐)定制 Dockerfile:开启本地向量嵌入 + 中文分词

coolify 的 Dockerfile 默认用 --omit=optional,会跳过本地向量模型 ,退化成纯 BM25 关键词检索;

且对中文是整段切词。你写中文、要语义召回,就改一行。

编辑 agentmemory/deploy/coolify/Dockerfile,把那条 npm install ... 改成:

dockerfile 复制代码
RUN printf '{"name":"agentmemory-deploy","version":"1.0.0","private":true,"overrides":{"iii-sdk":"%s"}}\n' "${III_SDK_VERSION}" > package.json \
 && npm install "@agentmemory/agentmemory@${AGENTMEMORY_VERSION}" --no-fund --no-audit \
 && npm install @xenova/transformers @node-rs/jieba tiny-segmenter --no-fund --no-audit \
 && ln -s /opt/agentmemory/node_modules/.bin/agentmemory /usr/local/bin/agentmemory

(去掉了 --omit=optional,显式装了本地嵌入模型 + 中日韩分词器。)

维护提示:你改过这个文件后不要直接 git pull(会被覆盖)。日常升级只改 compose 里的版本号即可(见第 6 节)。


2. docker-compose.yml

存成 docker-compose.yml,和 clone 出来的 agentmemory/ 目录同级

yaml 复制代码
services:
  # Tailscale 节点:持有网络栈,agentmemory 共享它
  ts-agentmemory:
    image: tailscale/tailscale:latest
    hostname: agentmemory                 # → MagicDNS:http://agentmemory:3111
    environment:
      - TS_AUTHKEY=${TS_AUTHKEY}
      - TS_STATE_DIR=/var/lib/tailscale
      - TS_USERSPACE=false                # 内核模式(需 /dev/net/tun)
    volumes:
      - ts-state:/var/lib/tailscale
    devices:
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - net_admin
    ports:
      - "3113:3113"                       # viewer 发布到 NAS 局域网(端口须发布在网络栈持有者上)
    restart: unless-stopped

  agentmemory:
    build:
      context: ./agentmemory/deploy/coolify
      dockerfile: Dockerfile
      args:
        AGENTMEMORY_VERSION: "0.9.26"
        III_VERSION: "0.11.2"
        III_SDK_VERSION: "0.11.2"
    network_mode: service:ts-agentmemory  # 与 Tailscale 容器共享网络
    depends_on:
      - ts-agentmemory
    environment:
      # ---- 压缩 LLM:DeepSeek(OpenAI 兼容)----
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - OPENAI_BASE_URL=${OPENAI_BASE_URL} #https://api.deepseek.com
      - OPENAI_MODEL=${OPENAI_MODEL} #deepseek-v4-flash
      # ---- viewer 局域网访问 ----
      - AGENTMEMORY_VIEWER_HOST=0.0.0.0
      - VIEWER_ALLOWED_HOSTS=${NAS_LAN_IP}:3113
      - VIEWER_ALLOWED_ORIGINS=http://${NAS_LAN_IP}:3113
    volumes:
      - agentmemory-data:/data
    restart: unless-stopped

volumes:
  ts-state:
  agentmemory-data:

.env(同目录,务必加入 .gitignore):

env 复制代码
TS_AUTHKEY=tskey-auth-xxxxxxxx
OPENAI_BASE_URL=sk-xxxxxxxx
OPENAI_API_KEY=https://api.deepseek.com
OPENAI_MODEL=deepseek-v4-flash
NAS_LAN_IP=192.168.1.50          # 换成你 NAS 的局域网 IP

端口说明:API(3111)、stream(3112)被 entrypoint 绑到 0.0.0.0,通过 Tailscale 节点在 tailnet 上可达,

发布到局域网;viewer(3113)默认绑 loopback,这里用 AGENTMEMORY_VIEWER_HOST=0.0.0.0 改绑 + 在

ts-agentmemoryports: 3113:3113 发布到局域网。


下面是容器网络与服务依赖关系图:
#mermaid-svg-H5Pf9kaEuai3Lf79{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-H5Pf9kaEuai3Lf79 .error-icon{fill:#552222;}#mermaid-svg-H5Pf9kaEuai3Lf79 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-H5Pf9kaEuai3Lf79 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .marker.cross{stroke:#333333;}#mermaid-svg-H5Pf9kaEuai3Lf79 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-H5Pf9kaEuai3Lf79 p{margin:0;}#mermaid-svg-H5Pf9kaEuai3Lf79 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .cluster-label text{fill:#333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .cluster-label span{color:#333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .cluster-label span p{background-color:transparent;}#mermaid-svg-H5Pf9kaEuai3Lf79 .label text,#mermaid-svg-H5Pf9kaEuai3Lf79 span{fill:#333;color:#333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .node rect,#mermaid-svg-H5Pf9kaEuai3Lf79 .node circle,#mermaid-svg-H5Pf9kaEuai3Lf79 .node ellipse,#mermaid-svg-H5Pf9kaEuai3Lf79 .node polygon,#mermaid-svg-H5Pf9kaEuai3Lf79 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-H5Pf9kaEuai3Lf79 .rough-node .label text,#mermaid-svg-H5Pf9kaEuai3Lf79 .node .label text,#mermaid-svg-H5Pf9kaEuai3Lf79 .image-shape .label,#mermaid-svg-H5Pf9kaEuai3Lf79 .icon-shape .label{text-anchor:middle;}#mermaid-svg-H5Pf9kaEuai3Lf79 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-H5Pf9kaEuai3Lf79 .rough-node .label,#mermaid-svg-H5Pf9kaEuai3Lf79 .node .label,#mermaid-svg-H5Pf9kaEuai3Lf79 .image-shape .label,#mermaid-svg-H5Pf9kaEuai3Lf79 .icon-shape .label{text-align:center;}#mermaid-svg-H5Pf9kaEuai3Lf79 .node.clickable{cursor:pointer;}#mermaid-svg-H5Pf9kaEuai3Lf79 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .arrowheadPath{fill:#333333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-H5Pf9kaEuai3Lf79 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H5Pf9kaEuai3Lf79 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-H5Pf9kaEuai3Lf79 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H5Pf9kaEuai3Lf79 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-H5Pf9kaEuai3Lf79 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-H5Pf9kaEuai3Lf79 .cluster text{fill:#333;}#mermaid-svg-H5Pf9kaEuai3Lf79 .cluster span{color:#333;}#mermaid-svg-H5Pf9kaEuai3Lf79 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-H5Pf9kaEuai3Lf79 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-H5Pf9kaEuai3Lf79 rect.text{fill:none;stroke-width:0;}#mermaid-svg-H5Pf9kaEuai3Lf79 .icon-shape,#mermaid-svg-H5Pf9kaEuai3Lf79 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H5Pf9kaEuai3Lf79 .icon-shape p,#mermaid-svg-H5Pf9kaEuai3Lf79 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-H5Pf9kaEuai3Lf79 .icon-shape .label rect,#mermaid-svg-H5Pf9kaEuai3Lf79 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H5Pf9kaEuai3Lf79 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-H5Pf9kaEuai3Lf79 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-H5Pf9kaEuai3Lf79 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 环境变量
docker-compose.yml 服务栈
共享网络栈
ts-agentmemory

Tailscale sidecar

网络栈持有者
agentmemory

主服务

network_mode: service:ts-agentmemory
ts-state 卷
agentmemory-data 卷
TS_AUTHKEY
DEEPSEEK_API_KEY
NAS_LAN_IP

3. 启动 + 取密钥

bash 复制代码
docker compose up -d --build
# 首次启动入口会生成一次性密钥,只打印一次,记下来:
docker compose logs agentmemory | grep AGENTMEMORY_SECRET
# 形如 AGENTMEMORY_SECRET=<64位hex>(持久化在 /data/.hmac)

验证:

bash 复制代码
# API(任意 tailnet 设备)
curl http://agentmemory:3111/agentmemory/health
# viewer(任意局域网设备浏览器)
#   http://192.168.1.50:3113

下面是首次启动的完整流程:
DeepSeek Tailscale agentmemory ts-agentmemory docker compose 管理员 DeepSeek Tailscale agentmemory ts-agentmemory docker compose 管理员 #mermaid-svg-PwKr9T8ohNZZ0Y62{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .error-icon{fill:#552222;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .marker.cross{stroke:#333333;}#mermaid-svg-PwKr9T8ohNZZ0Y62 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PwKr9T8ohNZZ0Y62 p{margin:0;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PwKr9T8ohNZZ0Y62 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PwKr9T8ohNZZ0Y62 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-PwKr9T8ohNZZ0Y62 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .sequenceNumber{fill:white;}#mermaid-svg-PwKr9T8ohNZZ0Y62 #sequencenumber{fill:#333;}#mermaid-svg-PwKr9T8ohNZZ0Y62 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .messageText{fill:#333;stroke:none;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .labelText,#mermaid-svg-PwKr9T8ohNZZ0Y62 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .loopText,#mermaid-svg-PwKr9T8ohNZZ0Y62 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PwKr9T8ohNZZ0Y62 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .noteText,#mermaid-svg-PwKr9T8ohNZZ0Y62 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .actorPopupMenu{position:absolute;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-PwKr9T8ohNZZ0Y62 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PwKr9T8ohNZZ0Y62 .actor-man circle,#mermaid-svg-PwKr9T8ohNZZ0Y62 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-PwKr9T8ohNZZ0Y62 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 密钥持久化到 /data/.hmac docker compose up -d --build启动 Tailscale sidecar使用 TS_AUTHKEY 认证加入 tailnet(节点: agentmemory)构建并启动 agentmemory连接 DeepSeek API(验证)连接成功生成 AGENTMEMORY_SECRETdocker compose logs agentmemory | grep SECRETAGENTMEMORY_SECRET=<64位hex>curl http://agentmemory:3111/agentmemory/health{"status":"ok"}

4. 客户端 Tailscale + Claude Code 接入

每台开发机(Mac / Windows / Linux):

bash 复制代码
# 1) 装并登录 Tailscale,加入同一 tailnet
#    https://tailscale.com/download → tailscale up

# 2) 装 Claude Code 插件(注册 hooks + skills + 自动接 MCP)
#    在 Claude Code 里:
#      /plugin marketplace add rohitg00/agentmemory
#      /plugin install agentmemory

# 3) 设两个环境变量(写进 ~/.zshrc / ~/.bashrc;Windows 用系统环境变量)
export AGENTMEMORY_URL="http://agentmemory:3111"     # MagicDNS;或 http://100.x.x.x:3111
export AGENTMEMORY_SECRET="<第3节日志里的密钥>"

# 4) 重启 Claude Code,验证连通 + 鉴权
curl -H "Authorization: Bearer $AGENTMEMORY_SECRET" http://agentmemory:3111/agentmemory/health

hooks 和 MCP shim 都读这两个变量:AGENTMEMORY_URL 决定连哪、AGENTMEMORY_SECRETBearer 发送。

两台机器配好即共享同一份记忆。日常正常写代码,hooks 自动捕获;需要时用 /recall/remember/handoff 等 skill。


5. 压缩 LLM(DeepSeek)说明与验证

agentmemory 的 provider 检测:只要 OPENAI_API_KEY 有真实值,就走 provider: "openai",

modelOPENAI_MODELbaseURLOPENAI_BASE_URL。这条通道官方注释支持

"OpenAI, DeepSeek, SiliconFlow, Azure, vLLM, LM Studio"。所以接 DeepSeek 就是把这三个变量指过去(已在第 2 节配好)。

  • deepseek-v4-flash 是 cost-optimized 档,适合做后台高频压缩(源码里专门有针对贵模型的成本告警)。
  • base URL 用 https://api.deepseek.com(OpenAI SDK 习惯的 https://api.deepseek.com/v1 也行)。

验证:

bash 复制代码
# 变量是否真进了容器
docker compose exec agentmemory printenv | grep -E 'OPENAI_|VIEWER_|TS_'
# provider 是 openai 还是 noop
docker compose exec agentmemory agentmemory doctor

若日志里仍出现 "No LLM provider key found ... using no-op provider",说明 key 没被读到------

检查 .envDEEPSEEK_API_KEY 和 compose 的 environment 引用。


6. 升级

三块各自独立,最常做的是 agentmemory 本身。

6.1 升级 agentmemory(改版本号 + 重建)

bash 复制代码
cd /volume1/docker
# 1) 先备份(数据唯一不可替代)
curl -s -H "Authorization: Bearer $AGENTMEMORY_SECRET" \
  http://agentmemory:3111/agentmemory/export > backup-$(date +%F).json
#    并对 agentmemory-data 卷做 NAS 快照
# 2) 查新版 + 看 release 是否要求改引擎
npm view @agentmemory/agentmemory version
# 3) 改 docker-compose.yml 的 args.AGENTMEMORY_VERSION
# 4) 重建
docker compose build agentmemory && docker compose up -d
docker compose logs --tail=50 agentmemory   # 确认无 EPIPE/报错

6.2 铁律:III_VERSION 别乱升

保持 0.11.2。升到 0.11.6+ 会出现 EPIPE 重连循环、保存后搜不到。

只有当 agentmemory 某新版 release notes 明确支持新引擎时,才按它给的版本同步改。

6.3 回滚

AGENTMEMORY_VERSION 改回旧值重建即可,数据卷不动。若新版动过状态库结构,

回滚旧二进制可能读不了已迁移数据------这时用第 6.1 步那份 JSON 导出 import 重建。

6.4 Tailscale 边车 / 客户端

bash 复制代码
docker compose pull ts-agentmemory && docker compose up -d   # 边车

客户端插件在 Claude Code 里重装/更新;尽量让服务端与客户端小版本相近。

你的 AGENTMEMORY_SECRET 存在 /data/.hmac,升级/重建不变,客户端无需重配。


7. 把本地已有记忆迁到 NAS

import 接口要求 { "exportData": <export内容>, "strategy": "merge"|"replace"|"skip" }

bash 复制代码
# (本地)先起本地 server:agentmemory 或 npx @agentmemory/agentmemory
curl -s http://127.0.0.1:3111/agentmemory/export > export.json
#   语料大、超时就分页:?maxSessions=10&offset=0 逐批拉
# 包一层
jq '{exportData: ., strategy: "merge"}' export.json > import.json
# 推到 NAS
curl -X POST http://agentmemory:3111/agentmemory/import \
  -H "Authorization: Bearer $AGENTMEMORY_SECRET" \
  -H "Content-Type: application/json" --data @import.json

merge 合并 / replace 覆盖 / skip 只补新。首次迁移用 merge

(裸拷贝 ~/.agentmemory 的 SQLite 为备选,要求两端版本一致且停服时操作,优先用 export/import。)


8. 备份 / 维护 / 排错

  • 备份 :记忆在 agentmemory-data 卷(/data/state_store.db),纳入 NAS 快照;或定期 export 出 JSON。
  • 密钥轮换 :删 /data/.hmac 后重启会重新生成并打印。
  • 只看到 7 个 MCP 工具 :shim 没连上 server------查 AGENTMEMORY_URL 可达、health 通。
  • 存了搜不到 / EPIPE :多半 iii 引擎版本不符,保持 III_VERSION=0.11.2
  • viewer 打不开 :确认 AGENTMEMORY_VIEWER_HOST=0.0.0.0VIEWER_ALLOWED_HOSTS 里的 host:port
    与你浏览器地址栏完全一致(含端口);改了要 docker compose up -d 重建容器生效。
  • provider 显示 noop:DeepSeek key 没传进容器,见第 5 节。

附录 A:Option --- 不用 sidecar,改 NAS 原生 Tailscale

若 NAS 容器拿不到 /dev/net/tun:套件中心装 Tailscale(NAS 得到 100.x.x.x),compose 去掉 sidecar,

agentmemory 直接发布端口:ports: ["100.x.x.x:3111:3111", "192.168.1.50:3113:3113"](API 走 tailnet IP、

viewer 走局域网 IP)。客户端 AGENTMEMORY_URL=http://100.x.x.x:3111

附录 B:viewer 的三档访问方式(按安全性从高到低)

共同前提:viewer 是免密特权界面 (代理时自动带 AGENTMEMORY_SECRET)。能打开它 = 全权读写记忆,无需令牌。

按你的暴露面选最小的一档。三档可按需共存(白名单逗号分隔),但暴露越广风险越大。

B1 --- SSH 隧道(最安全,viewer 不出现在任何网络)

把第 2 节 ts-agentmemoryports: ["3113:3113"] 改成 ["127.0.0.1:3113:3113"](只绑 NAS 本机回环),

并设:

yaml 复制代码
  agentmemory:
    environment:
      - AGENTMEMORY_VIEWER_HOST=0.0.0.0                 # 端口转发到容器内 loopback 收不到,必须 0.0.0.0
      - VIEWER_ALLOWED_HOSTS=localhost:3113,127.0.0.1:3113
      - VIEWER_ALLOWED_ORIGINS=http://localhost:3113,http://127.0.0.1:3113

然后 ssh -L 3113:127.0.0.1:3113 <用户>@<NAS>,浏览器开 http://localhost:3113

只有能 SSH 进 NAS 的人能用。

B2 --- 局域网(主文档默认,家庭内网用)

见第 2 节:ports: ["3113:3113"] + VIEWER_ALLOWED_HOSTS=${NAS_LAN_IP}:3113

同一局域网设备开 http://<NAS局域网IP>:3113

B3 --- 全域 / tailnet(你的任意 Tailscale 设备、任意地点可访问)

"全域"= 你 tailnet 内任意设备、任意网络位置可达;不是公网。

viewer 已绑 0.0.0.0、与 Tailscale 边车共享网络栈,所以它已在 tailscale 接口监听------

只需把 tailnet 主机加进白名单,无需再发布任何端口:

yaml 复制代码
  agentmemory:
    environment:
      - AGENTMEMORY_VIEWER_HOST=0.0.0.0
      # 可与局域网并存,逗号分隔;host:port 必须与地址栏完全一致
      - VIEWER_ALLOWED_HOSTS=${NAS_LAN_IP}:3113,agentmemory:3113,${NAS_TS_IP}:3113
      - VIEWER_ALLOWED_ORIGINS=http://${NAS_LAN_IP}:3113,http://agentmemory:3113,http://${NAS_TS_IP}:3113

.env 补一行 NAS_TS_IP=100.x.x.x(NAS 的 Tailscale IP)。docker compose up -d 生效。

任意 tailnet 设备开 http://agentmemory:3113(MagicDNS)或 http://100.x.x.x:3113

单人 tailnet 到此即可。若你的 tailnet 有别人 ,务必在 Tailscale 后台 Access controls 用 ACL

把 viewer 端口锁到只有你自己:给 NAS 节点打 tag(如 tag:agentmemory),并仅放行你这个用户访问该端口------

jsonc 复制代码
{
  "tagOwners": { "tag:agentmemory": ["autogroup:owner"] },
  "acls": [
    // 你自己的设备:全放行
    { "action": "accept", "src": ["autogroup:owner"], "dst": ["*:*"] }
    // 不要给其他用户/tag 添加指向 tag:agentmemory:3113 的规则,默认即拒绝
  ]
}

(打 tag 需让 TS_AUTHKEY--advertise-tags=tag:agentmemory,或在后台给该节点手动加 tag。)

不推荐 --- 公网直曝

viewer 无登录,真要从公网开必须在前面套一层带认证的反向代理(basic auth / OAuth)。

鉴于其特权性质,强烈建议改用 B3 的 tailnet 全域访问,而不是把它挂到公网。

附录 C:Headscale(连协调层都自托管)

NAS 的 ts-agentmemory 与各客户端 tailscale up 都加 --login-server=https://你的headscale;

auth key 由 headscale preauthkeys create 签发。数据平面行为不变。

相关推荐
geneculture26 分钟前
语(暨各级各类字组)对接外来的词和句以及本土的言和语:言和语的关系及双重形式化彻底解决问题
人工智能·语言学·融智学应用场景·哲学与科学统一性·融智时代(杂志)
weixin_4462608528 分钟前
Vortex:高效可编程稀疏注意力机制用于大模型推理服务
人工智能
AI科技星28 分钟前
精细结构常数α的多维度物理比值特性及空间螺旋模型研究
人工智能·线性代数·架构·概率论·学习方法
zhangfeng113328 分钟前
头部AI公司模以OpenAI、DeepSeek为代表型版本迭代训练策略深度解析:重新训练 vs. 增量训练(前瞻性技术推演
人工智能
装不满的克莱因瓶29 分钟前
掌握感知器的学习原理
人工智能·python·神经网络·算法·ai·卷积神经网络
卡梅德生物科技小能手34 分钟前
卡美德生物科普:LOXL2(赖氨酰氧化酶样蛋白2)
人工智能·经验分享·生活
Dragon Wu35 分钟前
AI视频创作笔记(五)短剧制作流程
人工智能·ai
一切皆是因缘际会38 分钟前
AI产业的深度变革与未来思辨
人工智能·ai·架构
不爱土豆唯爱马铃薯39 分钟前
MONKEYCODE 教程系列MC-025 | 实战AI客服机器人
人工智能·数据挖掘