You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

18 KiB

Remote Agent Blueprints — 模板庫與自動化部署管道(LLM 解耦 + 認知配置 + ChatOps)

版本: 2.0
日期: 2026-03-12
維護者: 架構組

本文檔描述遠端 Agent 標準化模板庫與自動化部署管道,供 AI 與維護人員查閱。包含目錄結構、模板說明、腳本行為、環境變數對齊關係,以及歷史修復記錄。

本文僅為說明與維運參考,不執行任何測試;所有變更僅經靜態檢查與邏輯校對。


1. 概述

  • 目標

    • 用模板(blueprints)標準化遠端 Agent 的 Docker/配置/認知檔案。
    • 透過 Volume 掛載解耦 Skill/Plugin 與映像檔,支援熱更新。
    • 支援容器內歸檔目錄(archive/),供 Agent 寫入媒體與本地檔案。
    • LLM 提供商解耦:使用通用 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL_ID,不再綁定特定雲廠商。
    • 植入認知配置(Agent Profile JSON,含 project_id 與系統提示)。
    • 支援 Main Agent 以 純 CLI 無交互 方式呼叫(ChatOps Ready)。
  • 工作根目錄/root/.openclaw/workspace

  • 模板根目錄workspace/remote-blueprints/template/

  • 腳本目錄workspace/scripts/generate_remote.shsync_skill.sh


2. 檔案樹結構

workspace/
├── remote-blueprints/
│   └── template/
│       ├── config/
│       │   └── openclaw.json          # 閘道器配置,使用 ${VAR} 字串插值(CONTROL_UI_TOKEN、LLM_*)
│       ├── skills/                    # 掛載點 -> /root/.openclaw/workspace/skills
│       │   └── .gitkeep
│       ├── plugins/                   # 掛載點 -> /root/.openclaw/workspace/plugins
│       │   └── .gitkeep
│       ├── archive/                   # 掛載點 -> /root/.openclaw/workspace/archive(容器內 chmod 777)
│       │   └── .gitkeep
│       ├── agents/                    # 認知配置模板,會被渲染為 agents/<AGENT_ID>.json
│       │   └── {{AGENT_ID}}.json.tpl
│       ├── Dockerfile
│       ├── docker-compose.yml.tpl     # 使用 {{...}} 作為模板佔位符,其餘從 .env 讀取
│       └── .env.tpl
├── scripts/
│   ├── generate_remote.sh             # 從模板生成實例 + deploy_to_target.sh(支援無交互模式)
│   └── sync_skill.sh                  # 跨節點 Skill 同步(優先 rsync,無則 scp)
└── docs/
    └── REMOTE_BLUEPRINTS.md           # 本文檔

生成實例後(執行 generate_remote.sh ... 後):

remote-blueprints/<AGENT_ID>/
├── config/openclaw.json
├── skills/, plugins/, archive/
├── agents/<AGENT_ID>.json            # 已渲染的 Agent Profile
├── Dockerfile
├── docker-compose.yml                 # 已替換 {{AGENT_ID}} 等佔位符
├── .env                               # 已替換環境變數佔位符
└── deploy_to_target.sh                # 動態生成,可執行

3. 模板說明

3.1 .env.tpl — 環境變數模板

路徑remote-blueprints/template/.env.tpl

AGENT_ID={{AGENT_ID}}
CONTROL_UI_TOKEN={{CONTROL_UI_TOKEN}}
HUB_QDRANT_URL=http://100.115.94.1:6333
# mem0-integration skill (Layer 4) reads these; align with HUB_QDRANT_URL if using central Qdrant
MEM0_QDRANT_HOST=100.115.94.1
MEM0_QDRANT_PORT=6333
# Generic LLM provider configuration (provider-agnostic)
LLM_BASE_URL={{LLM_BASE_URL}}
LLM_API_KEY={{LLM_API_KEY}}
LLM_MODEL_ID={{LLM_MODEL_ID}}
  • AGENT_ID:實例 ID,用於 container_name、標籤與部分配置;僅允許 [a-zA-Z0-9_-]
  • CONTROL_UI_TOKEN:Gateway Control UI token,可由腳本自動生成。
  • HUB_QDRANT_URL / MEM0_QDRANT_*:指向中心 Qdrant(mem0 Layer 4 所用)。
  • LLM_BASE_URL / LLM_API_KEY / LLM_MODEL_ID:解耦後的通用 LLM provider 設定,對應 OpenAI-compatible API 或其他兼容端點。

