31 KiB
AgentScope Skill + CLI Tool Protocol Refactor PRD
1. Goal
本次重构的目标不是发明一套新的 agent 工具体系,而是把当前项目的工具执行、skill 使用、UI 生成这三条链路收敛到一条一致的协议路径上:
- 以 AgentScope 原生
tools和skills能力为基础。 - 将当前项目工具包装为符合 AgentScope 工具协议的 CLI 工具。
- skill 不负责执行工具,而是负责向 agent 渐进式披露"有哪些能力、什么时候用、怎么用"。
- CLI 工具的 runtime 认证边界以用户登录 token 为主,默认通过受控环境变量注入,而不是直接注入数据库 session / owner_id。
- worker agent output 不再输出
ui_hints。 - tool output 继续保留独立结构化协议对象,并可携带
ui_hints给前端渲染使用。 - worker 在 ReAct loop 中消费的工具信息应收敛为 tool message
content,而不是完整ToolAgentOutput元数据对象。 message.content继续保持文本投影,不升级为通用 schema 字段;结构化结果进入ToolAgentOutput.result。ToolResponse只返回result文本投影;再由 tool 后处理器把result解析/补全为完整ToolAgentOutput,包括ui_hints等字段。
本次改造的核心收益:
- 减少 worker 输出 token 成本
- 消除 UI 在 worker / backend compiler / frontend renderer 三处漂移
- 让工具边界对 AgentScope、skill、前端渲染都更稳定
2. Corrected Design Principles
以下原则是本 PRD 的前提,必须严格遵守:
- AgentScope 原生支持
skills。- 官方 README 明确列出 built-in support for
tools, skills - 官方示例提供
toolkit.register_agent_skill(...)
- 官方 README 明确列出 built-in support for
- skill 是给 agent 的能力说明与工作流知识,不是业务执行 transport。
- 如果工具改成 CLI,CLI 仍然必须服从 AgentScope 的工具协议,而不是项目自己随意定义。
- preset/runtime 参数应该以认证凭证为边界,当前项目应使用 Bearer token,并默认通过受控环境变量注入 CLI 执行环境,而不是把 DB session 直接暴露给工具调用接口。
- worker output 和 tool output 的协议职责必须分离,不能混成同一套字段语义。
- 协议文档先行,
docs/protocols/**仍是项目单一协议真源。 - 本项目的"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包含 frontmatter:name、description- 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 tool:
project_cli - 对 tool 的内部实现来说,它可以调用 CLI
- CLI 的输入输出要能被稳定转换为 AgentScope
ToolResponse
4. Confirmed Repository Facts
4.1 当前工具执行方式
当前项目仍然是 Python 函数直接注册多个工具:
backend/src/core/agentscope/tools/toolkit.pyTOOL_FUNCTIONS直接绑定:calendar_readcalendar_writecalendar_shareuser_lookupmemory_writememory_forget
build_toolkit()通过toolkit.register_tool_function(...)注册这些函数
backend/src/core/agentscope/tools/tool_config.py- 现统一使用
enabled_skills(calendar|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.pyget_current_user()从Authorization: Bearer <token>解析 token- 先走 JWT verifier,再 fallback 到 Supabase user lookup
- 最终产出
CurrentUser
backend/src/core/auth/models.pyCurrentUser当前字段:id、phone、role
结论:如果工具改为 CLI,runtime 的合理边界应是 token 或 auth credential,而不是 DB session / owner_id。token 默认通过受控环境变量注入 CLI 运行环境,CLI 内部再根据 token 推导用户身份和数据访问上下文。
补充约束:
- 不能仅凭
owner_id直接构造用户 Bearer token;owner_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.pyWorkerAgentOutputRich.ui_hints
当前 runtime 会把 ui_hints 带入最终文本事件:
backend/src/core/agentscope/runtime/stage_emitter.pyemit_final_text_end()将ui_hints写入 payload
当前对外 AG-UI payload 会把 ui_hints 编译为 ui_schema:
backend/src/core/agentscope/events/agui_codec.pyTEXT_MESSAGE_END上执行compile_ui_hints(...)
当前 history 回放同样依赖 ui_hints -> ui_schema:
backend/src/v1/agent/utils.pybackend/src/v1/agent/schemas.py
结论:当前 ui_schema 的真源是 worker 自身输出的 ui_hints。本次改造将把 ui_hints 的来源从 worker output 改为 tool output,ui_hints → ui_schema 的编译链路保持不变。
4.4 当前前端消费方式
前端当前消费的是后端下发的编译后 ui_schema:
apps/lib/core/chat/ag_ui_event.dartapps/lib/core/chat/chat_history_repository.dartapps/lib/shared/widgets/ui_schema/ui_schema_renderer.dartapps/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 结构,不符合目标边界
- tool 最终返回
backend/src/core/agentscope/utils/parsing.py- 从 ToolResponse text block 中恢复
ToolAgentOutput
- 从 ToolResponse text block 中恢复
backend/src/core/agentscope/runtime/stage_emitter.pyTOOL_CALL_RESULTpayload 包含tool_name、tool_call_args、status、result
当前仓库已经存在"给 agent 的文本内容"和"给事件/持久化的完整结构化对象"分离的模式:
backend/src/core/agentscope/events/store.py- tool 消息持久化时:
content = tool_output.result - 完整结构化对象进入
metadata.tool_agent_output
- tool 消息持久化时:
backend/tests/unit/core/agentscope/events/test_store.py- 明确校验 tool message
content等于文本结果 - 同时完整
tool_agent_output保存在 metadata 中
- 明确校验 tool message
结论:当前仓库已经证明一个正确的职责分层:
- worker/上下文消费的应是 tool message
content - AG-UI 事件、持久化和前端渲染可以保留完整
ToolAgentOutput
但当前仍有三个缺口:
ToolAgentOutput还没有承载前端所需ui_hintsToolAgentOutput.result仍是字符串,还没有升级为结构化对象字段ToolResponse还没有收敛为只承载result文本投影,再交给 tool 后处理器生成完整ToolAgentOutput
此外,history/replay 的正确恢复方向也已经比较明确:
- 可以像 worker output 一样,从
message.metadata中恢复结构化对象 - 对 tool 来说,恢复源应是
metadata.tool_agent_output.ui_hints
5. Problem Statement
当前实现存在 5 个核心问题:
- 工具实现直接耦合在 Python runtime 函数注册层,缺少独立协议边界。
- skill 尚未成为 agent 的原生能力入口,工具知识仍主要依赖 prompt 和函数 docstring。
- worker 仍承担 UI 描述职责,导致
ui_hints占 token,且与前后端实现容易漂移。 - tool result 已经拥有独立结构化对象,但没有成为 UI 渲染主路径。
- 当前 tool output 协议没有明确区分"给 worker 推理的 content"和"给前端渲染的完整结构化输出"。
- 当前 CLI 工具边界尚未定义为受限命令行工具,容易和通用 shell 执行概念混淆。
6. Target Architecture
6.1 总体方向
目标架构应遵循下面的职责分层:
-
AgentScope skill
- 负责告诉 agent:
- 有哪些工具能力
- 什么时候调用
- 调用前后如何决策
- 不直接承担业务执行
- 负责告诉 agent:
-
AgentScope tool
- agent 固定只看到一个工具入口:
project_cli - 内部执行方式为结构化
command + subcommand + args-> 调用项目 CLI -> 适配回 ToolResponse
- agent 固定只看到一个工具入口:
-
CLI tool
- 是业务执行边界
- 输入输出必须稳定、结构化、可验证
- 采用经典命令树:
command + subcommand + args - 不按
skill + action建模 CLI - 必须符合 AgentScope 工具协议适配需要
- 必须是受限项目命令行工具,不提供通用 bash/shell 能力
-
Tool output protocol
- 保留独立的
ToolAgentOutput类协议对象 - 对 AG-UI 事件、持久化元数据、前端渲染负责
- 可包含
ui_hints这类前端渲染字段
- 保留独立的
-
UI contract
- 由 tool output 中的
ui_hints编译生成ui_schema ui_schema成为前端渲染的输入- worker output 不再输出
ui_hints
- 由 tool output 中的
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_nametool_call_idtool_call_argsstatusresulterrorui_hints
这样职责分层固定为:
- agent 只看到
message.content/ToolResponse中的result文本投影 - runtime / SSE / history / persistence 使用完整
ToolAgentOutput
6.4 Worker 与 Tool 输出职责分离
根据当前仓库已存在的运行时与持久化逻辑,本次重构必须明确保持以下分层:
-
worker output
- 面向 worker 最终回答
- 不再包含
ui_hints
-
tool output
- 使用
ToolAgentOutput作为结构化协议对象 - 面向 AG-UI 事件、历史持久化、前端渲染
- 可以包含
ui_hints
- 使用
-
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
- tool message
因此正确方向不是删除 ToolAgentOutput,而是:
- 保留
ToolAgentOutput作为独立 tool 协议对象 - 只让 worker 主要消费 tool message
content
6.4 message.content 字段策略
本次不建议把 message.content 从文本改成通用 schema 字段。
原因:
- AgentScope/Msg 本身是通用消息抽象,不同 role 的 content 类型已经存在差异,但当前项目的 worker 推理、历史持久化、事件处理都默认把文本内容当作主信息载体。
- 当前仓库已经有一条可工作的分层:
message.content给 worker 推理metadata.tool_agent_output给结构化消费
- 若把
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",而是:
- 先把 tool output 协议收敛为稳定的结构化 schema
- 在 tool output 协议中保留前端所需
ui_hints - 再从该协议导出 AG-UI / history / frontend 统一 contract
- AG-UI 传输时:后端 codec 将
ui_hints编译为ui_schema后传输 - 前端渲染
ui_schema(复用现有UiSchemaRenderer)
关键设计决策:
ui_hints是 tool 输出的描述性 UI 表示(真源)ui_schema是编译后的渲染性 UI 表示(传输格式)- 编译链路
ui_hints → ui_schema保持不变,仅改变ui_hints的来源 - 前端继续使用现有
UiSchemaRenderer渲染ui_schema
因此本次必须避免两个错误方向:
- 继续保留
worker -> ui_hints -> ui_schema(应改为tool -> ui_hints -> ui_schema) - 让前端直接绑定
ui_hints而不是ui_schema - 把完整
ToolAgentOutput直接塞回 worker 推理输入,而不是让 worker 主要消费 tool messagecontent - 把"项目 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 后,最终需要映射成两层信息:
-
message.content- 给 worker ReAct loop 使用
- 应为结构化
result的稳定文本投影 - 由结构化
result稳定投影生成 - 默认保留完整 JSON 文本投影,不做阉割式摘要裁剪
-
ToolAgentOutput- 给 AG-UI 事件、持久化、前端渲染使用
- 至少包含
tool_name、tool_call_id、tool_call_args、status、result、error - 本次应扩展支持
ui_hints
这里的实现约束已经确定:
ToolResponse只返回result文本投影- 完整
ToolAgentOutput由 tool 后处理器在 runtime 内生成 ui_hints由 tool 后处理器生成并写入ToolAgentOutputui_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_skillsfrom system agents configenabled_skillsfrom automation jobs config
允许变化的部分:
enabled_skills不再映射到 Python 函数名- 改为映射到 CLI-backed tool capability
7.4 Worker Output 精简要求
worker output 必须移除:
ui_hints
worker output 保留:
statusanswersuggested_actionserror
是否增加新的结构化字段,必须以协议文档先定义为前提;禁止再次引入新的"隐式 UI 描述字段"。
7.5 Tool Output 协议重构要求
ToolAgentOutput 不应被删除,而应被重构为更完整的 tool 协议对象。
至少应满足:
- 保留当前已有字段:
tool_nametool_call_idtool_call_argsstatusresulterror
- 扩展支持:
ui_hints
其中 result 应升级为结构化对象字段,不再以字符串为真源。
同时需要新增一条投影规则:
- 从结构化
result生成稳定文本投影,写入 tool messagecontent - 默认使用完整 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不再依赖 workerui_hints编译- history assistant message 不再依赖
metadata.agent_output.ui_hints编译 - tool result 成为 UI 合约的主要输入之一
TOOL_CALL_RESULT/ tool metadata / history replay 能保留 toolui_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.mddocs/protocols/ui/data-flow.mddocs/protocols/agent/sse-events.mddocs/protocols/agent/run-agent-input.mddocs/protocols/agent/api-endpoints.md
建议新增:
- 一个工具协议文档,明确:
- CLI 输入输出约定
- token preset 约定
- tool result 到 UI contract 的映射边界
8.2 Backend
主要改动点:
backend/src/core/agentscope/tools/toolkit.pybackend/src/core/agentscope/tools/tool_config.pybackend/src/core/agentscope/runtime/runner.pybackend/src/core/agentscope/runtime/stage_emitter.pybackend/src/core/agentscope/events/agui_codec.pybackend/src/core/agentscope/events/store.pybackend/src/core/agentscope/runtime/tasks.pybackend/src/core/agentscope/utils/parsing.pybackend/src/schemas/agent/runtime_models.pybackend/src/v1/agent/utils.pybackend/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 / 收尾清理
本次改造完成后,必须明确收尾清理以下代码与路径,避免旧协议残留:
-
删除或下线 worker
ui_hints主路径backend/src/schemas/agent/runtime_models.py中 worker rich output 的旧定义backend/src/core/agentscope/runtime/stage_emitter.py中向TEXT_MESSAGE_END写入 workerui_hints的逻辑backend/src/core/agentscope/events/agui_codec.py中TEXT_MESSAGE_END的compile_ui_hints(...)主路径backend/src/v1/agent/utils.py中 assistant history 读取 workerui_hints并编译的逻辑
-
清理旧文档语义
docs/protocols/ui/data-flow.md中"worker ui_hints 是 UI 真源"的描述docs/protocols/ui/ui-schema.md中把 UI compiler 绑定到 workerui_hints的描述docs/protocols/agent/sse-events.md/api-endpoints.md/run-agent-input.md中与旧 worker UI 路径冲突的描述
-
清理测试中的旧假设
- 依赖 worker
ui_hints的 runtime/event/history 单测 - 依赖
ToolAgentOutput.result为字符串真源的测试
- 依赖 worker
-
清理旧前端假设
- 只接受 assistant
ui_schema而不理解 toolui_schema的渲染逻辑 - 历史/事件解析中把 assistant UI 当唯一 UI 来源的路径
- 只接受 assistant
-
清理旧工具调用边界
- 继续把 Python runtime 函数当作唯一稳定工具边界的 registry 代码
- 任何会把 DB session / owner_id 直接注入到 CLI 边界的适配代码
- 旧
custom/*.py直接工具实现
-
清理第二条 runtime 冷路径
backend/src/core/agentscope/runtime/tasks.py中与新 tool output/context rebuild 不一致的旧序列化路径- 所有会导致热路径、冷路径看到不同 tool 上下文的兼容逻辑
8.4 Frontend
主要改动点:
apps/lib/core/chat/ag_ui_event.dartapps/lib/core/chat/chat_history_repository.dartapps/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将被移除,toolui_hints保留在独立协议中 - 明确
ui_hints → ui_schema编译链路保持不变
Phase 2. Skill And Tool Boundary Refactor
- 接入项目内 skill
- 定义单一
project_cliAgentScope 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 不再依赖 workerui_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 已收口,不再保留架构级未决项。
已确认结论:
ui_hints是 tool 输出的 UI 描述(真源),ui_schema是编译后的渲染格式(传输格式)- skill 资产目录最终精确落点为
backend/src/core/agentscope/tools/custom - skill 部署方式参考 AgentScope skill 提供的原生方法
- CLI 输入通道采用"两者结合",默认
argv为主、stdin为辅 - history route 的 tool UI 回放从
metadata.tool_agent_output.ui_hints读取并编译为ui_schema - 旧
custom/*.py不再保留,工具实现改为 CLI handler / router ToolResponse只返回result文本投影,完整ToolAgentOutput由 tool 后处理器生成
12. Risks
- 如果只把工具换成 CLI,但不先定义稳定工具协议,最终仍会把旧耦合问题原样搬过去。
- 如果前端直接消费
ui_hints而不是ui_schema,会破坏现有渲染链路。 - 如果把"项目 CLI"误实现为通用 shell/命令执行器,会引入提示词注入和越权风险。
- 如果 token/凭证 注入边界设计不严谨,容易把认证逻辑散落到多个工具实现中。
- 当前代码里仍有多处 broad catch,迁移时错误可能被掩盖:
backend/src/core/agentscope/events/agui_codec.pybackend/src/v1/agent/utils.pyapps/lib/core/chat/ag_ui_service.dart
13. Definition Of Done
当以下条件全部满足时,本任务完成:
- 协议文档修正完毕并成为实现依据。
- AgentScope skill 已在项目内落地并承担工具使用知识披露。
- 当前工具已切换为单一
project_cli+ skills 手册架构。 - token/受控凭证 已通过受控环境变量成为 CLI runtime 的认证边界。
- worker output 已移除
ui_hints。 ToolAgentOutput已成为独立完整的 tool 协议对象,并承载前端所需 UI hints。ToolAgentOutput.result已升级为结构化对象真源。- worker 仅通过完整 JSON 文本投影的 tool message
content获取工具结果主信息。 - history 能通过
metadata.tool_agent_output.ui_hints编译为ui_schema恢复 tool UI。 runtime/tasks.py等冷/热路径已统一,不再存在第二条旧路径。- AG-UI 对 tool UI 编译
ui_hints → ui_schema后传输,前端继续复用现有 UI 渲染器。 - 旧 worker UI 编译路径和相关清理项已完成收尾。
- 前后端事件/history/渲染链路验证通过。
ui_hints → ui_schema编译链路保持不变,仅改变ui_hints来源。- skill 资产已按约定落在
backend/src/core/agentscope/tools/skills,并按 AgentScope 原生方式装载。 - CLI 输入通道已按
argv主、stdin辅的组合模式落地。 - history route 已从
metadata.tool_agent_output.ui_hints编译为ui_schema回放 tool UI。 - 旧
custom/*.py直接工具实现已被 CLI handler / router 替换。 ToolResponse已收敛为只返回result文本投影,完整ToolAgentOutput由 tool 后处理器生成。