Files
social-app/.trellis/tasks/04-20-refactor-tool-cli-skill-ui-schema/prd.md
T

31 KiB
Raw Blame History

AgentScope Skill + CLI Tool Protocol Refactor PRD

1. Goal

本次重构的目标不是发明一套新的 agent 工具体系,而是把当前项目的工具执行、skill 使用、UI 生成这三条链路收敛到一条一致的协议路径上:

  1. 以 AgentScope 原生 toolsskills 能力为基础。
  2. 将当前项目工具包装为符合 AgentScope 工具协议的 CLI 工具。
  3. skill 不负责执行工具,而是负责向 agent 渐进式披露"有哪些能力、什么时候用、怎么用"。
  4. CLI 工具的 runtime 认证边界以用户登录 token 为主,默认通过受控环境变量注入,而不是直接注入数据库 session / owner_id。
  5. worker agent output 不再输出 ui_hints
  6. tool output 继续保留独立结构化协议对象,并可携带 ui_hints 给前端渲染使用。
  7. worker 在 ReAct loop 中消费的工具信息应收敛为 tool message content,而不是完整 ToolAgentOutput 元数据对象。
  8. message.content 继续保持文本投影,不升级为通用 schema 字段;结构化结果进入 ToolAgentOutput.result
  9. ToolResponse 只返回 result 文本投影;再由 tool 后处理器把 result 解析/补全为完整 ToolAgentOutput,包括 ui_hints 等字段。

本次改造的核心收益:

  • 减少 worker 输出 token 成本
  • 消除 UI 在 worker / backend compiler / frontend renderer 三处漂移
  • 让工具边界对 AgentScope、skill、前端渲染都更稳定

2. Corrected Design Principles

