欢迎光临
我们一直在努力

Agent架构:QwenPaw之Skill技能底座与Tool工具底座

QwenPaw:Skill技能底座与Tool工具底座如何协作

Agent 能真正动手干活,依赖的是“能力资产”和“执行运行”两套底座的分离。技能底座负责把 SKILL.md + scripts/ 这类能力包做入库、筛选、版本管理,并决定哪些能力应该被模型看见;工具底座负责把 scripts/ 里的业务函数封装成可治理、可隔离、可安全执行的工具对象,完成注册、查找、注入、执行和审计。两层底座上下衔接,单向交付,才构成一个既方便扩展能力、又不会放任裸函数运行的系统。

这篇内容以 QwenPaw 的拆解为主线,先讲工具底座怎么从函数走到安全执行,再讲技能底座怎么从资产走到模型决策,最后把两层底座的边界和协作链路串起来。

一、先建立整体认知:两层底座不是平级关系

Agent 能力底座可以分成两个层面:

底座主要对象核心职责解决的核心问题
技能底座 技能包、SKILL.md、manifest.json、全局技能池 能力入库、版本管理、多租户筛选、提示词注入 模型能不能识别并选择某个能力
工具底座 FunctionTool、PolicyGuardedTool、注册表、ToolGuard、沙箱 工具注册、查找、注入、权限校验、沙箱执行 函数能不能被安全、可靠地执行

技能底座在上,工具底座在下。技能底座产出“可被模型理解的资产素材”,工具底座承接“可被运行时执行的函数调用”。它们不是一套东西的两个名称,而是两个生命周期、两种治理对象。

#mermaid-svg-niMyrDuJfVS73Ocs{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-niMyrDuJfVS73Ocs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-niMyrDuJfVS73Ocs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-niMyrDuJfVS73Ocs .error-icon{fill:#552222;}#mermaid-svg-niMyrDuJfVS73Ocs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-niMyrDuJfVS73Ocs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-niMyrDuJfVS73Ocs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-niMyrDuJfVS73Ocs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-niMyrDuJfVS73Ocs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-niMyrDuJfVS73Ocs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-niMyrDuJfVS73Ocs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-niMyrDuJfVS73Ocs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-niMyrDuJfVS73Ocs .marker.cross{stroke:#333333;}#mermaid-svg-niMyrDuJfVS73Ocs svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-niMyrDuJfVS73Ocs p{margin:0;}#mermaid-svg-niMyrDuJfVS73Ocs .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-niMyrDuJfVS73Ocs .cluster-label text{fill:#333;}#mermaid-svg-niMyrDuJfVS73Ocs .cluster-label span{color:#333;}#mermaid-svg-niMyrDuJfVS73Ocs .cluster-label span p{background-color:transparent;}#mermaid-svg-niMyrDuJfVS73Ocs .label text,#mermaid-svg-niMyrDuJfVS73Ocs span{fill:#333;color:#333;}#mermaid-svg-niMyrDuJfVS73Ocs .node rect,#mermaid-svg-niMyrDuJfVS73Ocs .node circle,#mermaid-svg-niMyrDuJfVS73Ocs .node ellipse,#mermaid-svg-niMyrDuJfVS73Ocs .node polygon,#mermaid-svg-niMyrDuJfVS73Ocs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-niMyrDuJfVS73Ocs .rough-node .label text,#mermaid-svg-niMyrDuJfVS73Ocs .node .label text,#mermaid-svg-niMyrDuJfVS73Ocs .image-shape .label,#mermaid-svg-niMyrDuJfVS73Ocs .icon-shape .label{text-anchor:middle;}#mermaid-svg-niMyrDuJfVS73Ocs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-niMyrDuJfVS73Ocs .rough-node .label,#mermaid-svg-niMyrDuJfVS73Ocs .node .label,#mermaid-svg-niMyrDuJfVS73Ocs .image-shape .label,#mermaid-svg-niMyrDuJfVS73Ocs .icon-shape .label{text-align:center;}#mermaid-svg-niMyrDuJfVS73Ocs .node.clickable{cursor:pointer;}#mermaid-svg-niMyrDuJfVS73Ocs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-niMyrDuJfVS73Ocs .arrowheadPath{fill:#333333;}#mermaid-svg-niMyrDuJfVS73Ocs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-niMyrDuJfVS73Ocs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-niMyrDuJfVS73Ocs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-niMyrDuJfVS73Ocs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-niMyrDuJfVS73Ocs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-niMyrDuJfVS73Ocs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-niMyrDuJfVS73Ocs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-niMyrDuJfVS73Ocs .cluster text{fill:#333;}#mermaid-svg-niMyrDuJfVS73Ocs .cluster span{color:#333;}#mermaid-svg-niMyrDuJfVS73Ocs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-niMyrDuJfVS73Ocs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-niMyrDuJfVS73Ocs rect.text{fill:none;stroke-width:0;}#mermaid-svg-niMyrDuJfVS73Ocs .icon-shape,#mermaid-svg-niMyrDuJfVS73Ocs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-niMyrDuJfVS73Ocs .icon-shape p,#mermaid-svg-niMyrDuJfVS73Ocs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-niMyrDuJfVS73Ocs .icon-shape .label rect,#mermaid-svg-niMyrDuJfVS73Ocs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-niMyrDuJfVS73Ocs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-niMyrDuJfVS73Ocs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-niMyrDuJfVS73Ocs :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

只交付函数引用、Schema 与技能描述

读取 SKILL.md 做决策

输出工具名 + 入参

工具底座:Runtime 执行层

函数注册为 FunctionTool

套上 PolicyGuardedTool 治理壳

注册表查找 + ChannelACL

策略裁决 + 参数安检 + 沙箱执行

技能底座:资产管理层