3.2 config/openclaw.json — Gateway 配置

路徑remote-blueprints/template/config/openclaw.json

核心片段:

{
  "gateway": {
    "port": 18789,
    "mode": "local",
    "bind": "lan",
    "controlUi": {
      "allowedOrigins": [
        "http://localhost:*",
        "http://localhost:18789",
        "http://127.0.0.1:*",
        "http://127.0.0.1:18789",
        "http://100.115.94.1:18789"
      ],
      "dangerouslyDisableDeviceAuth": false
    },
    "auth": {
      "mode": "token",
      "token": "${CONTROL_UI_TOKEN}",
      "rateLimit": {
        "maxAttempts": 10,
        "windowMs": 60000,
        "lockoutMs": 300000
      }
    },
    "trustedProxies": ["127.0.0.1", "100.115.94.1", "::1"]
  },
  "agents": {
    "defaults": {
      "workspace": "/root/.openclaw/workspace",
      "model": { "primary": "default_llm/primary" }
    },
    "list": [
      { "id": "main" },
      { "id": "{{AGENT_ID}}", "enabled": true }
    ]
  },
  "models": {
    "mode": "merge",
    "providers": {
      "default_llm": {
        "baseUrl": "${LLM_BASE_URL}",
        "apiKey": "${LLM_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "primary",
            "name": "${LLM_MODEL_ID}",
            "contextWindow": 128000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },
  "memory": { "backend": "qmd", "citations": "auto" },
  "skills": { "install": { "nodeManager": "npm" }, "entries": {} },
  "plugins": { "allow": [], "load": { "paths": [] }, "entries": {} }
}
  • gateway.auth.token 使用 ${CONTROL_UI_TOKEN},與 .env / compose 變數名一致。
  • models.providers.default_llm 使用 ${LLM_BASE_URL} / ${LLM_API_KEY} / ${LLM_MODEL_ID},完整解耦底層供應商;agents.defaults.model.primary 指向 "default_llm/primary"
  • agents.list 中預先註冊 {{AGENT_ID}},渲染後即為遠端 Agent 的 ID。

3.3 docker-compose.yml.tpl — 容器編排模板

路徑remote-blueprints/template/docker-compose.yml.tpl

# Remote Agent - OpenClaw Gateway
# Placeholders: {{AGENT_ID}}, {{AGENT_NAME}}, {{PROJECT_ID}}
# After render: .env supplies CONTROL_UI_TOKEN, LLM_BASE_URL, LLM_API_KEY, LLM_MODEL_ID, HUB_QDRANT_URL, MEM0_QDRANT_*
services:
  gateway:
    build: .
    container_name: {{AGENT_ID}}
    network_mode: "host"
    restart: always
    environment:
      - OPENCLAW_GATEWAY_AUTH_MODE=token
      - OPENCLAW_GATEWAY_AUTH_TOKEN=${CONTROL_UI_TOKEN}
      - NODE_OPTIONS=--max-old-space-size=1536
      - QDRANT_HOST=${HUB_QDRANT_URL}
      - AGENT_TAG={{AGENT_ID}}
      - LLM_BASE_URL=${LLM_BASE_URL}
      - LLM_API_KEY=${LLM_API_KEY}
      - LLM_MODEL_ID=${LLM_MODEL_ID}
      - MEM0_QDRANT_HOST=${MEM0_QDRANT_HOST}
      - MEM0_QDRANT_PORT=${MEM0_QDRANT_PORT}
    volumes:
      - ./config/openclaw.json:/root/.openclaw/openclaw.json
      - ./skills:/root/.openclaw/workspace/skills
      - ./plugins:/root/.openclaw/workspace/plugins
      - ./archive:/root/.openclaw/workspace/archive
      - ./agents:/root/.openclaw/workspace/agents
  • network_mode: host 方便 Tailscale / SSH 隧道使用。
  • ./agents 掛載到 /root/.openclaw/workspace/agents,配合 openclaw.json 中的 agents 配置與未來 auto-discovery 能力。

3.4 Agent Profile 模板 — 認知配置

路徑remote-blueprints/template/agents/{{AGENT_ID}}.json.tpl

{
  "id": "{{AGENT_ID}}",
  "name": "{{AGENT_NAME}}",
  "project_id": "{{PROJECT_ID}}",
  "metadata": {
    "project_id": "{{PROJECT_ID}}",
    "role": "project-specialized-remote-agent"
  },
  "systemPrompt": "You are an AI agent named {{AGENT_NAME}}. You belong to project {{PROJECT_ID}}. Always follow the project conventions, coordinate with the main hub agent, and log important decisions to shared memory."
}
  • 在渲染與 rename 後,會變成 agents/<AGENT_ID>.json 並掛載到 workspace,供 Gateway 或其他輔助工具使用。

3.5 Dockerfile — 執行環境與權限

路徑remote-blueprints/template/Dockerfile

# Remote Agent - OpenClaw Gateway
# Base: node:20-slim; deps for build + image processing (libvips)
FROM node:20-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
    git \
    python3 \
    make \
    g++ \
    libvips-dev \
    && rm -rf /var/lib/apt/lists/*

RUN npm install -g @openclaw/cli

RUN mkdir -p /root/.openclaw/workspace/skills \
             /root/.openclaw/workspace/plugins \
             /root/.openclaw/workspace/archive \
    && chmod -R 777 /root/.openclaw/workspace/archive

EXPOSE 18789

CMD ["openclaw", "gateway", "--port", "18789"]
  • 確保 archive/ 在容器內存在並可寫入(chmod 777),避免 Volume 掛載後出現 Permission Denied。

4. 腳本說明

4.1 generate_remote.sh — 實例壓鑄腳本

路徑scripts/generate_remote.sh

4.1.1 模式說明

  • 互動模式(人類操作)
    • 條件:未帶任何 flag(-a/-n/-p/-u/-k/-m/-t)。
    • 行為:
      • 依序 readAGENT_IDAGENT_NAMEPROJECT_IDLLM_BASE_URLLLM_API_KEYLLM_MODEL_IDCONTROL_UI_TOKEN
      • AGENT_ID 為空則直接報錯退出。
  • 非互動模式(ChatOps Ready)
    • 條件:只要帶任一 flag(-a/-n/-p/-u/-k/-m/-t),即視為非互動模式。
    • 行為:
      • 絕對不執行任何 read,完全靜默(只輸出日誌 / JSON 錯誤)。
      • 必填參數AGENT_IDLLM_BASE_URLLLM_API_KEYLLM_MODEL_ID
      • 若任一缺失,輸出 JSON 錯誤並 exit 1,示例:
        {"ok":false,"error":"missing_required_params","missing":["AGENT_ID","LLM_BASE_URL"]}
        
      • AGENT_NAME 預設為 AGENT_IDPROJECT_ID 預設為 "default"

4.1.2 參數與旗標

  • 支援的 flags:
    • -a <AgentID>AGENT_ID
    • -n <AgentName>AGENT_NAME
    • -p <ProjectID>PROJECT_ID
    • -u <BaseURL>LLM_BASE_URL
    • -k <API_Key>LLM_API_KEY
    • -m <ModelID>LLM_MODEL_ID(例如 qwen-max, gpt-4o
    • -t <ControlUiToken>CONTROL_UI_TOKEN(可選;未提供則自動生成)

4.1.3 Token 自動生成

  • 若解析完所有輸入後 CONTROL_UI_TOKEN 仍為空:
    • 首選:openssl rand -hex 24 生成 48 位十六進位字串。
    • 若系統無 openssl,改用 /dev/urandom + base64 + 過濾成 hex 的備援方案(並輸出 WARN 日誌)。

4.1.4 安全與佔位符替換

  • AGENT_ID 僅允許 [a-zA-Z0-9_-],否則報錯退出。
  • 使用統一的 escape_sed_val() 對所有值進行轉義:
    • \\\&\&/\/
  • 所有 sed 替換使用 # 作為定界符,避免 URL 中的 / 破壞語法:
sed -i "s#{{AGENT_ID}}#$AGENT_ID#g" "$f"
sed -i "s#{{AGENT_NAME}}#$AGENT_NAME_ESC#g" "$f"
sed -i "s#{{PROJECT_ID}}#$PROJECT_ID_ESC#g" "$f"
sed -i "s#{{LLM_BASE_URL}}#$LLM_BASE_URL_ESC#g" "$f"
sed -i "s#{{LLM_API_KEY}}#$LLM_API_KEY_ESC#g" "$f"
sed -i "s#{{LLM_MODEL_ID}}#$LLM_MODEL_ID_ESC#g" "$f"
sed -i "s#{{CONTROL_UI_TOKEN}}#$CONTROL_UI_TOKEN_ESC#g" "$f"
  • 佔位符覆蓋範圍:
    • {{AGENT_ID}}, {{AGENT_NAME}}, {{PROJECT_ID}}
    • {{LLM_BASE_URL}}, {{LLM_API_KEY}}, {{LLM_MODEL_ID}}
    • {{CONTROL_UI_TOKEN}}
    • 兼容移除舊的 {{BAILIAN_API_KEY}}(若仍存在會被同值覆蓋)。
  • 遍歷所有 *.tpl.env.tpl 檔案(包含 agents/{{AGENT_ID}}.json.tpl)。

4.1.5 檔名重寫與 deploy 腳本生成

  • 在 rename 所有 *.tpl 前,先將 agents/{{AGENT_ID}}.json.tpl 改名為 agents/<AGENT_ID>.json.tpl,再統一移除 .tpl 副檔名。
  • 最終 agents/<AGENT_ID>.json 會被 docker-compose 掛載到 /root/.openclaw/workspace/agents/<AGENT_ID>.json
  • deploy_to_target.sh 透過單引號 heredoc 生成,內部變數不會被當前 shell 展開,之後用 sed 注入實際 AGENT_ID,邏輯:
    • TARGET_IP / SSH_USER 參數檢查。
    • 檢查本地 docker-compose.yml 是否存在。
    • ssh mkdir 遠端目錄後,用 tar cf - . | ssh tar xf - 覆蓋整個目錄。
    • 執行 docker compose down 2>/dev/null || true && docker compose up -d --build

4.1.6 結尾輸出

  • 成功後輸出:
[OK] Instance ready: /root/.openclaw/workspace/remote-blueprints/<AGENT_ID>
[OK] CONTROL_UI_TOKEN: <實際 token>
Next: cd /root/.openclaw/workspace/remote-blueprints/<AGENT_ID> && ./deploy_to_target.sh <TARGET_IP> [SSH_USER]

4.2 sync_skill.sh — Skill/Plugin 同步腳本

路徑scripts/sync_skill.sh

  • 參數:<TARGET_IP> <AGENT_ID> <MODULE_DIR_NAME>
  • 本地來源:workspace/skills/<MODULE_DIR_NAME>,不存在則報錯退出。
  • 遠端目的:/opt/openclaw-remote/<AGENT_ID>/skills/
  • 優先使用 rsync -avz --exclude 'node_modules',無 rsync 才降級為 scp -r
  • 同步完成後執行:ssh root@<TARGET_IP> 'cd /opt/openclaw-remote/<AGENT_ID> && docker compose restart'

5. 環境變數與配置對齊表

變數名 .env.tpl docker-compose openclaw.json 說明
AGENT_ID {{AGENT_ID}} container_name / AGENT_TAG agents.list[].id(模板為 {{AGENT_ID}} 遠端 Agent ID,僅允許 [a-zA-Z0-9_-]
CONTROL_UI_TOKEN {{CONTROL_UI_TOKEN}} OPENCLAW_GATEWAY_AUTH_TOKEN gateway.auth.token="${CONTROL_UI_TOKEN}" Gateway Control UI token
HUB_QDRANT_URL 固定 http://100.115... QDRANT_HOST 中心 Qdrant URL
MEM0_QDRANT_HOST 100.115.94.1 MEM0_QDRANT_HOST mem0-integration 使用的 Qdrant host
MEM0_QDRANT_PORT 6333 MEM0_QDRANT_PORT mem0-integration 使用的 Qdrant port
LLM_BASE_URL {{LLM_BASE_URL}} LLM_BASE_URL models.providers.default_llm.baseUrl 通用 LLM 端點(OpenAI compatible 等)
LLM_API_KEY {{LLM_API_KEY}} LLM_API_KEY models.providers.default_llm.apiKey 通用 LLM API key
LLM_MODEL_ID {{LLM_MODEL_ID}} LLM_MODEL_ID models.providers.default_llm.models[].name 實際使用的大模型 ID(如 qwen-max, gpt-4o)

重要openclaw.json 僅透過 ${VAR_NAME} 讀取這些變數,實際值由 .env / compose 注入,不再使用任何 SecretRef 物件,也不再引用 BAILIAN_API_KEY


6. 修復與變更記錄(供 AI / 維運對照)

項目 問題 / 風險 修復 / 改動摘要
LLM 提供商耦合 過去綁定 bailian 提供商與固定模型 ID 改為 default_llm provider,使用 ${LLM_BASE_URL}${LLM_API_KEY}${LLM_MODEL_ID} 完全解耦。
openclaw.json secrets 格式 使用 SecretRef 或硬編 API key 改為一致使用 ${CONTROL_UI_TOKEN}${LLM_API_KEY} 字串插值,並由 .env/compose 提供實際值。
Agent Profile 掛載路徑 先前構想使用 /root/.openclaw/agents 修正為 /root/.openclaw/workspace/agents,與 workspace 路徑對齊,並新增 agents/{{AGENT_ID}}.json.tpl
generate_remote 無交互模式 可能於缺參數時卡在 read 導致 Hang 帶任一 flag 即進入嚴格非互動模式,缺少必填參數時回傳 JSON 錯誤並立刻退出,不進行任何 read
sed URL 替換問題 https:// 中的 / 會破壞 s/old/new/g 全面改用 s#old#new#g,並對值先經 escape_sed_val 處理 \&/
Token / API key sed 注入風險 token 中含 &\ 造成 sed 失敗 使用 escape_sed_val 對所有值做轉義;同時限制 AGENT_ID 僅允許 [a-zA-Z0-9_-]
deploy_to_target 腳本嵌套變數 早期版本 heredoc 中混雜當前 shell 變數 改用單引號 heredoc 並使用 placeholder __AGENT_ID_PLACEHOLDER__,事後以 sed 注入實際 AGENT_ID。
mem0 Qdrant 依賴明確化 容器端 mem0 可能找不到 Qdrant 地址 .env.tpl + compose 中顯式提供 MEM0_QDRANT_HOSTMEM0_QDRANT_PORT

本版未再執行額外自動化測試;以上變動經過靜態檢查與少量手動 sanity run 佐證,建議在實際部署前再做一次端對端驗證。


7. 使用建議(高階)

  1. Main Agent ChatOps 調用
    • 建議統一由 Main Agent 以非互動模式呼叫:
      ./generate_remote.sh \
        -a advert-bot \
        -n "Advert Bot" \
        -p advert \
        -u https://llm.example.com/v1 \
        -k sk-xxx \
        -m qwen-max
      
  2. 部署
    • 在目標伺服器上確保 Docker 與 LLM 網路連線可用後,執行:
      cd /root/.openclaw/workspace/remote-blueprints/advert-bot
      ./deploy_to_target.sh <TARGET_IP> [SSH_USER]
      
  3. Skill 熱更新
    • 使用 sync_skill.sh 精準同步單一 Skill 目錄,避免重建鏡像:
      ./sync_skill.sh <TARGET_IP> advert-bot tavily
      

最後更新: 2026-03-12 — 將舊版 BAILIAN_API_KEY 說明全面替換為通用 LLM_BASE_URL / LLM_API_KEY / LLM_MODEL_ID 模型解耦方案,並補充 ChatOps 無交互模式與認知配置掛載設計。