Merge branch 'feature/fix_large_results_backend' into dev
This commit is contained in:
commit
66cde77117
@ -1,24 +1,21 @@
|
||||
# Skill 功能
|
||||
|
||||
> 负责范围:技能包管理服务 - 核心实现
|
||||
<<<<<<< Updated upstream
|
||||
> 最后更新:2026-05-23
|
||||
> 最后更新:2026-04-20
|
||||
=======
|
||||
|
||||
> 最后更新:2026-05-20
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
## 当前状态
|
||||
|
||||
Skill 系统支持两种来源:官方 skills (`./skills/`) 和用户 skills (`projects/uploads/{bot_id}/skills/`)。支持 Hook 系统和 MCP 服务器配置,通过 SKILL.md 或 plugin.json 定义元数据。
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
2026-04 起 skill 包可在 `agents/*.md` 下定义子 agent(由 `SubAgentMiddleware` 加载);启用 Daytona 沙箱时 skill 加载路径变为沙箱内的 `/workspace/skills`。
|
||||
|
||||
MCP UI 类 skill 已按 MCP Apps 模式改造:工具返回数据,静态 HTML App 由 host 加载后通过 postMessage 接收数据渲染。
|
||||
|
||||
目前已新增一批**纯 `SKILL.md` 型业务 skill MVP**,用于研究、摘要、报告和情报编排,底层文件处理与外部检索能力继续复用既有 skill。
|
||||
|
||||
>>>>>>> Stashed changes
|
||||
## 核心文件
|
||||
|
||||
- `routes/skill_manager.py` - Skill 上传/删除/列表 API
|
||||
@ -28,10 +25,25 @@ MCP UI 类 skill 已按 MCP Apps 模式改造:工具返回数据,静态 HTML
|
||||
- `routes/mcp_resources.py` - MCP App 静态 HTML resource REST 入口
|
||||
- `skills/` - 官方 skills 目录
|
||||
- `skills_developing/` - 开发中 skills
|
||||
- `agent/subagent_loader.py` - 扫描 skill `agents/*.md` 加载子 agent(2026-05 引入)
|
||||
- `agent/mcp_trace_meta.py` - 对 `ClientSession.call_tool` 做 monkey-patch,向 `rag_retrieve` / `table_rag_retrieve` 的 MCP `_meta` 注入 `trace_id`(2026-05 引入)
|
||||
|
||||
## 最近重要事项
|
||||
|
||||
- [2026-05-12](changelog/2026-Q2.md): 跨 6→10 个 skill 变体批量精修 `retrieval-policy*.md`,统一 onprem/support/autoload 各路径下的 policy 口径(`be96f24`, `7b4f03d`)
|
||||
- [2026-05-11](changelog/2026-Q2.md): 新增子 agent (SubAgent) 支持——skill 包通过 `agents/*.md` 暴露子 agent,由 `SubAgentMiddleware` 加载;附 `pmda-drug-info` skill 示例(`5b634bc`)
|
||||
- [2026-05-11](changelog/2026-Q2.md): `pmda-drug-info` 的 `pmda_server.py` 大改为 mock 实现(`a92096a`)
|
||||
- [2026-05-11](changelog/2026-Q2.md): `retrieval-policy.md` 跨 4 个 skill 变体内容同步更新(`e6d1698`)
|
||||
- [2026-05-08](changelog/2026-Q2.md): 通过 monkey-patch `ClientSession.call_tool`,把 trace_id 透传到 `rag_retrieve` / `table_rag_retrieve` 的 MCP `_meta`(`1f06450`)
|
||||
- [2026-05-06](changelog/2026-Q2.md): support 分支新增 `kfs-answer` skill(`a9227b8`)
|
||||
- [2026-05-06](changelog/2026-Q2.md): 修复 Daytona 沙箱增量同步漏掉符号链接的问题——`find -type f` 不覆盖 symlink、`tar.add` 默认不 dereference 导致悬空软链;并统一 dataset 路径为复数 `datasets/`(`3c0fa49`)
|
||||
- [2026-04-24](changelog/2026-Q2.md): 非流式响应路径上 `_execute_post_agent_hooks` 改为 `asyncio.create_task` 非阻塞执行;同时临时注释停用 `ToolOutputLengthMiddleware`(`45a9494`)
|
||||
- [2026-04-23](changelog/2026-Q2.md): PrePrompt hook 内容改为通过 `{hook_content}` 占位符注入系统提示词模板,不再在 prompt 末尾追加(`51fbf01`)
|
||||
- [2026-04-23](changelog/2026-Q2.md): Daytona 沙箱接入——`init_agent` 并行加载 + 返回元组增加 `sandbox` 字段;`skills_sources` 在沙箱模式下变为 `/workspace/skills`,`agent_dir_path` 变为 `/workspace`(`c9e0789`, `8446dab`)
|
||||
- [2026-04-22](changelog/2026-Q2.md): `skills/developing/` 下新增 `rag-retrieve-no-citation` 与 `novare-context` 两个开发中 skill(`7a30e52`)
|
||||
|
||||
- 2026-05-20: `mcp-ui` 和 `data-dashboard` 改为 MCP Apps 标准模式,App HTML 放在 skill 的 `apps/` 目录,由 host 加载后 postMessage 数据
|
||||
|
||||
- 2026-04-20: 为 `rag-retrieve` 新增 `retrieval-policy-forbidden-self-knowledge.md`,禁止知识问答场景使用模型自身知识补全答案,要求严格基于检索证据作答
|
||||
- 2026-04-19: 环境变量 `SKILLS_SUBDIR` 重命名为 `PROJECT_NAME`,用于选择 `skills/{PROJECT_NAME}` 和 `skills/autoload/{PROJECT_NAME}` 目录
|
||||
- 2026-04-19: `create_robot_project` 的 autoload 去重和 stale 清理补强,autoload 目录也纳入 managed 清理,避免 `rag-retrieve-only` 场景下旧的 `rag-retrieve` 残留
|
||||
@ -41,8 +53,6 @@ MCP UI 类 skill 已按 MCP Apps 模式改造:工具返回数据,静态 HTML
|
||||
|
||||
## Gotchas(开发必读)
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
- ⚠️ MCP App resource REST 读取路径是 `projects/robot/{bot_id}/skills/{server_name}/apps/{resource_name}.html`,前端 bot_id 应由 `ChatView` 从当前 bot 传给 `ChatMessage`,不要在子组件里重新调用 `useBotManager()`
|
||||
- ⚠️ `langchain-mcp-adapters` 会丢失 `EmbeddedResource` 的 uri/_meta;MCP App payload 需作为 text JSON 传递给前端识别
|
||||
|
||||
@ -60,6 +70,13 @@ MCP UI 类 skill 已按 MCP Apps 模式改造:工具返回数据,静态 HTML
|
||||
- ⚠️ 上传大小限制:50MB(ZIP),解压后最大 500MB
|
||||
- ⚠️ 压缩比例检查:最大 100:1(防止 zip 炸弹)
|
||||
- ⚠️ 符号链接检查:禁止解压包含符号链接的文件
|
||||
- ⚠️ **子 agent 同名静默 last-wins**:`subagent_loader._parse_agent_md` 跨 skill 扫描 `agents/*.md` 时,按 `name` 字段去重,**后扫描到的覆盖先扫描的**,只打 warning 不报错。多 skill 都暴露子 agent 时需自觉错开命名。
|
||||
- ⚠️ **`SubAgentMiddleware` 中间件顺序**:必须插在 `CustomFilesystemMiddleware` 之后、`AnthropicPromptCachingMiddleware` 之前——这是匹配 `deepagents.create_deep_agent` 的官方顺序,调整 `create_custom_cli_agent` 中的中间件顺序时不能随意挪动这一段。
|
||||
- ⚠️ **Daytona 模式下 skill 路径不同**:`DAYTONA_ENABLED=true` 时 `enable_skills` 的 `skills_sources` 是 `/workspace/skills`(沙箱内),同时 system prompt 的 `agent_dir_path` 是 `/workspace`;写死本地路径的 hook / 脚本需要兼容两种环境。
|
||||
- ⚠️ **PostAgent hook 非流式分支已 fire-and-forget**:`routes/chat.py` 用 `asyncio.create_task` 启动 hook,调用方不会等待也不会感知到 hook 的异常——hook 失败只会被自己的 logger 捕获。
|
||||
- ⚠️ **MCP `_meta.trace_id` 是全局 monkey-patch 注入**:`agent/mcp_trace_meta.patch_mcp_client_session_trace_meta()` 在 `get_tools_from_mcp()` 入口调用一次后,会把 `mcp.ClientSession.call_tool` 永久包装;仅对工具名在 `{"rag_retrieve", "table_rag_retrieve"}` 集合内的调用注入 `_meta.trace_id`,扩展白名单要直接改 `_TRACE_META_TOOL_NAMES` 常量。
|
||||
- ⚠️ **PrePrompt hook 内容位置由模板决定**:自 2026-04-23 起 hook 产出通过 `{hook_content}` 占位符注入 `prompt/system_prompt.md`,不再追加在 prompt 末尾;自定义模板必须包含 `{hook_content}` 占位符否则 hook 内容会丢失。
|
||||
- ⚠️ **`init_agent` 返回值已变 3 元素**:Daytona 改造后 `init_agent` 返回 `(agent, checkpointer, sandbox)`;调用方解构必须更新。
|
||||
|
||||
## Skill 目录结构
|
||||
|
||||
|
||||
@ -1,5 +1,272 @@
|
||||
# 2026-Q2 Skill Changelog
|
||||
|
||||
按时间倒序记录本季度的重要变更。
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-12: 批量精修 retrieval policy 文案
|
||||
|
||||
**类型**:内容调整
|
||||
|
||||
**背景**:[待补充]
|
||||
|
||||
**改动**:
|
||||
- `be96f24`: 跨 6 个 skill 变体调整 `retrieval-policy-forbidden-self-knowledge.md` 的措辞(onprem / support / autoload-onprem / autoload-onprem-rag-only / autoload-support-rag-only 路径下的版本及一份 `retrieval-policy.md`)。
|
||||
- `7b4f03d`: 在更广的 10 个文件范围内同步更新 `retrieval-policy.md` 与 `retrieval-policy-forbidden-self-knowledge.md` 两套 policy,使各 skill 变体的策略口径保持一致。
|
||||
|
||||
**根因**:N/A(非 Bug)
|
||||
|
||||
**影响**:所有使用 `rag-retrieve` / `rag-retrieve-only` 这两个 hook 的 skill 在策略行为上保持一致;同时影响 onprem 与 support 两个发布分支的部署。
|
||||
|
||||
**相关文件**:
|
||||
- `skills/onprem/rag-retrieve/hooks/retrieval-policy*.md`
|
||||
- `skills/support/rag-retrieve/hooks/retrieval-policy*.md`
|
||||
- `skills/autoload/onprem/rag-retrieve/hooks/retrieval-policy*.md`
|
||||
- `skills/autoload/onprem/rag-retrieve-only/hooks/retrieval-policy*.md`
|
||||
- `skills/autoload/support/rag-retrieve-only/hooks/retrieval-policy*.md`
|
||||
|
||||
**Commit/PR**:`be96f24`, `7b4f03d`
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-11: 子 agent (SubAgent) 支持 + pmda-drug-info skill
|
||||
|
||||
**类型**:新功能
|
||||
|
||||
**背景**:需要让单个 skill 在主 agent 之外承载多个专用子 agent,按用途隔离上下文与工具集(如 pmda 药品信息场景下的 single-drug / interaction / adverse-event / patient-specific 四个专用 agent)。
|
||||
|
||||
**改动**:
|
||||
- 新增 `agent/subagent_loader.py`:扫描 skill 目录下的 `agents/*.md`,按 YAML frontmatter 的 `name` / `description` / `tools` 字段解析为 `SubAgent` 字典;按 `name` 去重,**后扫描的覆盖先扫描的**(last-wins)。
|
||||
- `agent/deep_assistant.py`:`init_agent` 调用 `load_subagents()`,存在则将 `SubAgentMiddleware`(来自 `deepagents.middleware.subagents`)插在 `CustomFilesystemMiddleware` 之后、`AnthropicPromptCachingMiddleware` 之前,顺序匹配 `create_deep_agent`。
|
||||
- 新增 `skills/developing/pmda-drug-info/`:完整 skill 包,包含 `.claude-plugin/plugin.json`、`hooks/pre_prompt.py` + `hooks/pmda-instructions.md`、四个 `agents/*.md`、自带 `pmda_server.py` MCP server + `pmda_tools.json`、`mcp_common.py` 工具基础类。
|
||||
|
||||
**根因**:N/A
|
||||
|
||||
**影响**:
|
||||
- skill 包结构新增约定:`agents/*.md` 目录下的 markdown 文件会被加载为子 agent。
|
||||
- skill 加载流程在 `init_agent` 内增加一次目录扫描;对没有 `agents/` 的 skill 无影响。
|
||||
- skill 跨 bot 共享时存在 sub-agent 同名冲突的风险——同名 sub-agent 不会报错,而是被后扫描到的覆盖。
|
||||
|
||||
**相关文件**:
|
||||
- `agent/subagent_loader.py`(新)
|
||||
- `agent/deep_assistant.py`(接线)
|
||||
- `skills/developing/pmda-drug-info/`(新 skill)
|
||||
|
||||
**Commit/PR**:`5b634bc`
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-11: pmda-drug-info MCP server 重写为 mock 实现
|
||||
|
||||
**类型**:内部改造
|
||||
|
||||
**背景**:[待补充]
|
||||
|
||||
**改动**:`skills/developing/pmda-drug-info/pmda_server.py` 大幅替换(+322 / -385),保留接口面向 agent 的契约,内部替换为 mock 数据实现。
|
||||
|
||||
**根因**:N/A
|
||||
|
||||
**影响**:pmda-drug-info skill 当前不再依赖外部真实 PMDA 数据源,便于开发期联调。
|
||||
|
||||
**相关文件**:
|
||||
- `skills/developing/pmda-drug-info/pmda_server.py`
|
||||
|
||||
**Commit/PR**:`a92096a`
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-11: retrieval-policy.md 内容更新
|
||||
|
||||
**类型**:内容调整
|
||||
|
||||
**背景**:[待补充]
|
||||
|
||||
**改动**:在 onprem / support / autoload-onprem-rag-only / autoload-support-rag-only 四个版本的 `retrieval-policy.md` 上做了同步内容更新。
|
||||
|
||||
**根因**:N/A
|
||||
|
||||
**影响**:与同月 12 日的 policy 批量精修配套,使 rag-retrieve hook 策略保持一致。
|
||||
|
||||
**相关文件**:
|
||||
- `skills/onprem/rag-retrieve/hooks/retrieval-policy.md`
|
||||
- `skills/support/rag-retrieve/hooks/retrieval-policy.md`
|
||||
- `skills/autoload/onprem/rag-retrieve-only/hooks/retrieval-policy.md`
|
||||
- `skills/autoload/support/rag-retrieve-only/hooks/retrieval-policy.md`
|
||||
|
||||
**Commit/PR**:`e6d1698`
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-08: 通过 MCP `_meta` 透传 trace_id 给 RAG 工具
|
||||
|
||||
**类型**:新功能
|
||||
|
||||
**背景**:需要把 catalog-agent 的 trace_id 透传给 MCP 端的 `rag_retrieve` / `table_rag_retrieve` 服务,便于跨进程追踪。
|
||||
|
||||
**改动**:
|
||||
- 新增 `agent/mcp_trace_meta.py`:通过 `patch_mcp_client_session_trace_meta()` 对 `mcp.ClientSession.call_tool` 做一次幂等 monkey-patch,调用时若工具名在 `{"rag_retrieve", "table_rag_retrieve"}` 集合内且当前请求上下文有 `trace_id`,则注入到 `kwargs["meta"]["trace_id"]`;并提供 `_call_tool_with_meta_compat` 以兼容旧版 MCP SDK(不接受 `meta=` 关键字时退化为手动构造 `CallToolRequestParams._meta`)。
|
||||
- `agent/deep_assistant.py`:在 `get_tools_from_mcp()` 入口处调用一次补丁安装。
|
||||
- 同步调整 `skills/onprem/rag-retrieve/rag_retrieve_server.py` 与 `skills/support/rag-retrieve/rag_retrieve_server.py`,接收并使用 `_meta.trace_id`。
|
||||
|
||||
**根因**:N/A
|
||||
|
||||
**影响**:
|
||||
- `rag_retrieve` / `table_rag_retrieve` 现在在 MCP `_meta` 上必带 `trace_id`(若上下文存在)。
|
||||
- 全局 monkey-patch 风格 - 只要 `get_tools_from_mcp()` 被调用过一次后,所有 `ClientSession.call_tool` 都会被包装。
|
||||
|
||||
**相关文件**:
|
||||
- `agent/mcp_trace_meta.py`(新)
|
||||
- `agent/deep_assistant.py`
|
||||
- `skills/onprem/rag-retrieve/rag_retrieve_server.py`
|
||||
- `skills/support/rag-retrieve/rag_retrieve_server.py`
|
||||
|
||||
**Commit/PR**:`1f06450`
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-06: 新增 kfs-answer skill (support 分支)
|
||||
|
||||
**类型**:新功能
|
||||
|
||||
**背景**:[待补充] - 为 support 分支补齐 kfs-answer 能力(onprem 分支此前已有同名 skill)。
|
||||
|
||||
**改动**:新增 `skills/support/kfs-answer/`,包括 `SKILL.md` 与 `scripts/` 下的 `query.py` / `search.py` / `detail.py` / `query_db.py` / `format_answer.py` / `merge_citations.py` / `_session.py` 共 7 个脚本(约 1809 行)。
|
||||
|
||||
**根因**:N/A
|
||||
|
||||
**影响**:support 部署版本获得 kfs-answer 能力。
|
||||
|
||||
**相关文件**:
|
||||
- `skills/support/kfs-answer/**`
|
||||
|
||||
**Commit/PR**:`a9227b8`
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-06: Daytona 沙箱增量同步漏掉符号链接
|
||||
|
||||
**类型**:Bug 修复
|
||||
|
||||
**背景**:dataset 通过符号链接挂载,但增量同步用 `find -type f` 只匹配普通文件,导致 dataset 符号链接没被检测到也没被打包同步到 Daytona 沙箱;并且 `tar.add()` 默认不 dereference,打进去的是指向宿主机路径的悬空软链。
|
||||
|
||||
**改动**:
|
||||
- `utils/daytona_sync._list_local_changed_files`:同时匹配 file 和 symlink (`-type f -o -type l`)。
|
||||
- `utils/daytona_sync._tar_workspace_entries`:`tar.add(dereference=True)`,把软链解引用为实际内容打包。
|
||||
- `skills/onprem/kfs-answer/SKILL.md` 和 `prompt/system_prompt_deep_agent.md`:统一数据集路径用复数形式 `datasets/`。
|
||||
|
||||
**根因**:`find -type f` 与 `tar.add()` 默认行为对符号链接不友好。
|
||||
|
||||
**影响**:Daytona 模式下 kfs-answer 等依赖 dataset 软链的 skill 可以正常使用沙箱内的数据;提示词与 SKILL.md 内的路径口径统一。
|
||||
|
||||
**相关文件**:
|
||||
- `utils/daytona_sync.py`
|
||||
- `skills/onprem/kfs-answer/SKILL.md`
|
||||
- `prompt/system_prompt_deep_agent.md`
|
||||
|
||||
**Commit/PR**:`3c0fa49`
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-24: PostAgent hooks 非阻塞执行 + 临时停用 ToolOutputLengthMiddleware
|
||||
|
||||
**类型**:性能优化 / 临时调整
|
||||
|
||||
**背景**:非流式响应路径上 `_execute_post_agent_hooks` 是同步等待,阻塞了响应返回。
|
||||
|
||||
**改动**:
|
||||
- `routes/chat.py`:非流式分支将 `await _execute_post_agent_hooks(...)` 改为 `asyncio.create_task(_execute_post_agent_hooks(...))`,hook 在后台执行,不阻塞响应。
|
||||
- `agent/deep_assistant.py`:将 `ToolOutputLengthMiddleware` 整段注释掉(未删除,可恢复)。
|
||||
- `utils/settings.py`:切换 `DAYTONA_API_KEY` / `DAYTONA_SERVER_URL` 注释行(启用自托管 Daytona,注释掉 SaaS 行)。
|
||||
|
||||
**根因**:N/A(性能优化为主)
|
||||
|
||||
**影响**:
|
||||
- 非流式接口响应不再等待 PostAgent hooks 完成 → hook 中失败/异常**只会被 task 内部的 logger 捕获**,调用方收不到错误反馈。
|
||||
- 工具输出长度暂时不再被截断,存在超长输出冲爆上下文的风险(中间件已被注释,并未拆除)。
|
||||
|
||||
**相关文件**:
|
||||
- `routes/chat.py`
|
||||
- `agent/deep_assistant.py`
|
||||
- `utils/settings.py`
|
||||
|
||||
**Commit/PR**:`45a9494`
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-23: PrePrompt hook 内容改为模板占位符注入
|
||||
|
||||
**类型**:重构
|
||||
|
||||
**背景**:原先 PrePrompt hook 的产出文本是在 `system_prompt_default.format(...)` 之后追加在 prompt 末尾,hook 内容在 prompt 中的位置固定且偏后,模板对它的可见性差。
|
||||
|
||||
**改动**:`agent/prompt_loader.load_system_prompt_async`:先执行 `execute_hooks('PrePrompt', config)` 拿到 `hook_content`,然后通过新增的 `{hook_content}` 占位符传入 `system_prompt_default.format(...)`;模板侧 `prompt/system_prompt.md` 增加对应占位符。
|
||||
|
||||
**根因**:N/A(结构化注入更可控)
|
||||
|
||||
**影响**:编写 PrePrompt hook 的 skill 必须依赖模板里 `{hook_content}` 占位符的位置;若使用了未升级的旧模板,hook 内容将不再出现在最终 system prompt 中。
|
||||
|
||||
**相关文件**:
|
||||
- `agent/prompt_loader.py`
|
||||
- `prompt/system_prompt.md`
|
||||
|
||||
**Commit/PR**:`51fbf01`
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-23: Daytona 沙箱接入
|
||||
|
||||
**类型**:新功能
|
||||
|
||||
**背景**:技能脚本需要在隔离沙箱中执行(Daytona),避免直接污染宿主机。
|
||||
|
||||
**改动**:
|
||||
- `agent/deep_assistant.py`:
|
||||
- 在 `init_agent` 中读取 `DAYTONA_ENABLED` / `DAYTONA_API_KEY` / `DAYTONA_SERVER_URL`,启用时创建 `DaytonaSandbox`;并将 `sandbox` / `sandbox_type` 传到 `create_custom_cli_agent` / `agent.invoke_config`。
|
||||
- 重构为并行加载:`load_system_prompt_async` 与 `load_mcp_settings_async` 用 `asyncio.gather` 并行;`get_tools_from_mcp` 与 `asyncio.to_thread(init_daytona_sandbox, ...)` 并行;`init_agent` 现在返回 `(agent, checkpointer, sandbox)`(多了 sandbox)。
|
||||
- `enable_skills` 时 `skills_sources` 从 `"/skills"` 改为 `"/workspace/skills"`(指向沙箱内的路径)。
|
||||
- `agent/prompt_loader.py`:`agent_dir_path` 在 `DAYTONA_ENABLED=True` 时改为 `/workspace`,否则保持本地路径。
|
||||
- `utils/daytona_sync.py` 新增(204 行):沙箱与本地 workspace 双向同步。
|
||||
- `pyproject.toml` / `poetry.lock` / `requirements.txt`:新增 `daytona`、`langchain_daytona` 依赖。
|
||||
- `utils/settings.py`:新增 `DAYTONA_API_KEY` / `DAYTONA_SERVER_URL` / `DAYTONA_ENABLED` 配置。
|
||||
|
||||
**根因**:N/A
|
||||
|
||||
**影响**:
|
||||
- `init_agent` 返回元组从 2 元素变为 3 元素 (`agent, checkpointer, sandbox`)——**调用方必须同步更新解构**。
|
||||
- skill 在沙箱模式下的根路径与本地模式不同,所有写死路径的 hook / 脚本需要兼容两种环境。
|
||||
|
||||
**相关文件**:
|
||||
- `agent/deep_assistant.py`
|
||||
- `agent/prompt_loader.py`
|
||||
- `utils/daytona_sync.py`(新)
|
||||
- `utils/settings.py`
|
||||
- `pyproject.toml`, `poetry.lock`, `requirements.txt`
|
||||
|
||||
**Commit/PR**:`c9e0789`, `8446dab`
|
||||
|
||||
---
|
||||
|
||||
## 2026-04-22: 新增 rag-retrieve-no-citation 与 novare-context 两个开发中 skill
|
||||
|
||||
**类型**:新功能
|
||||
|
||||
**背景**:[待补充]
|
||||
|
||||
**改动**:
|
||||
- `skills/developing/rag-retrieve-no-citation/`:完整 skill 包,含 `.claude-plugin/plugin.json`、`README.md`、`hooks/pre_prompt.py`、`hooks/retrieval-policy.md` 与 `hooks/retrieval-policy-forbidden-self-knowledge.md`、独立 `rag_retrieve_server.py` + `rag_retrieve_tools.json` + `mcp_common.py`。
|
||||
- `skills/developing/novare-context/`:包含 `.claude-plugin/plugin.json`、`README.md`、`hooks/pre_prompt.py`。
|
||||
|
||||
**根因**:N/A
|
||||
|
||||
**影响**:开发中 skill 集合扩张,可作为后续正式版本的母版。
|
||||
|
||||
**相关文件**:
|
||||
- `skills/developing/rag-retrieve-no-citation/**`
|
||||
- `skills/developing/novare-context/**`
|
||||
|
||||
**Commit/PR**:`7a30e52`
|
||||
|
||||
---
|
||||
### 2026-05-20
|
||||
- **变更**: `mcp-ui` 和 `data-dashboard` 从自定义 `uri + data` 工具协议改为 MCP Apps 模式
|
||||
- **说明**: 静态 HTML App 放在各 skill 的 `apps/` 目录,host 通过 resource URI 加载 iframe,再用 postMessage 传递工具数据
|
||||
|
||||
47
.features/skill/decisions/2026-05-subagent-support.md
Normal file
47
.features/skill/decisions/2026-05-subagent-support.md
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
date: "2026-05-11"
|
||||
status: pending
|
||||
topic: "subagent-support"
|
||||
impact: [skill, agent, deep_assistant]
|
||||
---
|
||||
|
||||
# Sub-Agent 在 skill 内的承载方式
|
||||
|
||||
## 背景
|
||||
|
||||
业务方 (pmda-drug-info) 需要在单个 skill 内同时承载若干面向不同子任务的专用 agent
|
||||
(single-drug / interaction / adverse-event / patient-specific),每个子 agent
|
||||
需要独立的 system prompt 和工具白名单,但应与主 agent 复用同一组 MCP 工具实例
|
||||
与同一份 LLM。
|
||||
|
||||
[待补充]:是否考虑过用 skill-per-subagent 的方式(每个子 agent 一个独立 skill)。
|
||||
|
||||
## 选项
|
||||
|
||||
### 选项 A:skill 内 `agents/*.md` + 全局 `SubAgentMiddleware`(已实现)
|
||||
- 优点:
|
||||
- skill 包自洽,子 agent 定义与 hook / MCP 同包发布。
|
||||
- 复用 `deepagents.middleware.subagents.SubAgentMiddleware`,无需自研路由层。
|
||||
- 工具按 `tools` 字段白名单过滤,统一以 MCP tool name 引用。
|
||||
- 缺点:
|
||||
- 跨 skill 子 agent **同名时静默 last-wins 覆盖**,仅有 warning,无强校验。
|
||||
- 中间件位置耦合:`SubAgentMiddleware` 必须插在
|
||||
`CustomFilesystemMiddleware` 之后、`AnthropicPromptCachingMiddleware` 之前
|
||||
(与 `create_deep_agent` 顺序匹配),改动中间件顺序时容易踩坑。
|
||||
|
||||
### 选项 B:每个子 agent 单独建一个 skill
|
||||
- 优点:天然隔离,命名冲突由 skill 加载层处理。
|
||||
- 缺点:同一业务的多个子 agent 在 skill 列表里散落,部署 / autoload 配置复杂;
|
||||
pmda-drug-info 的 4 个子 agent 强相关,作为同一 skill 更自然。
|
||||
|
||||
## 决策
|
||||
|
||||
选择 **选项 A**(已落地)。
|
||||
|
||||
## 影响
|
||||
|
||||
- 需要改动:调用方知道 `init_agent` 返回元组现已包含 sandbox(与 daytona 改动叠加)。
|
||||
- 风险:sub-agent 同名静默覆盖;未来如多 skill 都暴露 sub-agent,需要增加冲突检测。
|
||||
- 后续任务:
|
||||
1. 沉淀 sub-agent 编写规范(`agents/*.md` frontmatter 字段 + 工具白名单约定)。
|
||||
2. 跨 skill sub-agent 命名冲突的检测策略——是否升级为 error / 加 skill 名前缀。
|
||||
@ -480,13 +480,19 @@ def create_custom_cli_agent(
|
||||
backend = FilesystemBackend(root_dir=workspace_root, virtual_mode=False)
|
||||
|
||||
# Set up composite backend with routing based on the new implementation
|
||||
# NOTE: virtual_mode=True anchors all paths to root_dir. This is required for
|
||||
# these offload-only backends: CompositeBackend strips the route prefix and
|
||||
# forwards "/" to grep, so virtual_mode=False would resolve "/" to the real
|
||||
# filesystem root and scan the whole disk (hitting /usr, /var, other sessions'
|
||||
# temp dirs), causing 45-152s grep calls. virtual_mode=True confines grep to
|
||||
# the temp dir and filters out-of-root results.
|
||||
large_results_backend = FilesystemBackend(
|
||||
root_dir=tempfile.mkdtemp(prefix="deepagents_large_results_"),
|
||||
virtual_mode=False,
|
||||
virtual_mode=True,
|
||||
)
|
||||
conversation_history_backend = FilesystemBackend(
|
||||
root_dir=tempfile.mkdtemp(prefix="deepagents_conversation_history_"),
|
||||
virtual_mode=False,
|
||||
virtual_mode=True,
|
||||
)
|
||||
composite_backend = CompositeBackend(
|
||||
default=backend,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user