以下原则是本 PRD 的前提,必须严格遵守:

  1. AgentScope 原生支持 skills
    • 官方 README 明确列出 built-in support for tools, skills
    • 官方示例提供 toolkit.register_agent_skill(...)
  2. skill 是给 agent 的能力说明与工作流知识,不是业务执行 transport。
  3. 如果工具改成 CLICLI 仍然必须服从 AgentScope 的工具协议,而不是项目自己随意定义。
  4. preset/runtime 参数应该以认证凭证为边界,当前项目应使用 Bearer token,并默认通过受控环境变量注入 CLI 执行环境,而不是把 DB session 直接暴露给工具调用接口。
  5. worker output 和 tool output 的协议职责必须分离,不能混成同一套字段语义。
  6. 协议文档先行,docs/protocols/** 仍是项目单一协议真源。
  7. 本项目的"CLI"是受限命令行工具,不是通用 bash/shell 执行能力。

3. Confirmed External Facts

3.1 AgentScope 对 Skills 的官方支持

已确认的外部事实:

  • AgentScope 官方 README 明确写有 built-in support for skills
  • 官方示例 examples/functionality/agent_skill/main.py 使用:
    • toolkit.register_agent_skill(...)
  • 官方示例同时说明:
    • 使用 agent skill 时,agent 需要具备查看文本文件等基础工具能力
    • skill 目录通过 SKILL.md 进行渐进式披露

已确认的 skill 示例结构:

  • SKILL.md 包含 frontmatternamedescription
  • skill 内容描述:
    • 适用场景
    • 推荐工作流
    • 需要执行的脚本/命令
    • 何时读取补充材料

结论:本项目不应绕开 AgentScope skill 能力自行设计一套"伪 skill"机制。

3.2 AgentScope 工具协议的确认边界

已确认的 AgentScope 工具使用方式:

  • Toolkit.register_tool_function(...) 注册 callable function
  • tool 返回 ToolResponse
  • ToolResponse.content 可承载 TextBlock
  • toolkit 支持 preset_kwargs

这意味着如果本项目改成 CLI 路径,落点应是:

  • 对 agent 来说,固定暴露为单一 AgentScope toolproject_cli
  • 对 tool 的内部实现来说,它可以调用 CLI
  • CLI 的输入输出要能被稳定转换为 AgentScope ToolResponse

4. Confirmed Repository Facts

4.1 当前工具执行方式

当前项目仍然是 Python 函数直接注册多个工具:

  • backend/src/core/agentscope/tools/toolkit.py
    • TOOL_FUNCTIONS 直接绑定:
      • calendar_read
      • calendar_write
      • calendar_share
      • user_lookup
      • memory_write
      • memory_forget
    • build_toolkit() 通过 toolkit.register_tool_function(...) 注册这些函数
  • backend/src/core/agentscope/tools/tool_config.py
    • 现统一使用 enabled_skillscalendar|contacts|memory)做能力白名单
  • backend/src/core/agentscope/runtime/runner.py
    • _build_toolkit() 根据 enabled_skills 选择技能白名单

结论:当前实现尚未接入 AgentScope skill,也尚未接入 CLI 工具边界。

4.2 当前项目中的认证边界

当前项目已有明确的 Bearer token 用户解析路径:

  • backend/src/v1/users/dependencies.py
    • get_current_user()Authorization: Bearer <token> 解析 token
    • 先走 JWT verifier,再 fallback 到 Supabase user lookup
    • 最终产出 CurrentUser
  • backend/src/core/auth/models.py
    • CurrentUser 当前字段:idphonerole

结论:如果工具改为 CLI,runtime 的合理边界应是 token 或 auth credential,而不是 DB session / owner_id。token 默认通过受控环境变量注入 CLI 运行环境,CLI 内部再根据 token 推导用户身份和数据访问上下文。

补充约束:

  • 不能仅凭 owner_id 直接构造用户 Bearer tokenowner_id 不是签名凭证。
  • automation 场景由当前 Bearer token 的签发方负责基于 automation_jobs.owner_id 签发短期受控凭证;若现有签发链路不支持,则补一个服务端签发函数。
  • 当前假设该签发方与用户登录 Bearer token 的签发体系一致;现有若仅支持"邮箱 + 验证码"登录签发,则在同一信任边界下新增 automation 凭证签发能力。
  • automation 受控凭证生命周期目标为 5-10 分钟,只覆盖 agent 调用工具所需窗口。
  • 该凭证的签发方式、有效期、权限边界和审计规则必须在协议文档中写清。

4.3 当前 worker output 与 UI 路径

当前 worker output 仍然包含 UI 描述:

  • backend/src/schemas/agent/runtime_models.py
    • WorkerAgentOutputRich.ui_hints

当前 runtime 会把 ui_hints 带入最终文本事件:

  • backend/src/core/agentscope/runtime/stage_emitter.py
    • emit_final_text_end()ui_hints 写入 payload

当前对外 AG-UI payload 会把 ui_hints 编译为 ui_schema

  • backend/src/core/agentscope/events/agui_codec.py
    • TEXT_MESSAGE_END 上执行 compile_ui_hints(...)

当前 history 回放同样依赖 ui_hints -> ui_schema

  • backend/src/v1/agent/utils.py
  • backend/src/v1/agent/schemas.py

结论:当前 ui_schema 的真源是 worker 自身输出的 ui_hints。本次改造将把 ui_hints 的来源从 worker output 改为 tool outputui_hints → ui_schema 的编译链路保持不变。

4.4 当前前端消费方式

前端当前消费的是后端下发的编译后 ui_schema

  • apps/lib/core/chat/ag_ui_event.dart
  • apps/lib/core/chat/chat_history_repository.dart
  • apps/lib/shared/widgets/ui_schema/ui_schema_renderer.dart
  • apps/lib/features/home/presentation/widgets/home_chat_item_renderer.dart

结论:前端目前理解的是后端已编译好的 ui_schema。本次改造目标不是改变前端消费方式,而是改变 ui_hints 的来源(从 worker 改为 tool),ui_hints → ui_schema 编译链路保持不变。

4.5 当前 tool result 结构

当前 tool result 已经走 machine-oriented 路线,但结构还不完整:

  • backend/src/core/agentscope/tools/utils/tool_response_builder.py
    • tool 最终返回 ToolResponse
    • 当前 ToolResponse 中仍混入完整 tool 结构,不符合目标边界
  • backend/src/core/agentscope/utils/parsing.py
    • 从 ToolResponse text block 中恢复 ToolAgentOutput
  • backend/src/core/agentscope/runtime/stage_emitter.py
    • TOOL_CALL_RESULT payload 包含 tool_nametool_call_argsstatusresult

当前仓库已经存在"给 agent 的文本内容"和"给事件/持久化的完整结构化对象"分离的模式:

  • backend/src/core/agentscope/events/store.py
    • tool 消息持久化时:content = tool_output.result
    • 完整结构化对象进入 metadata.tool_agent_output
  • backend/tests/unit/core/agentscope/events/test_store.py
    • 明确校验 tool message content 等于文本结果
    • 同时完整 tool_agent_output 保存在 metadata 中

结论:当前仓库已经证明一个正确的职责分层:

  • worker/上下文消费的应是 tool message content
  • AG-UI 事件、持久化和前端渲染可以保留完整 ToolAgentOutput

但当前仍有三个缺口:

  • ToolAgentOutput 还没有承载前端所需 ui_hints
  • ToolAgentOutput.result 仍是字符串,还没有升级为结构化对象字段
  • ToolResponse 还没有收敛为只承载 result 文本投影,再交给 tool 后处理器生成完整 ToolAgentOutput

此外,history/replay 的正确恢复方向也已经比较明确:

  • 可以像 worker output 一样,从 message.metadata 中恢复结构化对象
  • 对 tool 来说,恢复源应是 metadata.tool_agent_output.ui_hints

5. Problem Statement

当前实现存在 5 个核心问题:

  1. 工具实现直接耦合在 Python runtime 函数注册层,缺少独立协议边界。
  2. skill 尚未成为 agent 的原生能力入口,工具知识仍主要依赖 prompt 和函数 docstring。
  3. worker 仍承担 UI 描述职责,导致 ui_hints 占 token,且与前后端实现容易漂移。
  4. tool result 已经拥有独立结构化对象,但没有成为 UI 渲染主路径。
  5. 当前 tool output 协议没有明确区分"给 worker 推理的 content"和"给前端渲染的完整结构化输出"。
  6. 当前 CLI 工具边界尚未定义为受限命令行工具,容易和通用 shell 执行概念混淆。

6. Target Architecture

6.1 总体方向

目标架构应遵循下面的职责分层:

  1. AgentScope skill

    • 负责告诉 agent
      • 有哪些工具能力
      • 什么时候调用
      • 调用前后如何决策
    • 不直接承担业务执行
  2. AgentScope tool

    • agent 固定只看到一个工具入口:project_cli
    • 内部执行方式为结构化 command + subcommand + args -> 调用项目 CLI -> 适配回 ToolResponse
  3. CLI tool

    • 是业务执行边界
    • 输入输出必须稳定、结构化、可验证
    • 采用经典命令树:command + subcommand + args
    • 不按 skill + action 建模 CLI
    • 必须符合 AgentScope 工具协议适配需要
    • 必须是受限项目命令行工具,不提供通用 bash/shell 能力
  4. Tool output protocol

    • 保留独立的 ToolAgentOutput 类协议对象
    • 对 AG-UI 事件、持久化元数据、前端渲染负责
    • 可包含 ui_hints 这类前端渲染字段
  5. UI contract

    • 由 tool output 中的 ui_hints 编译生成 ui_schema
    • ui_schema 成为前端渲染的输入
    • worker output 不再输出 ui_hints

6.2 Token / 受控凭证作为 runtime 注入参数

本项目要求将 Bearer token 或受控服务端凭证作为 tool runtime 注入参数,而不是 DB 级参数。

目标边界:

  • AgentScope tool 被调用时,runtime 将认证 token 或受控服务端凭证注入 CLI 执行环境
  • CLI 接收到 token 后:
    • 验证 token
    • 解析用户身份
    • 推导可访问数据范围
    • 再进入 service / repository / DB 层

禁止继续扩大的错误边界:

  • 不应把 AsyncSession 直接暴露到 CLI 工具调用边界
  • 不应把 owner_id 当作唯一可信的输入
  • 不应让 agent 直接控制数据库上下文对象

当前优先方案:

  • token 不作为模型可见的业务参数字段进入 tool args schema
  • token 由 runtime 以默认环境变量方式注入到 CLI 子进程
  • CLI 只读取受控环境变量,不从自然语言或 tool args 中接受任意 token 字符串
  • automation 不直接伪造用户 Bearer token;由当前 token 签发方基于 automation_jobs.owner_id 获取或签发 5-10 分钟短期受控凭证后注入

6.3 ToolResponse 与 ToolAgentOutput 的边界

本次协议边界明确如下:

  • CLI/Tool 原始执行结果先产出结构化 result
  • AgentScope ToolResponse 只承载给 agent 使用的 result 文本投影
  • 不再把完整 ToolAgentOutput 直接塞进 ToolResponse.content
  • runtime 内增加 tool 后处理器:基于 result 解析/补全完整 ToolAgentOutput
  • 该后处理器负责补齐:
    • tool_name
    • tool_call_id
    • tool_call_args
    • status
    • result
    • error
    • ui_hints

这样职责分层固定为:

  • agent 只看到 message.content / ToolResponse 中的 result 文本投影
  • runtime / SSE / history / persistence 使用完整 ToolAgentOutput

6.4 Worker 与 Tool 输出职责分离

根据当前仓库已存在的运行时与持久化逻辑,本次重构必须明确保持以下分层:

  1. worker output

    • 面向 worker 最终回答
    • 不再包含 ui_hints
  2. tool output

    • 使用 ToolAgentOutput 作为结构化协议对象
    • 面向 AG-UI 事件、历史持久化、前端渲染
    • 可以包含 ui_hints
  3. tool message content

    • 面向 agent ReAct loop 上下文
    • 应是工具结构化结果的稳定文本投影
    • 不应把完整 ToolAgentOutput 字段直接作为下一轮 worker 输入上下文

当前仓库中的支持证据:

  • backend/src/core/agentscope/events/store.py
    • tool message content = tool_output.result
    • metadata 保留完整 tool_agent_output

因此正确方向不是删除 ToolAgentOutput,而是:

  • 保留 ToolAgentOutput 作为独立 tool 协议对象
  • 只让 worker 主要消费 tool message content

6.4 message.content 字段策略

本次不建议把 message.content 从文本改成通用 schema 字段。

原因:

  1. AgentScope/Msg 本身是通用消息抽象,不同 role 的 content 类型已经存在差异,但当前项目的 worker 推理、历史持久化、事件处理都默认把文本内容当作主信息载体。
  2. 当前仓库已经有一条可工作的分层:
  • message.content 给 worker 推理
  • metadata.tool_agent_output 给结构化消费
  1. 若把 message.content 直接升级为 schema,会把:
    • ReAct loop
    • memory/context assembly
    • event store
    • history replay
    • frontend parsing 一起拉进大范围协议改动,收益不成比例。

因此推荐策略是:

  • message.content 继续保持文本
  • 文本内容由 ToolAgentOutput.result 结构化对象稳定投影生成
  • 结构化真源放在 ToolAgentOutput.result

也就是说,后续语义应变成:

  • message.content: 给 worker 的完整 JSON 文本投影
  • ToolAgentOutput.result: 给系统使用的结构化对象真源

6.5 UI 真源迁移方向

本次改造的目标不是"前端直接裸渲染任意 CLI 参数 schema",而是:

  1. 先把 tool output 协议收敛为稳定的结构化 schema
  2. 在 tool output 协议中保留前端所需 ui_hints
  3. 再从该协议导出 AG-UI / history / frontend 统一 contract
  4. AG-UI 传输时:后端 codec 将 ui_hints 编译为 ui_schema 后传输
  5. 前端渲染 ui_schema(复用现有 UiSchemaRenderer

关键设计决策

  • ui_hints 是 tool 输出的描述性 UI 表示(真源)
  • ui_schema 是编译后的渲染性 UI 表示(传输格式)
  • 编译链路 ui_hints → ui_schema 保持不变,仅改变 ui_hints 的来源
  • 前端继续使用现有 UiSchemaRenderer 渲染 ui_schema

因此本次必须避免两个错误方向:

  1. 继续保留 worker -> ui_hints -> ui_schema(应改为 tool -> ui_hints -> ui_schema
  2. 让前端直接绑定 ui_hints 而不是 ui_schema
  3. 把完整 ToolAgentOutput 直接塞回 worker 推理输入,而不是让 worker 主要消费 tool message content
  4. 把"项目 CLI"实现成可执行任意 shell 的通用命令入口

7. Required Refactor Requirements

7.1 Skill 接入要求

必须:

  • 基于 AgentScope 原生 register_agent_skill(...) 接入 skill
  • 提供项目内 skill 目录与 SKILL.md
  • skill 内容必须包含:
    • 工具能力说明
    • 何时调用哪个工具
    • 参数构造规则
    • 组合调用规则
    • 失败后的恢复策略

不允许:

  • 用单纯 prompt 文本替代 skill
  • 自定义一套与 AgentScope skill 不兼容的 skill 机制

7.2 CLI Tool Protocol 要求

CLI 工具必须满足:

  • 能被 AgentScope tool wrapper 稳定调用
  • 输入参数可从当前 AgentScope tool schema 映射得到
  • 输出结果可稳定映射回 ToolResponse
  • 输出至少包含:
    • 状态
    • 结构化结果
    • 错误信息
    • 前端渲染所需的稳定字段

CLI 输出在进入 AgentScope tool wrapper 后,最终需要映射成两层信息:

  1. message.content

    • 给 worker ReAct loop 使用
    • 应为结构化 result 的稳定文本投影
    • 由结构化 result 稳定投影生成
    • 默认保留完整 JSON 文本投影,不做阉割式摘要裁剪
  2. ToolAgentOutput

    • 给 AG-UI 事件、持久化、前端渲染使用
    • 至少包含 tool_nametool_call_idtool_call_argsstatusresulterror
    • 本次应扩展支持 ui_hints

这里的实现约束已经确定:

  • ToolResponse 只返回 result 文本投影
  • 完整 ToolAgentOutput 由 tool 后处理器在 runtime 内生成
  • ui_hints 由 tool 后处理器生成并写入 ToolAgentOutput
  • ui_hints 经后端 codec 编译为 ui_schema 后传输给前端
  • worker 不参与 tool UI 生成

需要显式设计:

  • stdin / argv / env 何者承载输入
  • token 放在哪个输入通道
  • stdout 返回 JSON 的格式
  • 非 0 exit code 的错误语义

当前已确认的输入通道策略:

  • CLI 输入通道采用"两者结合"
  • 默认以 argv 为主、stdin 为辅
  • token 继续通过受控环境变量注入,不进入模型可控参数

7.3 Tool Configuration 保留要求

以下配置能力必须保留:

  • enabled_skills from system agents config
  • enabled_skills from automation jobs config

允许变化的部分:

  • enabled_skills 不再映射到 Python 函数名
  • 改为映射到 CLI-backed tool capability

7.4 Worker Output 精简要求

worker output 必须移除:

  • ui_hints

worker output 保留:

  • status
  • answer
  • suggested_actions
  • error

是否增加新的结构化字段,必须以协议文档先定义为前提;禁止再次引入新的"隐式 UI 描述字段"。

7.5 Tool Output 协议重构要求

ToolAgentOutput 不应被删除,而应被重构为更完整的 tool 协议对象。

至少应满足:

  • 保留当前已有字段:
    • tool_name
    • tool_call_id
    • tool_call_args
    • status
    • result
    • error
  • 扩展支持:
    • ui_hints

其中 result 应升级为结构化对象字段,不再以字符串为真源。

同时需要新增一条投影规则:

  • 从结构化 result 生成稳定文本投影,写入 tool message content
  • 默认使用完整 JSON 投影,保持与 result 信息量一致,避免因摘要裁剪削弱模型对结构化数据的读取能力

同时需要固定 tool 后处理规则:

  • 后处理器以 tool 原始 result 为真源
  • 根据 result 解析/补齐 ToolAgentOutput
  • ui_hints 由后处理器生成并写入 ToolAgentOutput
  • worker 不参与 tool UI 生成

这样可以满足两条不同消费链路:

  • worker 继续消费由 result 投影生成的 message.content
  • AG-UI / history / frontend 消费完整 ToolAgentOutput

7.6 UI Contract 重构要求

必须完成:

  • TEXT_MESSAGE_END 不再依赖 worker ui_hints 编译
  • history assistant message 不再依赖 metadata.agent_output.ui_hints 编译
  • tool result 成为 UI 合约的主要输入之一
  • TOOL_CALL_RESULT / tool metadata / history replay 能保留 tool ui_hints

AG-UI 传递策略调整为:

  • tool 事件内部携带 ui_hints
  • 后端 codec 将 ui_hints 编译为 ui_schema
  • AG-UI 对前端传输 ui_schema
  • 前端继续复用现有 UI 渲染器渲染 ui_schema
  • history 恢复时优先从 message.metadata.tool_agent_output.ui_hints 读取并编译为 ui_schema 后渲染

这里的设计结论已经确定:

  • ui_hints 是 tool 输出的 UI 描述(真源)
  • ui_schema 是编译后的渲染格式(传输格式)
  • 编译链路 ui_hints → ui_schema 保持不变
  • 前端继续使用现有 UiSchemaRenderer 渲染 ui_schema

8. Scope Of Changes

8.1 Protocol Docs

必须更新:

  • docs/protocols/ui/ui-schema.md
  • docs/protocols/ui/data-flow.md
  • docs/protocols/agent/sse-events.md
  • docs/protocols/agent/run-agent-input.md
  • docs/protocols/agent/api-endpoints.md

建议新增:

  • 一个工具协议文档,明确:
    • CLI 输入输出约定
    • token preset 约定
    • tool result 到 UI contract 的映射边界

8.2 Backend

主要改动点:

  • backend/src/core/agentscope/tools/toolkit.py
  • backend/src/core/agentscope/tools/tool_config.py
  • backend/src/core/agentscope/runtime/runner.py
  • backend/src/core/agentscope/runtime/stage_emitter.py
  • backend/src/core/agentscope/events/agui_codec.py
  • backend/src/core/agentscope/events/store.py
  • backend/src/core/agentscope/runtime/tasks.py
  • backend/src/core/agentscope/utils/parsing.py
  • backend/src/schemas/agent/runtime_models.py
  • backend/src/v1/agent/utils.py
  • backend/src/v1/agent/schemas.py
  • 新增 skill 资产与 CLI adapter
  • 新增 Python console entrypoint 与内嵌 command router

skill 资产目录精确落点:

  • backend/src/core/agentscope/tools/custom

skill 部署方式:

  • 参考 AgentScope skill 提供的原生装载/注册方法进入运行时与部署产物
  • 现有 custom/*.py 不再保留为最终工具实现,后续由 CLI handler / router 重写替换

8.3 Cleanup / 收尾清理

本次改造完成后,必须明确收尾清理以下代码与路径,避免旧协议残留:

  1. 删除或下线 worker ui_hints 主路径

    • backend/src/schemas/agent/runtime_models.py 中 worker rich output 的旧定义
    • backend/src/core/agentscope/runtime/stage_emitter.py 中向 TEXT_MESSAGE_END 写入 worker ui_hints 的逻辑
    • backend/src/core/agentscope/events/agui_codec.pyTEXT_MESSAGE_ENDcompile_ui_hints(...) 主路径
    • backend/src/v1/agent/utils.py 中 assistant history 读取 worker ui_hints 并编译的逻辑
  2. 清理旧文档语义

    • docs/protocols/ui/data-flow.md 中"worker ui_hints 是 UI 真源"的描述
    • docs/protocols/ui/ui-schema.md 中把 UI compiler 绑定到 worker ui_hints 的描述
    • docs/protocols/agent/sse-events.md / api-endpoints.md / run-agent-input.md 中与旧 worker UI 路径冲突的描述
  3. 清理测试中的旧假设

    • 依赖 worker ui_hints 的 runtime/event/history 单测
    • 依赖 ToolAgentOutput.result 为字符串真源的测试
  4. 清理旧前端假设

    • 只接受 assistant ui_schema 而不理解 tool ui_schema 的渲染逻辑
    • 历史/事件解析中把 assistant UI 当唯一 UI 来源的路径
  5. 清理旧工具调用边界

    • 继续把 Python runtime 函数当作唯一稳定工具边界的 registry 代码
    • 任何会把 DB session / owner_id 直接注入到 CLI 边界的适配代码
    • custom/*.py 直接工具实现
  6. 清理第二条 runtime 冷路径

    • backend/src/core/agentscope/runtime/tasks.py 中与新 tool output/context rebuild 不一致的旧序列化路径
    • 所有会导致热路径、冷路径看到不同 tool 上下文的兼容逻辑

8.4 Frontend

主要改动点:

  • apps/lib/core/chat/ag_ui_event.dart
  • apps/lib/core/chat/chat_history_repository.dart
  • apps/lib/shared/widgets/ui_schema/ui_schema_renderer.dart(保持不变,继续渲染 ui_schema
  • apps/lib/features/home/presentation/widgets/home_chat_item_renderer.dart

9. Phased Plan

Phase 1. Protocol Correction

先修正文档中的错误前提:

  • 明确 AgentScope skill 是原生能力
  • 明确 CLI 是工具实现载体,不是替代 AgentScope tool/skill
  • 明确 token 环境变量注入边界
  • 明确仅 worker ui_hints 将被移除,tool ui_hints 保留在独立协议中
  • 明确 ui_hints → ui_schema 编译链路保持不变

Phase 2. Skill And Tool Boundary Refactor

  • 接入项目内 skill
  • 定义单一 project_cli AgentScope tool wrapper
  • 使用 Pydantic 化的 enabled_skills 作为唯一配置字段
  • CLI 输入通道采用"两者结合",默认 argv 为主、stdin 为辅
  • 定义 Python console entrypoint 作为外部 CLI 入口
  • 定义内嵌 command router 作为唯一分发核心
  • router 只注册白名单 command + subcommand
  • 每个命令绑定 Python handler
  • handler 只调用允许的内部能力
  • 默认不开放 shell 执行能力
  • 移除旧多工具暴露实现,改为 skills 手册 + 单一 CLI 入口

Phase 3. Auth-Preset Refactor

  • 将 tool preset 从 runtime DB context 改为 auth token / 受控凭证
  • CLI 内部完成身份解析与数据作用域推导
  • token 默认通过受控环境变量进入 CLI,而不是模型可控参数
  • automation 基于 automation_jobs.owner_id 获取或签发受控凭证,不直接伪造用户 Bearer token

Phase 4. UI Source Refactor

  • 删除 worker ui_hints 输出
  • 删除 worker ui_hints -> ui_schema 编译主路径
  • 将 tool ui_hints 纳入 ToolAgentOutput 协议
  • ToolAgentOutput.result 升级为结构化对象
  • 建立 result -> message.content 的稳定完整 JSON 文本投影规则
  • 建立 tool output ui_hints → ui_schema 的编译路径

Phase 4.5 Runtime Path Unification

  • 改造 backend/src/core/agentscope/runtime/tasks.py
  • 确保热路径、冷路径、context rebuild 都使用同一套:
    • ToolAgentOutput.result 结构化对象真源
    • message.content 完整 JSON 文本投影
    • metadata.tool_agent_output 作为历史恢复真源
  • 移除第二条旧路径,避免同一线程在不同路径下看到不同 tool 上下文

Phase 5. Frontend Alignment

  • 调整事件解析和 history 解析,从 TOOL_CALL_RESULT.ui_schema 读取
  • 渲染逻辑保持不变,继续使用 UiSchemaRenderer 渲染 ui_schema

10. Acceptance Criteria

  • PRD 与协议文档不再错误描述 AgentScope skill 能力
  • skill 通过 AgentScope 原生能力接入,而不是自定义伪 skill 机制
  • 单一 project_cli 能通过 AgentScope tool protocol 被稳定调用
  • 工具 runtime 以 Bearer token / 受控服务端凭证为边界
  • token/凭证 默认以受控环境变量注入 CLI 执行环境
  • CLI 能基于 token/凭证 解析用户身份与数据访问范围
  • automation 能基于 owner_id 由当前 token 签发方签发 5-10 分钟受控凭证,但不直接伪造用户 Bearer token
  • enabled_skills 能驱动技能手册和允许命令域配置
  • worker output 不再包含 ui_hints
  • ToolAgentOutput 保留为独立 tool 协议对象,并支持 ui_hints
  • worker 在上下文中主要消费 tool message content/result,而不是完整 ToolAgentOutput
  • message.content 保持文本,不升级为通用 schema 字段
  • ToolAgentOutput.result 升级为结构化对象真源
  • message.content 采用完整 JSON 文本投影,而不是裁剪摘要
  • ToolResponse 只承载 result 文本投影
  • tool 后处理器能基于 result 生成完整 ToolAgentOutput(含 ui_hints
  • TEXT_MESSAGE_END 和 assistant history 不再依赖 worker ui_hints 编译 UI
  • history 能直接从 metadata.tool_agent_output.ui_hints 恢复 tool UI
  • runtime/tasks.py 等冷/热路径已统一,不再存在第二条旧路径
  • 前端继续通过现有 UI 渲染器消费 ui_schema 渲染内容
  • ui_hints → ui_schema 编译链路保持不变,仅改变 ui_hints 来源
  • skill 资产目录已落在 backend/src/core/agentscope/tools/skills
  • skill 部署/装载方式与 AgentScope 原生方法保持一致
  • CLI 输入通道已按 argv 主、stdin 辅的组合模式落地
  • custom/*.py 直接工具实现已被 CLI handler / router 替换

11. Open Questions

当前 open questions 已收口,不再保留架构级未决项。

已确认结论:

  1. ui_hints 是 tool 输出的 UI 描述(真源),ui_schema 是编译后的渲染格式(传输格式)
  2. skill 资产目录最终精确落点为 backend/src/core/agentscope/tools/custom
  3. skill 部署方式参考 AgentScope skill 提供的原生方法
  4. CLI 输入通道采用"两者结合",默认 argv 为主、stdin 为辅
  5. history route 的 tool UI 回放从 metadata.tool_agent_output.ui_hints 读取并编译为 ui_schema
  6. custom/*.py 不再保留,工具实现改为 CLI handler / router
  7. ToolResponse 只返回 result 文本投影,完整 ToolAgentOutput 由 tool 后处理器生成

12. Risks

  1. 如果只把工具换成 CLI,但不先定义稳定工具协议,最终仍会把旧耦合问题原样搬过去。
  2. 如果前端直接消费 ui_hints 而不是 ui_schema,会破坏现有渲染链路。
  3. 如果把"项目 CLI"误实现为通用 shell/命令执行器,会引入提示词注入和越权风险。
  4. 如果 token/凭证 注入边界设计不严谨,容易把认证逻辑散落到多个工具实现中。
  5. 当前代码里仍有多处 broad catch,迁移时错误可能被掩盖:
    • backend/src/core/agentscope/events/agui_codec.py
    • backend/src/v1/agent/utils.py
    • apps/lib/core/chat/ag_ui_service.dart

13. Definition Of Done

当以下条件全部满足时,本任务完成:

  1. 协议文档修正完毕并成为实现依据。
  2. AgentScope skill 已在项目内落地并承担工具使用知识披露。
  3. 当前工具已切换为单一 project_cli + skills 手册架构。
  4. token/受控凭证 已通过受控环境变量成为 CLI runtime 的认证边界。
  5. worker output 已移除 ui_hints
  6. ToolAgentOutput 已成为独立完整的 tool 协议对象,并承载前端所需 UI hints。
  7. ToolAgentOutput.result 已升级为结构化对象真源。
  8. worker 仅通过完整 JSON 文本投影的 tool message content 获取工具结果主信息。
  9. history 能通过 metadata.tool_agent_output.ui_hints 编译为 ui_schema 恢复 tool UI。
  10. runtime/tasks.py 等冷/热路径已统一,不再存在第二条旧路径。
  11. AG-UI 对 tool UI 编译 ui_hints → ui_schema 后传输,前端继续复用现有 UI 渲染器。
  12. 旧 worker UI 编译路径和相关清理项已完成收尾。
  13. 前后端事件/history/渲染链路验证通过。
  14. ui_hints → ui_schema 编译链路保持不变,仅改变 ui_hints 来源。
  15. skill 资产已按约定落在 backend/src/core/agentscope/tools/skills,并按 AgentScope 原生方式装载。
  16. CLI 输入通道已按 argv 主、stdin 辅的组合模式落地。
  17. history route 已从 metadata.tool_agent_output.ui_hints 编译为 ui_schema 回放 tool UI。
  18. custom/*.py 直接工具实现已被 CLI handler / router 替换。
  19. ToolResponse 已收敛为只返回 result 文本投影,完整 ToolAgentOutput 由 tool 后处理器生成。