Files
gori-agent/AGENTS.md
T
2026-08-16 11:07:33 +08:00

13 KiB
Raw Blame History

gori-agent 项目施工指南

本文件供 Kimi Code 等 Coding Agent 在本仓库中施工时使用。目标是让后续 Agent 先理解架构和配置契约,再做最小、可验证的修改。

1. 项目定位

gori-agent 是一个 Node.js 20+ / TypeScript 项目,通过 IM 接收用户请求,并通过官方 Agent Client Protocol(ACP)驱动 Coding Agent。

当前主链路:

用户
  → QQ / 其他 IM
  → Platform Adapter
  → Gateway
  → AcpSessionManager
  → AcpWorker
  → ACP Coding Agent(默认 Kimi Code)
  → 工具、脚本和工作目录
  → 原路返回用户

当前运行时只使用 ACP。不要重新引入“一句话启动一次 CLI”的单轮调用方式,也不要把 legacy CliAgent 当作运行时 fallback。

模型和 provider 属于 ACP 后端自身的配置。例如 Kimi Code 使用其自己的 config.toml;gori-agent/config.json 只配置如何启动 ACP backend,不负责复制或管理模型凭据。

2. 核心设计原则

  • Role 是业务身份:定义职责、workspace、skills 和权限策略。
  • Backend 是执行后端:定义 ACP 子进程的 command、args 和 env。
  • Skill 是可注入知识:顶层声明 SKILL.md,role 按 ID 引用。
  • Session 是连续对话:同一 platform + chat + role 复用同一 native ACP session。
  • 权限由 ACP policy 约束:persona 不是安全边界,不能替代 permission policy。
  • 默认 fail closed:不确定时拒绝权限,不自动扩大工具或命令范围。
  • 一个进程只登录一个 QQ Bot:多 Bot 使用多个进程和独立配置、端口、状态目录。

3. 代码结构

  • src/server.ts
    • 组装 store、role registry、ACP session manager、Gateway 和平台 adapter。
    • 挂载 health/platform/webhook 路由,按配置启动 QQ WebSocket。
  • src/config.ts
    • config v2 的 Zod schema、默认值、交叉引用校验和 v1 Kimi 配置迁移。
    • 新增配置字段时,必须先更新 schema,再更新模板、setup/doctor、测试和文档。
  • src/core/gateway.ts
    • 入站 allowlist、群聊 mention 规则、命令分发、per-chat 串行锁和回复发送。
    • /cancel 必须能绕过 chat lock,避免无法取消长任务。
  • src/core/command-router.ts
    • /help、/roles、/role、/status、/cancel、/new。
  • src/core/durable-session-store.ts
    • 持久化 role 选择和 ACP session binding。
    • 使用单 writer lock 和原子写入;不要绕过或手改运行中的 state。
  • src/roles/role-registry.ts
    • 读取 role、加载 skill、生成 fingerprint 和隐藏 bootstrap prompt。
  • src/roles/skill-loader.ts
    • 校验 skill 文件、大小限制并计算内容 hash。
  • src/acp/client.ts
    • ACP initialize、session new/resume/load、prompt、cancel 和 permission request。
  • src/acp/worker.ts
    • 在 role.workspace 中启动 ACP 子进程,处理超时、取消和异常退出。
  • src/acp/session-manager.ts
    • 管理 chat/role binding、worker 池、冷恢复、idle sweep、容量淘汰和 reset。
  • src/platforms/qq/
    • QQ WebSocket、webhook、验签、消息标准化和发送。
  • src/cli.ts、src/cli/
    • setup、doctor、status 和 backend discovery。
  • src/agents/、src/core/session-store.ts
    • legacy compatibility/reference,不是当前运行链路。除非需求明确,不要在这里扩展新能力。
  • dist/
    • TypeScript 构建产物。只修改 src/,不要手改 dist/。

4. Config v2 契约

唯一可提交的配置模板是 config.example.json。真实部署配置复制为本地 config.json:

cp config.example.json config.json
chmod 600 config.json

config.json 和备份包含 IM credentials,不得提交。

4.1 顶层字段

configVersion  必须为 2
server         HTTP 服务配置
policy         IM 入站访问策略
acp            ACP 生命周期、状态和进程池配置
backends[]     ACP 后端启动定义,至少一个
skills[]       可选 SKILL.md 定义
defaultRole    默认 role ID
roles[]        业务角色定义,至少一个
platforms      QQ、Feishu、WeCom、Webhook、Weixin 配置

Zod 会剥离 schema 未声明的字段。因此不能只在 JSON 中增加字段而不修改 src/config.ts。

4.2 server

  • host:默认 0.0.0.0。
  • port:1–65535;多实例必须使用不同端口。
  • publicBaseUrl:反向代理或公开 webhook 基础地址;不需要时为空。