技能包 SKILL.md + scripts/

入库 / 版本 / 来源管理

多租户与父子 Agent 权限筛选

把 SKILL.md 注入模型 Prompt

大模型

二、工具底座:函数怎么变成可安全调用的 Agent 资产

工具底座要回答四件事:工具怎么进来、Agent 怎么找到它、工具怎么进入运行环境、工具怎么被安全执行。

2.1 工具注册:普通函数包装成标准工具对象

注册入口做的事情很简单:把业务函数、名称和 Schema 组合成一个 FunctionTool,再用工具名登记进注册表。

# 工具注册:把业务函数包装成 FunctionTool 并登记进注册表
def register_tool(name, func, schema):
tool = FunctionTool(name=name, func=func, schema=schema)
registry.register(name, tool) # 工具名作为唯一标识
return tool

这里有三类信息需要分开理解:

  • name:Agent 查找工具的稳定标识;
  • schema:给 LLM 看的接口契约,说明入参和出参;
  • func:真正的业务执行逻辑。

QwenPaw 的关键设计是:注册时并不注册裸函数,而是注册一个被“治理壳”包装过的工具。PolicyGuardedTool 用动态 type() 构造 FunctionTool 子类,把权限检查、调用入口真实挂在类上,让业务工具在注册时就自动获得策略拦截和审批能力,业务代码内部不需要写权限逻辑。

# PolicyGuardedTool 动态构造:工具注册即获得治理能力
real_cls = type(
"PolicyGuardedTool",
(FunctionTool,),
{"check_permissions": _policy_tool_check_permissions,
"call": _policy_tool_call},
)

注册存在两种形态:

  • 函数工具注册:代码内置工具,进程启动时统一登记,属于静态注册;
  • 技能包注册:SKILL.md + scripts/ 存放在 MinIO 等对象存储中,按需加载进运行环境,属于动态加载。

两者共同构成 Agent 的能力资产池。

#mermaid-svg-Y65aLQQbdkLKnYCN{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Y65aLQQbdkLKnYCN .error-icon{fill:#552222;}#mermaid-svg-Y65aLQQbdkLKnYCN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Y65aLQQbdkLKnYCN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Y65aLQQbdkLKnYCN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Y65aLQQbdkLKnYCN .marker.cross{stroke:#333333;}#mermaid-svg-Y65aLQQbdkLKnYCN svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Y65aLQQbdkLKnYCN p{margin:0;}#mermaid-svg-Y65aLQQbdkLKnYCN .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Y65aLQQbdkLKnYCN .cluster-label text{fill:#333;}#mermaid-svg-Y65aLQQbdkLKnYCN .cluster-label span{color:#333;}#mermaid-svg-Y65aLQQbdkLKnYCN .cluster-label span p{background-color:transparent;}#mermaid-svg-Y65aLQQbdkLKnYCN .label text,#mermaid-svg-Y65aLQQbdkLKnYCN span{fill:#333;color:#333;}#mermaid-svg-Y65aLQQbdkLKnYCN .node rect,#mermaid-svg-Y65aLQQbdkLKnYCN .node circle,#mermaid-svg-Y65aLQQbdkLKnYCN .node ellipse,#mermaid-svg-Y65aLQQbdkLKnYCN .node polygon,#mermaid-svg-Y65aLQQbdkLKnYCN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Y65aLQQbdkLKnYCN .rough-node .label text,#mermaid-svg-Y65aLQQbdkLKnYCN .node .label text,#mermaid-svg-Y65aLQQbdkLKnYCN .image-shape .label,#mermaid-svg-Y65aLQQbdkLKnYCN .icon-shape .label{text-anchor:middle;}#mermaid-svg-Y65aLQQbdkLKnYCN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Y65aLQQbdkLKnYCN .rough-node .label,#mermaid-svg-Y65aLQQbdkLKnYCN .node .label,#mermaid-svg-Y65aLQQbdkLKnYCN .image-shape .label,#mermaid-svg-Y65aLQQbdkLKnYCN .icon-shape .label{text-align:center;}#mermaid-svg-Y65aLQQbdkLKnYCN .node.clickable{cursor:pointer;}#mermaid-svg-Y65aLQQbdkLKnYCN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Y65aLQQbdkLKnYCN .arrowheadPath{fill:#333333;}#mermaid-svg-Y65aLQQbdkLKnYCN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Y65aLQQbdkLKnYCN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Y65aLQQbdkLKnYCN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y65aLQQbdkLKnYCN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Y65aLQQbdkLKnYCN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y65aLQQbdkLKnYCN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Y65aLQQbdkLKnYCN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Y65aLQQbdkLKnYCN .cluster text{fill:#333;}#mermaid-svg-Y65aLQQbdkLKnYCN .cluster span{color:#333;}#mermaid-svg-Y65aLQQbdkLKnYCN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Y65aLQQbdkLKnYCN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Y65aLQQbdkLKnYCN rect.text{fill:none;stroke-width:0;}#mermaid-svg-Y65aLQQbdkLKnYCN .icon-shape,#mermaid-svg-Y65aLQQbdkLKnYCN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Y65aLQQbdkLKnYCN .icon-shape p,#mermaid-svg-Y65aLQQbdkLKnYCN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Y65aLQQbdkLKnYCN .icon-shape .label rect,#mermaid-svg-Y65aLQQbdkLKnYCN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Y65aLQQbdkLKnYCN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Y65aLQQbdkLKnYCN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Y65aLQQbdkLKnYCN :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

工具注册入口

函数工具启动时统一登记

技能包SKILL.md + scripts/

FunctionTool + PolicyGuardedTool

按需加载到运行环境

内存工具注册表

2.2 工具查找:从模型决策到注册表解析

