graft-comboagent
本页讲的是 本地宿主版 的 combo agent 客户端:装在 Cursor / Claude Code / Codex / Trae 里、通过 HTTPS 访问云端 combo agent。和它对应的云端 builtin 版 graft 请看 skills/agentic/graft;底层机制看 核心概念 · Graft。
它解决什么问题
工程师每天的工作分两端:
- 云端 combo agent:跑 ASPICE 追溯、需求审计、跨基线变更分析、新颖性检索等"重型"分析任务,并沉淀到云端 KB
- 本地 IDE(Cursor / Claude Code / Codex / Trae):改代码、跑测试、提 PR、写文档
两端要打通的不止是"复制粘贴 session 摘要"。graft-comboagent 在一个 skill 包里把这件事抽成 三类用途:
| 用途 | 解决什么 | 主要 action |
|---|---|---|
| A · KB 检索 | 让本地 agent 把云端 KB 当成 RAG 数据源——不依赖云端 session 也能直接查文档 / chunk | list_kbs · kb_detail · list_documents · get_doc_profile · list_chunks · search --source document |
| B · Session 嫁接 | 把云端已有 session 的 digest / round / 产出物拉到本地上下文里继续工作 | list_sessions · get_digest · get_round · search --source round · read_file · download · list_files · search_by_artifact · grep_file |
| C · 任务派发 | 把一段新指令丢回云端某个长寿命 session 异步跑(重型计算 / 工具栈不在本地 / 需要别人继续跟进) | dispatch_task |
A 类是纯 RAG(不开 session);B 类是只读 graft;C 类是唯一一种"写入"入口——它不能创建/删除 session 或文件,只能给 已存在 的 session 多触发一轮。
架构
- 服务端:
api/apps/graft_app.py暴露 user-level 端点 - 认证:复用 web UI 的
itsdangerous签名 access_token,登录走平台已有的/v1/user/login - 客户端:4 个 Python 脚本(login / whoami / logout / call)+ 单一公钥文件
- 写动作(如
register_artifact/copy_kb_document/save_*)在 client 与 server 双层拦截;只有dispatch_task是 唯一允许 的写入路径
安装
graft-comboagent 是一个独立目录(在仓库 skills/graft-comboagent/,公开仓 Nox-Lumen-tech/combo-skills)。装到对应宿主:
| 宿主 | 安装命令 | 官方 Skills 文档 |
|---|---|---|
| Cursor | cp -r skills/graft-comboagent ~/.cursor/skills/或 ln -s $(pwd)/skills/graft-comboagent ~/.cursor/skills/graft-comboagent | cursor.com/docs/skills |
| Claude Code | cp -r skills/graft-comboagent ~/.claude/skills/ | code.claude.com/docs/en/skills |
| Trae | cp -r skills/graft-comboagent ~/.trae/skills/ | docs.trae.ai/ide/skills |
| Codex | cp -r skills/graft-comboagent ~/.codex/skills/ | (随仓库内 SKILL.md 标准) |
Cursor 同时也会扫描
~/.claude/skills/、~/.codex/skills/,所以软链一份在~/.cursor/skills/后,也可以在 Cursor / Claude Code / Codex 通用。
装完重启宿主让 skill 被 discovery 阶段加载(Claude Code 在已开会话内会实时检测,但新建顶层目录仍要重启)。
Python 依赖:
老环境只有
pycrypto也能用,login.py会自动 fallback。
首次使用:三步走
Step 1 · 登录
交互提示:
URL 默认值是
https://mfg.nox-lumen.com。如果你的私有部署在别处,直接覆盖一行就好。
发生了什么:
- 读 skill 包根目录下的
public.pem - 用 RSA 加密 password(与 web UI 的
crypt()完全一致) - POST
/v1/user/login→ 拿到signed_auth_token - 写入
~/.config/graft-comboagent/token.json(chmod 0600)
Step 2 · 验证身份
输出:
Step 3 · 试一下三类用途
能力清单
所有命令通过 scripts/call.py 走,token 自动从 ~/.config/graft-comboagent/token.json 加载。
Skill 包内自带
references/action-decision-tree.md— 一个按用户意图分支的快表("我想找一篇文档" / "我想看历史 session" / "让云端帮我跑一下"),本地 LLM 在选 action 之前应当先扫这张表,避免误用。
A · KB 检索(不依赖 session 也能跑)
| Action | 用途 | 命令 |
|---|---|---|
list_kbs | 发现租户下可见的 KB | call.py list_kbs |
kb_detail | 看一个 KB 的元信息(描述、文件数、向量配置) | call.py kb_detail --kb-id "ASPICE 工程库" |
list_documents | 列 KB 里的文档(支持 --query / --page-size) | call.py list_documents --kb-id "ASPICE 工程库" --query 冷却 |
get_doc_profile | 看单文档的画像(页数、解析状态、元数据) | call.py get_doc_profile --doc-id <id> |
list_chunks | 列文档的所有 chunk(跳页 / 大文档定位) | call.py list_chunks --doc-id <id> |
search | document 源=hybrid 检索(=前端"提问"按钮的能力) | call.py search --query <kw> --source document --kb-ids "ASPICE 工程库" |
search --source document是 RAG 的入口;底层走平台unified_search的 BM25 + 向量混合检索 + rerank,跟前端 ChatBox 一致。
B · Session 嫁接(只读访问已有 session)
| Action | 用途 | 命令 |
|---|---|---|
list_sessions | 发现可见 session(自己的 + 团队共享) | call.py list_sessions --query <kw> |
get_digest | 看一个 session 的全貌(每轮做了什么、产出什么) | call.py get_digest --session-id <x> |
get_round | 取某轮的精确输入输出 | call.py get_round --session-id <x> --round-id N |
search | round 源=跨 session 全文搜(--session-id "*") | call.py search --query <kw> --session-id "*" --source round |
search_by_artifact | 按产出物名找 | call.py search_by_artifact --query <名> --session-id <x> |
grep_file | 文件内全文搜 | call.py grep_file --query <kw> |
read_file | 服务端 markitdown 把 docx/xlsx/pdf 转 markdown 文本,节流后给 AI 阅读 | call.py read_file --path <p> [--center-line N --context-lines K] [--find <kw>] |
download | 服务端 原始字节流,写本地文件(用 Office 打开 / pandas 读 xlsx) | call.py download --path <p> --out ./report.docx |
list_files | 列 session 的产出物路径 | call.py list_files --session-id <x> |
read_file 的精读模式(避免一次拉全文)
read_file 默认会把整篇 markdown 全返。大文件(>20K tokens)建议改成精读:
C · 任务派发(唯一一种"写入")
| Action | 用途 | 命令 |
|---|---|---|
dispatch_task | 把新一轮 prompt 异步丢回云端 已存在 的 session | call.py dispatch_task --session-id NAME-OR-UUID --prompt "..." |
发生了什么:
- 服务端把这条 prompt 当成一轮新 round 入队
- HTTP 立刻返回(不阻塞 IDE)
- 云端 session 在后台异步跑
- 跑完后用
list_sessions/get_digest/get_round --round-id 最新回头取结果
dispatch_task 的能力边界:只能给已存在 的 session 多触发一轮——不能新建 session、不能删 session、不能改 session 元信息。
session_id / kb_id 参数支持名称
与平台的 kb_ids / doc_ids 模式对齐——这两个参数 支持 ID,也支持人读名称,名称会自动解析为 ID:
如果名称匹配多个,向用户确认,不要自行选一个。
响应结构
所有 action 通过 scripts/call.py 走,stdout 是 JSON。统一结构:
错误时:
LLM 看到 success=false 时,应当先读 code + hint,而不是直接重试同一调用。
上下文节流规则(重要)
本地 IDE 的 context 比云端紧得多。skill 自带的 SKILL.md 强约束 LLM 必须按以下顺序:
- session 类查询先
get_digest,获取目录型概览(5–20K tokens) - 按需 drill down:digest 指明 Round N 有关键结论,才调
get_round --round-id N - 大文件不全文进上下文:
read_file默认调--find/--center-line精读;download拿到的字节流绝不塞进 prompt - KB 检索默认带
--source document:搜文档不要扫全 round(那是 B 类的事) - 不做全量拖库:禁止循环
get_round拉所有轮、循环list_chunks拉整个 KB、循环download拉所有 artifact
违反这些规则的最常见后果:本地 IDE context 在三五次调用后就崩了,AI 无法继续追问。
三个典型工作流
工作流 1(A 类)· 让本地 agent 用云端 KB 当 RAG
"我在本地写一段 EEA 控制器初始化代码,参照云端 'EEA 平台库' 里的标准实现。"
关键节制:先用 search 定位最相关的几个 chunk,再 read_file --find 精读对应段,不要上来就把整本 KB 文档读进上下文。
工作流 2(B 类)· 嫁接已有 session
"对照云端 session 'ASPICE 分析' 的 DFMEA 结论,审查本地
src/下的代码,找出未覆盖的 SRS 需求。"
工作流 3(C 类)· 让云端继续跑
"我刚改完代码 push 上去了,让云端 session 重跑一遍 ASPICE 追溯,跑完我自己回头看。"
dispatch_task 的精髓:本地 IDE 不阻塞。重型分析丢回云端,agent 继续做手头的事,结果晚点回来取。
环境变量
| 变量 | 用途 | 默认 |
|---|---|---|
GRAFT_COMBOAGENT_SERVER | login 的默认服务器 URL | https://mfg.nox-lumen.com |
GRAFT_COMBOAGENT_EMAIL | login 的默认 email | — |
GRAFT_COMBOAGENT_TOKEN | token 文件路径 | ~/.config/graft-comboagent/token.json |
GRAFT_COMBOAGENT_DL_DIR | download 默认落盘目录 | ./.graft/downloads/ |
服务端依赖
要让本地 skill 工作,对应 ragbase 服务端必须包含这些改动:
api/apps/user_app.py的/v1/user/login响应在data里追加signed_auth_token(用itsdangerous签发)api/apps/graft_app.py暴露:POST /v1/graft/memory/unified_search— A 类(KB 检索)+ B 类(session 嫁接)所有 JSON action 入口GET /v1/graft/memory/download— B 类原始字节下载POST /v1/graft/dispatch— C 类任务派发
所有端点都 @login_required,权限校验完全复用现有 _verify_graft_access(同租户 + owner / 共享可见 + 写动作拦截)。
部署完成后,调用方 signed_auth_token 通过 Authorization: Bearer ... 头携带。
已知限制
- 几乎只读:除
dispatch_task外不能写回云端;它本身也不能新建/删除 session 或文件,只能给已有 session 触发新一轮 - 单 profile:一次只能登录一个 ragbase server;切换需
logout.py+ 重login.py,或用GRAFT_COMBOAGENT_TOKEN指向不同文件 - 不支持浏览器级 SSO:当前只支持 email + password 登录(如需 OAuth / SSO 请提需求单)
- 单次下载 ≤ 200 MB:服务端硬上限,防止误操作拖爆带宽
- dispatch_task 不返回最终结果:只返回入队 ack;结果用
get_digest/get_round异步取
故障排查
| 症状 | 原因 | 处理 |
|---|---|---|
[FATAL] public.pem 不存在 | skill 目录根缺公钥文件 | 从 ragbase conf/public.pem 复制到 skill 包根 |
[FATAL] 服务器没有返回 signed_auth_token | 服务端没部署 login 响应追加字段的改动 | 联系管理员升级到含 graft 改动的 ragbase |
[ERR] 未登录 | 本地 token 文件不存在 | python scripts/login.py |
HTTP 401 / 认证失效 | access_token 被别处 login 重置 | 重新 python scripts/login.py |
code: ACCESS_DENIED | 目标 session / KB 不在你可见范围 | 确认 owner / 共享关系;换 session_id / kb_id |
code: NOT_FOUND | path 拼错或文件不存在 | 先 list_files / list_documents / grep_file 确认路径 |
code: ACTION_NOT_ALLOWED | 误用了写 action(如 register_artifact / copy_kb_document) | graft 几乎只读;只有 dispatch_task 可写 |
code: FILE_TOO_LARGE | 超过 200 MB 服务端硬上限 | 让产出物发布时做分卷或专用下载通道 |
dispatch_task 之后 session 没动 | session 已被 close/暂停 | 先 get_digest 看 session 状态,状态正常再重发 |
与云端 builtin graft 的对照
| 维度 | 云端 agentic/graft | 本地 graft-comboagent(本页) |
|---|---|---|
| 谁在调 | combo agent 平台上的 Agent | 用户本地 IDE(Cursor / Claude Code / Codex / Trae)里的 AI |
| 调用通道 | 平台进程内 FunctionTool 直调 unified_search | 本地 Python 脚本 → HTTPS → ragbase 端点 |
| 认证 | 平台 session 内置 | 本地 ~/.config/graft-comboagent/token.json |
| 用途范围 | 单一:跨 session graft(B 类) | 三类:A KB 检索 + B session 嫁接 + C 任务派发 |
| 大文件处理 | Agent 上下文里直读 | 先 read_file --find / --center-line 精读,或 download 落地后再 Read |
| 写操作 | 通过其他 builtin skill 实现 | 几乎只读;dispatch_task 是唯一例外,且不能新建/删除 session |
相关文档
- 本地 Coding Agent 联用 — 本分类总览
- skills/agentic/graft — 云端 builtin 版 graft
- 核心概念 · Graft — Graft 机制总论
- ASPICE 工程闭环案例 — 云端 + 本地 graft 的端到端使用
Nox-Lumen-tech/combo-skills— skill 公开仓(包含完整 SKILL.md 与决策树)