4.3 顶层 policy

  • allowedUsers: string[]:空数组表示不按用户限制;非空时精确匹配。
  • allowedChats: string[]:空数组表示不按会话限制;非空时精确匹配。
  • requireMentionInGroup: boolean:群聊是否必须 @bot。
  • QQ 群 chat ID 形式为 group:<group_openid>。
  • 正式运维 Bot 应配置 allowlist,不要长期保持完全开放。

4.4 acp

  • stateFile:空字符串时使用 $GORI_AGENT_HOME/state/acp-sessions.json。
  • initializeTimeoutMs:ACP 初始化超时。
  • promptTimeoutMs:单轮 prompt 超时。
  • cancelGraceMs:取消后等待时间,超时才终止 worker。
  • idleTimeoutMs:空闲 worker 回收时间;session binding 仍可持久化恢复。
  • sweepIntervalMs:空闲扫描周期。
  • maxProcesses:最大 ACP 子进程数。

不同实例不得共享 stateFile 或 GORI_AGENT_HOME。持久 store 有单 writer lock,共享会使第二个实例启动失败。

4.5 backends[]

每项字段:

{
  "id": "kimi",
  "command": "/home/USER/.kimi-code/bin/kimi",
  "args": ["acp"],
  "env": {}
}

约束:

  • id 必须唯一。
  • command 必须是可执行程序。
  • Kimi Code backend 应使用 args: ["acp"]。
  • 子进程以 shell: false、cwd: role.workspace 启动。
  • env 会覆盖同名进程环境变量;不得把 token 或 API key 写入可提交模板。
  • 新增其他 Coding Agent 前,必须确认它提供兼容 ACP,或提供独立且有测试的 ACP adapter;不要假设普通 CLI 等同 ACP。

4.6 skills[]

每项字段:

{
  "id": "SKILL_ID",
  "file": "/absolute/path/to/SKILL.md",
  "maxBytes": 256000
}

约束:

  • id 必须唯一。
  • 建议使用绝对路径,避免不同启动目录导致解析变化。
  • 文件必须存在、可读、是普通文件且不超过 maxBytes。
  • Role 只能引用已在顶层声明的 skill ID。
  • Skill 内容会发送给 ACP backend,也参与 role fingerprint;不要在 skill 中放 secret。

4.7 roles[]

推荐一个 Bot 实例只保留它自己的一个 role:

{
  "id": "ROLE_ID",
  "backend": "kimi",
  "workspace": "/absolute/path/to/workspace",
  "persona": "明确描述职责、边界和何时停止请求确认。",
  "skills": [],
  "policy": {
    "permissionMode": "deny",
    "allowedTools": [],
    "allowedCommandPatterns": []
  }
}

约束:

  • Role id 必须唯一,defaultRole 必须引用存在的 role。
  • workspace 必须是绝对路径,并应在 doctor 时真实存在。
  • backend 和 skills 引用必须存在。
  • 修改 role ID、backend、workspace、persona、policy 或 skill 内容会改变 fingerprint;下一条消息会创建新 native session,避免沿用旧身份上下文。

权限模式:

  • deny:拒绝所有 ACP permission request;新角色默认使用此模式。
  • allowlist:只允许 allowedTools;bash/terminal 还必须匹配至少一个 allowedCommandPatterns 正则。
  • auto:自动允许,等价于高风险/yolo;只有用户明确要求、workspace 与 Bot 访问范围都可控时才能配置。

配置 allowlist 时:

  • 使用最小工具集合。
  • 命令正则应锚定开头并限制参数,不要使用 .* 放行所有命令。
  • 删除、部署、推送、发送消息等不可逆或外部操作仍应在 persona 中要求确认。
  • permission request 信息不足时必须拒绝,不能猜测。

4.8 platforms.qq

{
  "enabled": true,
  "connectionMode": "websocket",
  "appId": "QQ_APP_ID",
  "clientSecret": "QQ_CLIENT_SECRET",
  "botSecret": "",
  "verifySignature": true,
  "botNames": ["QQ_BOT_NAME"],
  "intents": 33554432,
  "shard": [0, 1]
}
  • WebSocket 登录需要有效的 appId 和 clientSecret。
  • Webhook 验签使用 botSecret || clientSecret。
  • botNames 用于 mention 识别,应与平台上的机器人名称一致。
  • 一个 config 只有一个 QQ 对象,因此一个进程只能登录一个 QQ Bot。
  • 不要把 QQ 注销、群注销、无权限等平台 4xx 错误误判成 ACP session 错误;先检查错误码、目标 chat/user openid 和消息发送 endpoint。

其他平台字段以 src/config.ts schema 为准。平台 enabled 不一定会统一禁用所有 HTTP 路由;公开 webhook 时仍需检查路由和验签实现。