模型在推理过程中决定调用哪个工具,输出工具名和入参。底座的查找逻辑,就是拿这个工具名去注册表定位工具对象。

# 工具查找:按名称解析工具,未命中给出明确错误
def resolve_tool(name):
tool = registry.get(name)
if tool is None:
raise ToolNotFound(name) # 未注册工具直接报错
return tool

查找阶段的核心策略是 fail-closed:未注册工具直接拒绝,不猜测执行。这一步相当于治理链路的第一道类型检查,遇到未知工具直接 DENY,理由明确是“未注册工具”。

查找不只解决“工具在哪里”,还要解决“谁有资格调用”。ChannelACL 在消息入口做身份校验:白名单直通、黑名单拒绝、陌生人进入 pending 审批队列。一个被拉进群的 Bot,不应该等于把整台机器交出去。

# 渠道准入:查找前先验身份,白名单外默认拒绝
def admit(channel, user):
if user in acl[channel].whitelist: return Pass()
if user in acl[channel].blacklist: return Reject()
acl[channel].pending.append(PendingEntry(user, first_msg))
return WaitForAdmin() # 陌生人进 pending,等待管理员审批

2.3 工具注入:把能力装配进 Agent 运行环境

工具要真正可用,还需要被注入到 Agent 的运行环境。注入分两个时机:启动时一次性注入、运行过程中动态新增。

启动阶段,WorkspaceBootstrapFactory 把三类东西塞进 Workspace:

  • 内置工具列表,例如文件读写、Shell 执行、HTTP 调用;
  • 生命周期钩子,用于审计、日志、超时控制;
  • 运行模式,例如是否允许联网、是否启用沙箱。

Web 入口和命令行入口都调用同一个 build_kwargs(),避免出现 Web 能调、CLI 不能调的不一致。

# 工具注入:装配工厂统一挂载内置工具与钩子
def build_kwargs(ws_cfg):
return {
"tools": self._builtin_tools(ws_cfg), # 注入内置工具
"hooks": self._builtin_hooks(), # 注入生命周期钩子
"modes": self._mode_registry() # 注入运行模式
}

运行期新增技能则走热刷新链路:Manager 把技能目录推到 MinIO,Worker 定时检查 ETag 指纹,发现变化后调用 refresh_and_enable_skills()。容器不重建、进程不重启、正在执行的任务不受影响,新任务可以立即使用新技能。

# 技能注入:推送技能目录到 MinIO,Worker 侧热刷新
mc mirror ./skills/git-skill minio/agents/member01/skills/ –overwrite –remove
mc stat minio/agents/member01/skills/git-skill/SKILL.md # 契约校验
notify_worker member01 "Your Manager updated these workspace skills"

MinIO 在这里是 Manager 与 Worker 之间的唯一传递媒介,两边通过文件路径和 ETag 指纹达成一致,不建立直接 RPC 连接。MCP 工具清单也走同一条管道:mcporter.go 生成 mcporter.json 写入 MinIO,Worker 拉取后解析出可用的 MCP 服务地址和工具列表。

Worker 执行面MinIO 对象存储Manager 控制面Worker 执行面MinIO 对象存储Manager 控制面#mermaid-svg-ibeGd3CsiTHJ02wf{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ibeGd3CsiTHJ02wf .error-icon{fill:#552222;}#mermaid-svg-ibeGd3CsiTHJ02wf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ibeGd3CsiTHJ02wf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ibeGd3CsiTHJ02wf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ibeGd3CsiTHJ02wf .marker.cross{stroke:#333333;}#mermaid-svg-ibeGd3CsiTHJ02wf svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ibeGd3CsiTHJ02wf p{margin:0;}#mermaid-svg-ibeGd3CsiTHJ02wf .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ibeGd3CsiTHJ02wf text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-ibeGd3CsiTHJ02wf .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-ibeGd3CsiTHJ02wf .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-ibeGd3CsiTHJ02wf .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-ibeGd3CsiTHJ02wf .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-ibeGd3CsiTHJ02wf #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-ibeGd3CsiTHJ02wf .sequenceNumber{fill:white;}#mermaid-svg-ibeGd3CsiTHJ02wf #sequencenumber{fill:#333;}#mermaid-svg-ibeGd3CsiTHJ02wf #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-ibeGd3CsiTHJ02wf .messageText{fill:#333;stroke:none;}#mermaid-svg-ibeGd3CsiTHJ02wf .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ibeGd3CsiTHJ02wf .labelText,#mermaid-svg-ibeGd3CsiTHJ02wf .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-ibeGd3CsiTHJ02wf .loopText,#mermaid-svg-ibeGd3CsiTHJ02wf .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-ibeGd3CsiTHJ02wf .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-ibeGd3CsiTHJ02wf .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-ibeGd3CsiTHJ02wf .noteText,#mermaid-svg-ibeGd3CsiTHJ02wf .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-ibeGd3CsiTHJ02wf .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ibeGd3CsiTHJ02wf .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ibeGd3CsiTHJ02wf .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-ibeGd3CsiTHJ02wf .actorPopupMenu{position:absolute;}#mermaid-svg-ibeGd3CsiTHJ02wf .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-ibeGd3CsiTHJ02wf .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-ibeGd3CsiTHJ02wf .actor-man circle,#mermaid-svg-ibeGd3CsiTHJ02wf line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-ibeGd3CsiTHJ02wf :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}alt[指纹发生变化][无变化]mc mirror 推送技能目录mc stat 校验 SKILL.md 契约周期性读取 ETag 指纹refresh_and_enable_skills()新工具注入本地注册表保持当前 Workspace

2.4 工具执行:四道独立校验门

