module/file.py:function_nameknowhub/docs/decisions.mdKnowHub 服务器托管的远端 Agent,供客户端通过统一的 agent 工具(agent_type="remote_xxx")调用。
目前部署:
| agent_type | 职责 | 允许的 skills | 核心实现 |
|---|---|---|---|
remote_librarian |
知识库查询整合 / 知识上传图谱编排 | ask_strategy(默认)/ upload_strategy |
knowhub/agents/librarian.py::run_librarian |
remote_research |
深度调研,全网搜集 + 总结 | —(不支持动态 skill) | knowhub/agents/research.py::research |
一个 Agent,多种模式:Librarian 是同一个 AgentRunner,调用方通过 skills 参数选择当前的策略——这比通过 task 内容或独立 agent_type 区分模式更显式、更可靠。
skills 的语义:
agent 工具的 skills 参数透传到 HTTP body)ALLOWED_SKILLS 白名单过滤(非法 skill 被忽略并打 warning)所有 agent 调用同步执行——服务器处理完成后才返回结果。
新增远端 Agent 时,handler 构造的 RunConfig 必须显式满足三条:
| 约束 | 如何配置 |
|---|---|
禁止调用 agent / evaluate 工具 |
用 tools=[...] 精确列表不含它们;或 tool_groups + exclude_tools=["agent","evaluate"] |
| 关闭自动知识提取 / 复盘 | knowledge=KnowledgeConfig(enable_extraction=False, enable_completion_extraction=False, ...) |
| 关闭自动知识注入 | knowledge=KnowledgeConfig(enable_injection=False, ...) |
原因:
agent:remote agent 在服务器上再派生子 Agent 会污染服务器 trace;调 remote_* 则 HTTP 回调自己enable_injection=True 会在 focus goal 时调 remote_librarian → 服务器自己调自己 → 递归当前实现参考:knowhub/agents/librarian.py::get_librarian_config(显式 tool 列表 + knowledge 全关)、knowhub/agents/research.py::research(tool_groups + exclude_tools + knowledge 全关)。
新增远端 Agent 只需:在 knowhub/agents/ 下写实现 + prompt + 定义 ALLOWED_SKILLS,在 knowhub/server.py::_get_remote_agent_dispatch 的分发表里登记 agent_type。客户端零改动。
端侧 Agent
└── agent 工具(统一入口,按 agent_type 路由)
↓ HTTP
POST /api/agent
→ 服务器按 agent_type 分发到对应 AgentRunner
远端 Agent 不是常驻进程。每次 HTTP 请求触发一次 AgentRunner.run(),状态持久化到服务器本地的 .trace/。
续跑:客户端显式传 continue_from=<sub_trace_id>。服务器不维护 caller → sub_trace 映射,caller 自己记住并回传。
知识上传和查询用同一个 remote_librarian,靠 skills=["upload_strategy"] 切换到上传模式。task 此时是 JSON 字符串 {knowledge, tools, resources}。服务器同步跑完图谱编排后返回——不再是独立的 /api/knowledge/upload 端点。
统一端点 POST /api/agent,详见 api.md § POST /api/agent。
知识查询(Librarian + ask_strategy):
{
"agent_type": "remote_librarian",
"task": "ControlNet 相关的工具知识",
"skills": ["ask_strategy"],
"continue_from": null
}
知识上传(Librarian + upload_strategy;task 用 JSON 字符串承载结构化数据):
{
"agent_type": "remote_librarian",
"task": "{\"knowledge\": [...], \"tools\": [...], \"resources\": [...]}",
"skills": ["upload_strategy"],
"continue_from": null
}
深度调研(remote_research 不接受 skill):
{
"agent_type": "remote_research",
"task": "深度调研 Nano Banana 多图融合",
"continue_from": null
}
所有调用同步返回标准 Agent 结果 {sub_trace_id, status, summary, stats}。summary 是 Agent 最终产出的 message 文本——结构化信息(引用来源、ID 列表等)由 Agent 的 prompt 约定写进文本,由调用方 parse。不定义 per-agent 的强 schema。
知识上传请求会在服务器 .cache/.knowledge/buffer/ 下写一份 buffer 文件(审计用)。处理失败的文件可通过运维端点查询与重跑:
GET /api/knowledge/upload/pending — 列出 pending 或 failed 的 bufferPOST /api/knowledge/upload/retry — 同步重跑所有 failedinject_knowledge_for_goal(agent/trace/goal_tool.py)在 Goal 开始时自动通过 agent_type="remote_librarian" 调用 /api/agent,把返回的 summary 作为 cognition_log 的 query 事件记录(详见 agent/docs/cognition-log-plan.md)。
| 组件 | 位置 |
|---|---|
| Librarian 核心 | knowhub/agents/librarian.py::run_librarian(skill 决定模式;ALLOWED_SKILLS 定义白名单) |
| Research 核心 | knowhub/agents/research.py(research()) |
| Prompt | knowhub/agents/librarian_agent.prompt / research_agent.prompt |
| Server 端点 | knowhub/server.py::agent_api(/api/agent)+ 运维 /api/knowledge/upload/{pending,retry} |
| 客户端入口 | agent/tools/builtin/subagent.py::agent(按 remote_ 前缀路由) |
| SDK / CLI | agent.invoke_agent() (agent/client.py);Claude Code skill 脚本 ~/.claude/skills/agent/invoke.py 透传参数 |
每次 remote_librarian 调用在 Agent 侧产生一个 query 事件,记录查询和整合回答。后续评估以 query 为单位。详见 cognition-log-plan.md。
upload 提交的知识进入处理流水线(去重、工具关联分析)。逻辑在 server.py:KnowledgeProcessor 中。详见 processing-pipeline.md。