5. Role 与 Session 行为

  • Binding key 是 platform + chatId + roleId。
  • 同一 chat 的不同 role 拥有不同 native ACP session。
  • 首次 prompt 会创建 session、发送隐藏 bootstrap,成功后保存 binding,再发送用户请求。
  • Gateway 或 ACP worker 重启后,使用持久 binding 尝试 session/resume,必要时回退 session/load。
  • /new 删除当前 chat/role binding;下一条普通消息再创建新 session。
  • /cancel 取消当前 turn,不应等待正在执行的 chat lock。
  • Prompt 失败不能擅自重放,因为工具操作可能已经产生副作用。
  • Session 上下文由 native ACP Agent 维护;gori-agent 维护角色选择、binding、生命周期和恢复信息,不应每轮把完整历史重新拼给 CLI。

6. 多机器、多 Bot 部署规范

每个 Bot 使用一份位于部署机器上的本地 config.json,不要在仓库中创建 config.ops.json、config.developer.json 等带真实凭据的文件。

每个实例至少要唯一:

  • QQ appId、clientSecret、botNames
  • server.port
  • GORI_AGENT_HOME,或显式且独立的 acp.stateFile
  • role ID、workspace、persona 和 policy

示例:

GORI_AGENT_HOME=/home/USER/.gori-agent-ROLE_ID \
  ./gori-agent.sh start-daemon --config ./config.json

GORI_AGENT_HOME 隔离:

  • PID
  • 日志
  • 默认 ACP session state
  • 单实例锁

同一机器启动多个实例时,每个实例应从各自部署目录运行,或明确指定独立配置路径和 GORI_AGENT_HOME。

7. 配置施工流程

当用户让 Agent 配置一个新角色或新 Bot 时,按以下顺序执行:

  1. 读取 AGENTS.md、config.example.json 和相关 schema;不要先读取或展示真实 secrets。

  2. 明确 role 的职责、workspace、所需 skills、允许的工具和命令。

  3. 确认 backend 可执行路径以及 kimi acp 可用。

  4. 从唯一模板复制本地 config.json,不另建可提交的具体 Bot 模板。

  5. 填写本机 QQ credentials;不要在回复、日志、diff 或测试输出中回显。

  6. 默认先用 deny;需要施工能力时配置最小 allowlist;只有明确授权才使用 auto。

  7. 设置文件权限为 0600。

  8. 运行配置和 backend 检查:

    ./gori-agent.sh discover-backends --config ./config.json
    ./gori-agent.sh doctor --config ./config.json
    
  9. 前台启动,确认 QQ WebSocket ready,再从 IM 执行只读验收。

  10. 前台通过后,使用唯一 GORI_AGENT_HOME 后台启动。

  11. 任何包含 secret 的配置、备份和日志都不得加入 Git。

若缺少真实凭据,可以完成无密钥模板和规范,但不得虚构 credentials,也不得声称真实 QQ 登录已验证。

8. 常用命令

npm install
npm run typecheck
npm test
npm run build

gori-agent setup --config ./config.json
gori-agent discover-backends --config ./config.json
gori-agent doctor --config ./config.json
gori-agent start --config ./config.json

./gori-agent.sh start --config ./config.json
./gori-agent.sh start-daemon --config ./config.json
./gori-agent.sh status --config ./config.json
./gori-agent.sh logs
./gori-agent.sh stop

gori-agent.sh 不会检测源码是否比 dist/ 新。修改 TypeScript 后必须显式运行 npm run build。

9. 修改与验收规则

  • 做最小、局部、可审查的修改,不做无关重构。

  • 先修改 src/,不要直接修改 dist/。

  • 行为变化应补对应测试;不要通过削弱测试来适配实现。

  • 配置 schema 变化必须同步:

    • src/config.ts
    • config.example.json
    • setup/doctor(如适用)
    • README 和本文件
    • 配置测试
  • 平台错误必须保留足够的错误码和 trace ID 用于诊断,但不得输出 secret。

  • 修改后运行:

    npm run typecheck
    npm test
    npm run build
    git diff --check
    
  • 测试未通过时不能宣称完成。

  • 不执行真实 QQ 消息、pull、部署、push、创建 PR 等外部操作,除非用户明确要求并授权。

  • 不自动执行 Git commit/push;需要时按用户当次指令处理。

10. 敏感信息与禁止提交内容

不得提交或粘贴:

  • config.json
  • config.json.*.bak
  • 任意包含真实 Bot/App credentials 的自定义配置
  • .env
  • backends[].env 中的 token/API key
  • ACP state、PID、lock 和 session metadata
  • 日志中的真实 chat ID、user ID、message ID、消息正文或 ACP stderr 敏感内容

唯一可提交配置模板:config.example.json。其中只能使用明显占位符。

当前 .gitignore 已覆盖 config.json、备份、日志、dist/、node_modules/ 和 coverage。新增其他具体配置文件名时,不要依赖命名约定判断安全;只要包含真实凭据,就必须留在仓库外或明确忽略。