工具执行链路是:LLM 输出 tool_call -> 底座拦截 -> 逐层校验 -> 真实执行。QwenPaw 在模型调用与真实执行之间设置了四道相互独立的校验门:

  • 技能体检,在技能加载时执行;
  • 渠道准入,在消息入口执行;
  • 策略裁决,在工具执行前执行;
  • 参数安检,在参数即将进入执行函数时执行。
  • #mermaid-svg-OVVhmEhrzLZ7tJup{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OVVhmEhrzLZ7tJup .error-icon{fill:#552222;}#mermaid-svg-OVVhmEhrzLZ7tJup .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OVVhmEhrzLZ7tJup .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OVVhmEhrzLZ7tJup .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OVVhmEhrzLZ7tJup .marker.cross{stroke:#333333;}#mermaid-svg-OVVhmEhrzLZ7tJup svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OVVhmEhrzLZ7tJup p{margin:0;}#mermaid-svg-OVVhmEhrzLZ7tJup .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-OVVhmEhrzLZ7tJup .cluster-label text{fill:#333;}#mermaid-svg-OVVhmEhrzLZ7tJup .cluster-label span{color:#333;}#mermaid-svg-OVVhmEhrzLZ7tJup .cluster-label span p{background-color:transparent;}#mermaid-svg-OVVhmEhrzLZ7tJup .label text,#mermaid-svg-OVVhmEhrzLZ7tJup span{fill:#333;color:#333;}#mermaid-svg-OVVhmEhrzLZ7tJup .node rect,#mermaid-svg-OVVhmEhrzLZ7tJup .node circle,#mermaid-svg-OVVhmEhrzLZ7tJup .node ellipse,#mermaid-svg-OVVhmEhrzLZ7tJup .node polygon,#mermaid-svg-OVVhmEhrzLZ7tJup .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OVVhmEhrzLZ7tJup .rough-node .label text,#mermaid-svg-OVVhmEhrzLZ7tJup .node .label text,#mermaid-svg-OVVhmEhrzLZ7tJup .image-shape .label,#mermaid-svg-OVVhmEhrzLZ7tJup .icon-shape .label{text-anchor:middle;}#mermaid-svg-OVVhmEhrzLZ7tJup .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OVVhmEhrzLZ7tJup .rough-node .label,#mermaid-svg-OVVhmEhrzLZ7tJup .node .label,#mermaid-svg-OVVhmEhrzLZ7tJup .image-shape .label,#mermaid-svg-OVVhmEhrzLZ7tJup .icon-shape .label{text-align:center;}#mermaid-svg-OVVhmEhrzLZ7tJup .node.clickable{cursor:pointer;}#mermaid-svg-OVVhmEhrzLZ7tJup .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OVVhmEhrzLZ7tJup .arrowheadPath{fill:#333333;}#mermaid-svg-OVVhmEhrzLZ7tJup .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OVVhmEhrzLZ7tJup .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OVVhmEhrzLZ7tJup .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OVVhmEhrzLZ7tJup .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OVVhmEhrzLZ7tJup .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OVVhmEhrzLZ7tJup .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OVVhmEhrzLZ7tJup .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OVVhmEhrzLZ7tJup .cluster text{fill:#333;}#mermaid-svg-OVVhmEhrzLZ7tJup .cluster span{color:#333;}#mermaid-svg-OVVhmEhrzLZ7tJup div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OVVhmEhrzLZ7tJup .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OVVhmEhrzLZ7tJup rect.text{fill:none;stroke-width:0;}#mermaid-svg-OVVhmEhrzLZ7tJup .icon-shape,#mermaid-svg-OVVhmEhrzLZ7tJup .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OVVhmEhrzLZ7tJup .icon-shape p,#mermaid-svg-OVVhmEhrzLZ7tJup .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OVVhmEhrzLZ7tJup .icon-shape .label rect,#mermaid-svg-OVVhmEhrzLZ7tJup .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OVVhmEhrzLZ7tJup .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OVVhmEhrzLZ7tJup .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OVVhmEhrzLZ7tJup :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    LLM 输出 tool_call

    技能体检SkillScanner

    渠道准入ChannelACL

    策略裁决PolicyGuardedTool

    参数安检ToolGuard

    沙箱执行

    结果回写模型

    2.4.1 技能体检:防线前移到加载阶段

    技能被加载进 Workspace 前,SkillScanner 先做静态扫描:限制文件数量和单文件大小,检测硬编码密钥、危险系统调用等恶意模式,最终产出 ScanResult{is_safe}。这一步发生在技能安装或市场拉取阶段,不是每次调用时才扫描。

    2.4.2 渠道准入:只判断“谁在发消息”

    ChannelACL 只校验发送者身份,不校验消息内容和工具参数。白名单用户直接进入 LLM 推理,黑名单用户直接拒绝,未登记用户进入 pending 等待管理员审批。

    2.4.3 策略裁决:四态结果与 fail-closed

    模型决定调用某个工具后,PolicyGuardedTool 在真实执行前触发 check_permissions(),得到四态结果:

    • ALLOW:直接执行;
    • DENY:拒绝执行,错误返回给模型;
    • ASK:暂停执行,等待人工审批;
    • SANDBOX_FALLBACK:进入沙箱执行,沙箱内违规则升级为 ASK。

    # 工具执行:四态裁决 + 审计,governor 缺失 fail-closed 全拒
    def check_permissions(self):
    if self.governor is None:
    return Deny() # 治理层缺失,一律拒绝
    d = self.governor.assert_policy(self.spec())
    self.governor.audit(self.spec(), d) # 无论结果都落审计
    if d.is_off():
    self.attach_sandbox() # OFF 仍挂沙箱,只跳过问人
    return Allow()
    return {"ALLOW": Allow, "DENY": Deny,
    "SANDBOX": Sandbox, "ASK": Ask}

    这里有两个边界条件很关键:治理层组件未初始化成功时,governor 为 None 一律 DENY,不裸奔;OFF 模式不等于不隔离,它只跳过“问用户”这一步,但仍然挂沙箱。

    2.4.4 参数安检:四类守卫串行执行

    ToolGuard 在工具即将执行前,对参数做最后一道检查。四类守卫串行执行:

    守卫检查内容是否可关闭
    SharedSafety 灾难命令分类,如 rm -rf /、mkfs 否,always_run
    FilePath 敏感路径访问,如 /etc/passwd、~/.ssh 否,always_run
    RuleBased YAML 规则热更新,匹配自定义危险模式 是
    ShellEvasion 引号状态机检测命令混淆 是

    # 参数安检:归一化前置 + 四守卫 fail-open 汇总
    def guard(self, tool_name, params):
    params = normalize_continuations(params) # 续行归一化
    result = Result()
    for g in self.guardians:
    try:
    result.findings += g.guard(tool_name, params)
    except Exception as e:
    result.failed.append((g.name, str(e))) # 单守卫异常不中断
    return result

    这里有两条基础策略:

    • fail-open:单个守卫抛异常不会导致整体拒绝,异常被捕获后记录到 result.failed,继续执行下一个守卫;只有守卫明确返回“拒绝”才拦截。
    • always_run:SharedSafety 和 FilePath 不受配置开关控制,即使运维误操作关掉 ToolGuard,这两类底线检查仍然生效。

    ShellEvasionGuardian 用字符级引号状态机逐字符解析命令,区分单引号、双引号、无引号三种状态。单引号内不展开变量所以跳过检测,双引号内 $() 仍执行所以保留检测。rm -rf /et<换行>c 这类续行或引号包裹的变形,会被还原成真实命令再匹配。

    2.5 一次工具调用的完整旅程

    把前面的链路串起来,一次调用可以归纳为下面这张图:

    SandboxToolGuardPolicyGuardedToolLLMChannelACLSkillScanner用户SandboxToolGuardPolicyGuardedToolLLMChannelACLSkillScanner用户#mermaid-svg-YwWnFE2dFRAwzyvc{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YwWnFE2dFRAwzyvc .error-icon{fill:#552222;}#mermaid-svg-YwWnFE2dFRAwzyvc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YwWnFE2dFRAwzyvc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YwWnFE2dFRAwzyvc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YwWnFE2dFRAwzyvc .marker.cross{stroke:#333333;}#mermaid-svg-YwWnFE2dFRAwzyvc svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YwWnFE2dFRAwzyvc p{margin:0;}#mermaid-svg-YwWnFE2dFRAwzyvc .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-YwWnFE2dFRAwzyvc text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-YwWnFE2dFRAwzyvc .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-YwWnFE2dFRAwzyvc .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-YwWnFE2dFRAwzyvc .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-YwWnFE2dFRAwzyvc .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-YwWnFE2dFRAwzyvc #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-YwWnFE2dFRAwzyvc .sequenceNumber{fill:white;}#mermaid-svg-YwWnFE2dFRAwzyvc #sequencenumber{fill:#333;}#mermaid-svg-YwWnFE2dFRAwzyvc #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-YwWnFE2dFRAwzyvc .messageText{fill:#333;stroke:none;}#mermaid-svg-YwWnFE2dFRAwzyvc .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-YwWnFE2dFRAwzyvc .labelText,#mermaid-svg-YwWnFE2dFRAwzyvc .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-YwWnFE2dFRAwzyvc .loopText,#mermaid-svg-YwWnFE2dFRAwzyvc .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-YwWnFE2dFRAwzyvc .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-YwWnFE2dFRAwzyvc .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-YwWnFE2dFRAwzyvc .noteText,#mermaid-svg-YwWnFE2dFRAwzyvc .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-YwWnFE2dFRAwzyvc .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-YwWnFE2dFRAwzyvc .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-YwWnFE2dFRAwzyvc .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-YwWnFE2dFRAwzyvc .actorPopupMenu{position:absolute;}#mermaid-svg-YwWnFE2dFRAwzyvc .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-YwWnFE2dFRAwzyvc .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-YwWnFE2dFRAwzyvc .actor-man circle,#mermaid-svg-YwWnFE2dFRAwzyvc line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-YwWnFE2dFRAwzyvc :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}技能包准备加载ScanResult(is_safe)消息进入身份通过tool_name + argscheck_permissions参数安检守卫结果沙箱执行执行结果

    三、技能底座:能力资产怎么被模型看见

    技能底座面向技能包,不直接执行代码。一个技能包在磁盘上的结构如下:

    skills/git-skill/
    ├── SKILL.md # 技能描述文档,给模型读的
    ├── scripts/
    │ ├── git_ops.py # 业务函数源码
    │ └── utils.py
    └── manifest.json # 版本、依赖、入口函数名

    技能底座只做三件事:从磁盘或 MinIO 读取技能目录;解析 SKILL.md 得到给模型看的文本,解析 manifest 得到函数入口引用;把这些信息登记到全局技能池。它关心的是能力包的分发、筛选、版本和提示词注入,不关心 scripts/ 里的业务函数怎么执行。

    #mermaid-svg-VqECkK7a0hKuiwJ1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VqECkK7a0hKuiwJ1 .error-icon{fill:#552222;}#mermaid-svg-VqECkK7a0hKuiwJ1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VqECkK7a0hKuiwJ1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .marker.cross{stroke:#333333;}#mermaid-svg-VqECkK7a0hKuiwJ1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VqECkK7a0hKuiwJ1 p{margin:0;}#mermaid-svg-VqECkK7a0hKuiwJ1 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .cluster-label text{fill:#333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .cluster-label span{color:#333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .cluster-label span p{background-color:transparent;}#mermaid-svg-VqECkK7a0hKuiwJ1 .label text,#mermaid-svg-VqECkK7a0hKuiwJ1 span{fill:#333;color:#333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .node rect,#mermaid-svg-VqECkK7a0hKuiwJ1 .node circle,#mermaid-svg-VqECkK7a0hKuiwJ1 .node ellipse,#mermaid-svg-VqECkK7a0hKuiwJ1 .node polygon,#mermaid-svg-VqECkK7a0hKuiwJ1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VqECkK7a0hKuiwJ1 .rough-node .label text,#mermaid-svg-VqECkK7a0hKuiwJ1 .node .label text,#mermaid-svg-VqECkK7a0hKuiwJ1 .image-shape .label,#mermaid-svg-VqECkK7a0hKuiwJ1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-VqECkK7a0hKuiwJ1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VqECkK7a0hKuiwJ1 .rough-node .label,#mermaid-svg-VqECkK7a0hKuiwJ1 .node .label,#mermaid-svg-VqECkK7a0hKuiwJ1 .image-shape .label,#mermaid-svg-VqECkK7a0hKuiwJ1 .icon-shape .label{text-align:center;}#mermaid-svg-VqECkK7a0hKuiwJ1 .node.clickable{cursor:pointer;}#mermaid-svg-VqECkK7a0hKuiwJ1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .arrowheadPath{fill:#333333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VqECkK7a0hKuiwJ1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VqECkK7a0hKuiwJ1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VqECkK7a0hKuiwJ1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VqECkK7a0hKuiwJ1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VqECkK7a0hKuiwJ1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VqECkK7a0hKuiwJ1 .cluster text{fill:#333;}#mermaid-svg-VqECkK7a0hKuiwJ1 .cluster span{color:#333;}#mermaid-svg-VqECkK7a0hKuiwJ1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VqECkK7a0hKuiwJ1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VqECkK7a0hKuiwJ1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-VqECkK7a0hKuiwJ1 .icon-shape,#mermaid-svg-VqECkK7a0hKuiwJ1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VqECkK7a0hKuiwJ1 .icon-shape p,#mermaid-svg-VqECkK7a0hKuiwJ1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VqECkK7a0hKuiwJ1 .icon-shape .label rect,#mermaid-svg-VqECkK7a0hKuiwJ1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VqECkK7a0hKuiwJ1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VqECkK7a0hKuiwJ1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VqECkK7a0hKuiwJ1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    技能市场 / 内置仓库 / MinIO

    文件签名与语言变体解析

    staged 临时目录静态体检

    原子 rename 写入 manifest

    全局技能池内存 dict 登记

    Agent 装配筛选

    SKILL.md 注入模型 Prompt

    技能底座保存的不是已经实例化完成的 FunctionTool,而是函数引用路径、元信息 Schema 和 SKILL.md 文档。只有进入 Agent 装配阶段,才会向下实例化并交付给工具底座。这样同一个技能池可以批量生成多份不同 Agent 的生效元集合,而不会提前大量占用内存。

    四、两层底座的衔接:从资产到调用闭环

    技能底座与工具底座的边界在“函数引用从资产层跨层传递到执行层”这一步。整体可以分为四个阶段:

  • 技能资产入库;
  • Agent 装配筛选;
  • 技能底座向工具底座交付函数引用;
  • 模型决策与工具执行。
  • #mermaid-svg-3ccQrLhABjN6k7j1{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3ccQrLhABjN6k7j1 .error-icon{fill:#552222;}#mermaid-svg-3ccQrLhABjN6k7j1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3ccQrLhABjN6k7j1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3ccQrLhABjN6k7j1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3ccQrLhABjN6k7j1 .marker.cross{stroke:#333333;}#mermaid-svg-3ccQrLhABjN6k7j1 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3ccQrLhABjN6k7j1 p{margin:0;}#mermaid-svg-3ccQrLhABjN6k7j1 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-3ccQrLhABjN6k7j1 .cluster-label text{fill:#333;}#mermaid-svg-3ccQrLhABjN6k7j1 .cluster-label span{color:#333;}#mermaid-svg-3ccQrLhABjN6k7j1 .cluster-label span p{background-color:transparent;}#mermaid-svg-3ccQrLhABjN6k7j1 .label text,#mermaid-svg-3ccQrLhABjN6k7j1 span{fill:#333;color:#333;}#mermaid-svg-3ccQrLhABjN6k7j1 .node rect,#mermaid-svg-3ccQrLhABjN6k7j1 .node circle,#mermaid-svg-3ccQrLhABjN6k7j1 .node ellipse,#mermaid-svg-3ccQrLhABjN6k7j1 .node polygon,#mermaid-svg-3ccQrLhABjN6k7j1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3ccQrLhABjN6k7j1 .rough-node .label text,#mermaid-svg-3ccQrLhABjN6k7j1 .node .label text,#mermaid-svg-3ccQrLhABjN6k7j1 .image-shape .label,#mermaid-svg-3ccQrLhABjN6k7j1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-3ccQrLhABjN6k7j1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3ccQrLhABjN6k7j1 .rough-node .label,#mermaid-svg-3ccQrLhABjN6k7j1 .node .label,#mermaid-svg-3ccQrLhABjN6k7j1 .image-shape .label,#mermaid-svg-3ccQrLhABjN6k7j1 .icon-shape .label{text-align:center;}#mermaid-svg-3ccQrLhABjN6k7j1 .node.clickable{cursor:pointer;}#mermaid-svg-3ccQrLhABjN6k7j1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3ccQrLhABjN6k7j1 .arrowheadPath{fill:#333333;}#mermaid-svg-3ccQrLhABjN6k7j1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3ccQrLhABjN6k7j1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3ccQrLhABjN6k7j1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3ccQrLhABjN6k7j1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3ccQrLhABjN6k7j1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3ccQrLhABjN6k7j1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3ccQrLhABjN6k7j1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3ccQrLhABjN6k7j1 .cluster text{fill:#333;}#mermaid-svg-3ccQrLhABjN6k7j1 .cluster span{color:#333;}#mermaid-svg-3ccQrLhABjN6k7j1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3ccQrLhABjN6k7j1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3ccQrLhABjN6k7j1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-3ccQrLhABjN6k7j1 .icon-shape,#mermaid-svg-3ccQrLhABjN6k7j1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3ccQrLhABjN6k7j1 .icon-shape p,#mermaid-svg-3ccQrLhABjN6k7j1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3ccQrLhABjN6k7j1 .icon-shape .label rect,#mermaid-svg-3ccQrLhABjN6k7j1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3ccQrLhABjN6k7j1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3ccQrLhABjN6k7j1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3ccQrLhABjN6k7j1 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    阶段 4:模型决策与执行

    SKILL.md 注入 Prompt

    模型输出工具名 + 入参

    注册表查找

    四道门校验

    沙箱执行与结果回写

    阶段 3:向下交付

    读取 SKILL.md 与 Schema

    取 scripts 函数引用

    FunctionTool 封装

    套 PolicyGuardedTool

    注册进 toolkit._qp_skills

    阶段 2:Agent 装配筛选

    渠道黑白名单

    双目录合并

    父子 Agent 求交

    产出生效技能元集合

    阶段 1:技能资产入库

    拉取技能包

    签名校验与静态扫描

    原子持久化

    全局技能池登记

    阶段 3 的核心动作,是技能底座只把函数引用和 Schema 交给工具底座,不传任何运行时对象。

    # skill_meta 是技能底座产出的元数据,包含函数引用和 schema
    func_ref = skill_meta.scripts_entry # scripts 目录下的业务函数
    schema = skill_meta.input_schema # SKILL.md 里解析出的 JSON Schema
    # 向下交付:只传引用和 schema,不传任何运行时对象
    tool_base = FunctionTool(func_ref, schema=schema)

    工具底座拿到函数引用后,先构造裸工具对象。

    class FunctionTool:
    def __init__(self, func_ref, schema):
    self.func_ref = func_ref # 业务函数引用
    self.schema = schema # 入参约束 schema
    self.name = func_ref.__name__ # 工具名称取自函数名

    再套上治理壳,把身份准入、沙箱和审计能力挂到工具实例上。

    guarded_tool = PolicyGuardedTool(
    wrapped=tool_base, # 被包装的裸工具
    acl=ChannelACL(), # 渠道准入校验
    sandbox=Sandbox(), # 沙箱隔离
    auditor=CallAuditor() # 调用审计
    )

    最后注册进当前 Agent 实例私有的内存注册表,完成两层底座的数据打通。

    # toolkit 是当前 Agent 实例私有的工具注册表
    toolkit._qp_skills[guarded_tool.name] = guarded_tool
    # 此后模型输出的斜杠命令,通过工具名在这里查找到对应实例

    阶段 4 中,模型只能看到 SKILL.md,看不到 scripts/ 内部代码;模型输出调用指令,但不知道底层函数实现。运行时按工具名查找并调用:

    tool_name = parse_slash_command(output_text) # 解析 /skill_name
    tool = toolkit._qp_skills.get(tool_name) # 内存注册表查找
    if not tool:
    return "工具不存在" # fail-closed
    result = tool.invoke(parsed_args) # 执行校验与沙箱执行

    五、边界隔离:为什么两层底座必须分开

    5.1 语义边界隔离

    技能底座只读写 SKILL.md,绝不读取 scripts/ 脚本源码;工具底座只执行 scripts/ 函数,不读取技能文档。模型只能读取 SKILL.md,完全看不到业务代码。

    这样修改业务脚本不需要改 Prompt 文档,修改技能描述也不需要重新发布代码。约束是:SKILL.md 必须是模型理解技能语义的唯一结构化入口。如果文档描述和脚本实际行为不一致,模型认知就会和真实执行行为错位,所以版本迭代时必须保证 SKILL.md 与 scripts/ 一同变更。

    5.2 数据存储隔离

    技能底座的数据是磁盘持久化的技能池、manifest 账本和工作区配置,属于长期静态资产。工具底座的数据只存在于单 Agent 实例内存中的注册表、工具实例和会话调用日志,Agent 销毁即释放。

    manifest 只记录元信息,不记录 FunctionTool 对象实例。Agent 重启后,工具实例由磁盘元信息重新向下实例化生成。

    5.3 双层纵深防御

    上层技能底座在装配期做静态权限裁剪,例如父子 Agent 技能求交、渠道黑名单,在模型决策之前把越权能力剔除出候选集合。下层工具底座在运行时做动态治理校验,即使上层装配逻辑出现漏洞,嵌套调用也无法绕过执行层校验。

    两层防护是叠加关系,不是互斥替代。只做装配裁剪会让运行时失去兜底;只做运行时校验,会让大量无关技能进入 Prompt,造成 Token 膨胀和模型幻觉概率上升。

    #mermaid-svg-CNfbfpATI5BVcP9H{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CNfbfpATI5BVcP9H .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CNfbfpATI5BVcP9H .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CNfbfpATI5BVcP9H .error-icon{fill:#552222;}#mermaid-svg-CNfbfpATI5BVcP9H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CNfbfpATI5BVcP9H .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CNfbfpATI5BVcP9H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CNfbfpATI5BVcP9H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CNfbfpATI5BVcP9H .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CNfbfpATI5BVcP9H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CNfbfpATI5BVcP9H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CNfbfpATI5BVcP9H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CNfbfpATI5BVcP9H .marker.cross{stroke:#333333;}#mermaid-svg-CNfbfpATI5BVcP9H svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CNfbfpATI5BVcP9H p{margin:0;}#mermaid-svg-CNfbfpATI5BVcP9H .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-CNfbfpATI5BVcP9H .cluster-label text{fill:#333;}#mermaid-svg-CNfbfpATI5BVcP9H .cluster-label span{color:#333;}#mermaid-svg-CNfbfpATI5BVcP9H .cluster-label span p{background-color:transparent;}#mermaid-svg-CNfbfpATI5BVcP9H .label text,#mermaid-svg-CNfbfpATI5BVcP9H span{fill:#333;color:#333;}#mermaid-svg-CNfbfpATI5BVcP9H .node rect,#mermaid-svg-CNfbfpATI5BVcP9H .node circle,#mermaid-svg-CNfbfpATI5BVcP9H .node ellipse,#mermaid-svg-CNfbfpATI5BVcP9H .node polygon,#mermaid-svg-CNfbfpATI5BVcP9H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CNfbfpATI5BVcP9H .rough-node .label text,#mermaid-svg-CNfbfpATI5BVcP9H .node .label text,#mermaid-svg-CNfbfpATI5BVcP9H .image-shape .label,#mermaid-svg-CNfbfpATI5BVcP9H .icon-shape .label{text-anchor:middle;}#mermaid-svg-CNfbfpATI5BVcP9H .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CNfbfpATI5BVcP9H .rough-node .label,#mermaid-svg-CNfbfpATI5BVcP9H .node .label,#mermaid-svg-CNfbfpATI5BVcP9H .image-shape .label,#mermaid-svg-CNfbfpATI5BVcP9H .icon-shape .label{text-align:center;}#mermaid-svg-CNfbfpATI5BVcP9H .node.clickable{cursor:pointer;}#mermaid-svg-CNfbfpATI5BVcP9H .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CNfbfpATI5BVcP9H .arrowheadPath{fill:#333333;}#mermaid-svg-CNfbfpATI5BVcP9H .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CNfbfpATI5BVcP9H .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CNfbfpATI5BVcP9H .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CNfbfpATI5BVcP9H .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CNfbfpATI5BVcP9H .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CNfbfpATI5BVcP9H .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CNfbfpATI5BVcP9H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CNfbfpATI5BVcP9H .cluster text{fill:#333;}#mermaid-svg-CNfbfpATI5BVcP9H .cluster span{color:#333;}#mermaid-svg-CNfbfpATI5BVcP9H div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CNfbfpATI5BVcP9H .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CNfbfpATI5BVcP9H rect.text{fill:none;stroke-width:0;}#mermaid-svg-CNfbfpATI5BVcP9H .icon-shape,#mermaid-svg-CNfbfpATI5BVcP9H .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CNfbfpATI5BVcP9H .icon-shape p,#mermaid-svg-CNfbfpATI5BVcP9H .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CNfbfpATI5BVcP9H .icon-shape .label rect,#mermaid-svg-CNfbfpATI5BVcP9H .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CNfbfpATI5BVcP9H .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CNfbfpATI5BVcP9H .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CNfbfpATI5BVcP9H :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    从源头裁剪越权能力

    即使装配遗漏仍拒绝危险调用

    用户请求

    装配期静态治理技能底座

    候选技能元集合

    模型决策

    运行期动态治理工具底座

    沙箱执行

    六、核心差异:资产管理平台和安全运行引擎

    维度技能底座工具底座
    治理对象 一个能力包,可包含多个脚本和多个函数入口 单次函数调用,一个业务函数对应一个 FunctionTool
    生命周期 长期资产管理,覆盖下载、入库、更新、分发、删除 单次 Agent 会话,工具实例只驻留内存
    面向主体 大模型,提供能力描述,决定“模型知不知道调什么” 本地 Runtime,提供函数执行,决定“系统能不能安全执行”
    扩展形态 从 MinIO 拉取技能包,热加载刷新 启动时静态注册 + 运行期动态注册

    只有工具底座、没有技能底座时,虽然仍可以跑工具调用,但 Schema、描述都需要硬编码,无法做市场拉取、多语言变体和父子 Agent 权限裁剪,新增能力要改代码重启。只有技能底座、没有工具底座时,系统只有一堆 SKILL.md 文档,模型只能看能力描述,没有实际执行能力。

    集群场景下,AgentTeams Manager 把技能包投影到 MinIO,属于技能底座集群侧分发逻辑;Worker 收到通知后,本地技能底座完成更新,再向下通知本地工具底座做动态注册。集群分发是技能底座的延伸,不是工具底座的职责。

    七、总结

    工具底座解决的是“函数能不能安全跑起来”,技能底座解决的是“能力能不能被模型识别并按需分发”。前者是 Runtime 执行层,负责注册、查找、注入、校验和沙箱执行;后者是资产管理层,负责技能包入库、版本管理、多租户筛选和提示词注入。

    两层底座通过“函数引用 + Schema + SKILL.md”单向衔接。技能底座保存元数据,不持有运行时对象;工具底座在 Agent 装配阶段才把元数据实例化为治理过的工具实例。装配期允许某个能力进入候选集合,并不等于运行时一定放行,这正是双层纵深防御的意义。

    对工程实践来说,最重要的是守住语义边界:技能文档只给模型看,业务代码只给运行时执行;manifest 只持久化元信息,不序列化运行时对象;技能版本变更时,描述与脚本必须同步演进。守住这些边界,能力才能做到可分发、可治理、可热加载,同时不会让一个普通函数变成系统里的裸奔入口。

    赞(0)
    未经允许不得转载:171主机测评 » Agent架构:QwenPaw之Skill技能底座与Tool工具底座
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址