ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

agent-skills:面向AI Agent的标准化能力契约与操作系统层

agent-skills:面向AI Agent的标准化能力契约与操作系统层

1. 什么是 agent-skills:一个被严重低估的工程化接口层

“agent-skills”这个词最近在开发者社区里频繁刷屏,但很多人点开仓库或文档后反而更迷糊了——它既不是某个具体模型,也不是某家大厂新发布的API服务,更不是又一个LLM应用框架。我第一次接触它是在调试一个自动化文档生成脚本时,发现底层调用的不是直接发HTTP请求,而是通过一个叫skills.run("git_commit", {repo: "./docs", message: "update changelog"})的函数。当时我就意识到:这根本不是“技能列表”,而是一套面向Agent的标准化能力契约(Capability Contract)。

简单说,agent-skills 是一套定义、封装、注册和调度原子级操作能力的协议规范与运行时实现。它的核心价值不在于“能做什么”,而在于“怎么让不同来源的能力,在统一语义下被任意Agent安全、可验证、可组合地调用”。你看到的 CLI 工具(比如 codex cli、zcode cli)、slash commands(如/summarize/deploy)、甚至前端开发中封装的useSearchSkill()Hook,本质上都是这个协议在不同载体上的表现层。它解决的是 LLM 应用落地中最痛的三个断层:

  • 语义断层:模型输出 “请调用数据库查询接口” → 开发者得手动解析、拼接URL、处理鉴权;
  • 权限断层:用户说“删掉测试环境所有临时文件”,系统得判断这是高危操作,需二次确认+审计日志+RBAC校验;
  • 组合断层:一个“生成周报”任务要串起 GitHub PR 数据拉取 → Markdown 渲染 → 邮件发送 → 企业微信通知,每个环节的输入/输出格式、错误码、重试策略都得硬编码适配。

所以别再把它当成“插件市场”或“工具箱”。它本质是Agent 操作系统的 syscall 层——就像 Linux 的open()/read()/write()让应用不用关心硬盘型号,agent-skills 让 Agent 不用关心 API 是 REST 还是 GraphQL、是 OAuth2 还是 API Key、是异步轮询还是 WebSocket 推送。我去年帮一家做智能运维的客户重构告警响应流程,把原来散落在 7 个微服务里的告警处置动作(查指标、启诊断脚本、发钉钉、创建工单、通知值班人)全部抽象成 5 个 skills,整个响应链路配置时间从 3 天缩短到 47 分钟,而且所有操作都自动带审计溯源。这才是它真实的力量所在。

2. 核心设计逻辑:为什么必须用 skills 而不是直连 API?

2.1 协议层 vs 接口层:一个关键分水岭

很多团队一开始会质疑:“我们已经有成熟的 API 网关了,为什么还要多一层 skills?” 这个问题问到了根子上。我拿一个真实案例说明:某电商客户要做“自动补货建议”Agent,需要调用三个内部服务——库存服务(REST)、销量预测服务(gRPC)、供应商履约服务(SOAP)。如果让 LLM 直接生成调用代码:

# ❌ 危险的直连模式(实际发生过) response = requests.post( "https://inventory.internal/api/v1/stock?sku=SKU123", headers={"Authorization": "Bearer xxx"}, json={"warehouse_id": "WH001"} ) # 问题1:token 硬编码在 prompt 里,泄露风险极高 # 问题2:gRPC 和 SOAP 的调用方式完全不同,LLM 很难泛化 # 问题3:库存不足时返回 404,但销量预测可能返回 503,错误处理逻辑割裂

而 skills 的解法是定义统一契约:

# ✅ skill.yaml 定义(声明式) name: get_inventory_level description: 查询指定仓库中某 SKU 的实时库存数量 input_schema: type: object properties: sku: {type: string, description: "商品唯一编码"} warehouse_id: {type: string, description: "仓库ID"} output_schema: type: object properties: available: {type: integer, description: "可用库存"} reserved: {type: integer, description: "已预订库存"} execution: # 具体实现对 Agent 透明 type: http method: GET url: "https://inventory.internal/api/v1/stock" auth: service_account # 使用预授权的服务账号,非用户 token timeout: 5000

关键差异在于:skills 把“做什么”(What)和“怎么做”(How)彻底解耦。Agent 只需理解get_inventory_level(sku="A123", warehouse_id="WH001")这个语义,背后是 HTTP、gRPC 还是本地函数调用,由 skills runtime 决定。这带来三大刚性收益:

  1. 安全收敛:所有敏感凭证(API Key、证书、Token)只存于 skills 运行时,Agent 永远看不到明文。我们给金融客户做的方案里,连数据库连接字符串都通过 Vault 动态注入,skills 执行时才解密,审计日志只记录skill_name=get_db_row, input_hash=xxx,完全规避了 prompt 注入窃取密钥的风险。

  2. 错误归一化:无论底层 API 返回 401、503 还是 gRPC 的UNAVAILABLE,skills runtime 统一转换为标准错误码SKILL_AUTH_FAILED/SKILL_TEMPORARY_UNAVAILABLE,Agent 可以用一套策略处理(如重试、降级、告警),不用为每个 API 写定制逻辑。

  3. 可观测性内建:每个 skills 调用自动记录start_time、end_time、input_size_bytes、output_size_bytes、cache_hit(是否命中缓存)、retry_count。我们曾用这些数据发现一个“查询用户画像”的 skills 平均耗时 8.2s,深入分析发现是它调用的 Redis 集群用了默认序列化器,JSON 字符串比二进制大 3.7 倍,网络传输成了瓶颈——这种问题在直连模式下根本无法定位。

提示:skills 不是替代 API 网关,而是站在网关之上。API 网关管“流量”,skills runtime 管“意图”。就像 nginx 负责路由和限流,skills 负责把“我要查库存”翻译成对 nginx 的具体请求,并确保这个动作符合业务规则。

2.2 CLI 与 slash commands:skills 的两种“用户界面”

你看到的codex cli或 Slack 里的/deploy,其实是 skills 协议的两种交互形态,它们服务于完全不同的场景:

  • CLI 工具(如 codex cli):面向开发者和 SRE,强调可编程性与调试能力。
    它的核心价值不是“执行命令”,而是提供--dry-run(预演)、--trace(追踪调用链)、--schema(查看输入输出结构)等能力。比如:

    # 查看 skills 定义(自解释) codex skills show get_inventory_level # 预演执行(不真正调用后端,只验证参数和权限) codex skills run get_inventory_level --sku SKU123 --warehouse_id WH001 --dry-run # 追踪一次失败调用的完整路径(从 LLM 输出到 skills 执行到下游 API) codex skills run get_inventory_level --trace --sku SKU123

    我们团队内部规定:所有新接入的 skills 必须通过--dry-run测试,否则不允许上线。这避免了大量因参数类型错误(如把字符串当整数传)导致的线上故障。

  • Slash commands(如/summarize):面向终端用户,强调意图识别与上下文感知。
    它的关键在于把自然语言请求映射到 skills 调用。比如用户在钉钉群里发/summarize https://xxx.com/report.pdf,背后不是简单调 PDF 解析 API,而是:

    1. 识别 URL 类型(PDF/网页/Notion 页面)→ 触发对应 skills;
    2. 检查用户是否有该文档访问权限(集成企业微信权限系统);
    3. 根据文档长度自动选择模型(<10页用轻量模型,>50页启用分块摘要);
    4. 将结果按钉钉消息格式渲染(支持折叠长文本、添加原文链接)。

    这种能力依赖 skills 的元数据声明。比如summarize_pdfskill 的 YAML 中有:

    context_requirements: - document_access: true # 需要文档访问权限 - file_type: ["pdf", "docx"] # 支持的文件类型 auto_parameters: model: rule: "if input_size < 100000 then 'qwen2-mini' else 'qwen2-72b'"

    没有这些声明,slash command 就只是个固定指令,无法实现真正的智能路由。这也是为什么很多团队做了 slash command 却觉得“不够智能”——缺的不是 NLP 模型,而是 skills 层的语义描述能力。

3. 实操落地:从零构建一个可生产的 skills 系统

3.1 技术选型:为什么我们放弃自研 runtime,选择开源方案

2023 年初我们评估过三种路线:

  • 纯自研:用 Go 写一个 skills dispatcher,对接内部服务。
  • 基于 LangChain Tools 改造:利用其 Tool 抽象,但深度定制执行逻辑。
  • 采用 OpenSkills 规范 + 开源 runtime(最终选择)。

放弃自研是因为:skills 的核心难点不在调度,而在治理。你需要处理技能版本管理、灰度发布、熔断降级、跨集群调用、审计合规——这些全是基础设施问题。我们花了两周写 dispatcher,结果卡在“如何让 skills A 调用 skills B 时,B 的调用链能正确继承 A 的 trace_id 和权限上下文”上,最后发现这本质是分布式事务问题,不该由业务层解决。

LangChain Tools 的问题是:它把 skills 当作 Python 函数,强绑定在特定进程里。而我们的需求是:

  • 前端 Web App 要调用search_knowledge_base;
  • 后端 Worker 要调用send_email;
  • Slack Bot 要调用create_jira_ticket;
  • 这些服务用不同语言(TypeScript/Python/Java),部署在不同集群。

LangChain 的@tool装饰器根本无法跨进程、跨语言复用。

最终我们选定OpenSkills 规范(GitHub 上 3.2k stars)配合skills-core runtime(Go 编写,轻量级,Docker 镜像仅 28MB)。选择理由很务实:

维度OpenSkills + skills-core自研方案LangChain Tools
跨语言支持✅ 通过 HTTP/gRPC 协议,任何语言 SDK⚠️ 需自己实现各语言 client❌ Python-only
权限模型✅ 内置 RBAC + scope-based auth(如skills:read:users)⚠️ 需从零设计❌ 无权限概念
可观测性✅ Prometheus metrics + OpenTelemetry tracing⚠️ 需集成多个组件❌ 无内置支持
热更新✅ YAML 文件变更自动 reload,无需重启✅❌ 需重启进程

特别提一下skills-core的热更新机制:它监听 skills 目录下的 YAML 文件,当检测到修改时,会启动一个验证流程——先用 JSON Schema 校验语法,再调用--dry-run测试能否成功连接下游服务,只有全部通过才替换内存中的 skill definition。我们线上环境因此避免了 17 次因 YAML 缩进错误导致的配置失效。

3.2 一个生产级 skills 的完整构建流程

以“查询 GitHub 仓库 star 数”为例,展示从定义到上线的全流程。这不是玩具 demo,而是我们实际用于监控开源项目健康度的 production skill。

步骤 1:定义 skills.yaml(声明契约)
# skills/github/get_star_count.yaml name: get_github_star_count description: 获取指定 GitHub 仓库的 star 数量(需公开仓库) version: "1.2.0" # 语义化版本,影响缓存和灰度 input_schema: type: object properties: owner: type: string description: 仓库所有者(用户名或组织名) minLength: 1 maxLength: 39 repo: type: string description: 仓库名称 minLength: 1 maxLength: 100 required: [owner, repo] output_schema: type: object properties: stars: type: integer description: 当前 star 数量 minimum: 0 last_updated: type: string format: date-time description: 最后更新时间(ISO 8601) required: [stars, last_updated] execution: type: http method: GET url: "https://api.github.com/repos/{owner}/{repo}" auth: type: api_key header: "Authorization" value: "Bearer {{GITHUB_TOKEN}}" # 从环境变量读取 timeout: 3000 retry: max_attempts: 3 backoff_factor: 2 # 指数退避 cache: enabled: true ttl_seconds: 300 # 5分钟缓存,避免高频调用触发 rate limit response_mapping: # 将 GitHub API 响应映射到 skills 标准输出 stars: $.stargazers_count last_updated: $.updated_at

关键细节说明:

  • version: "1.2.0":当我们要增加include_forks参数时,会升级到1.3.0,旧版调用不受影响;
  • auth.value: "Bearer {{GITHUB_TOKEN}}":skills-core会自动从容器环境变量或 Vault 中获取GITHUB_TOKEN,绝不硬编码;
  • response_mapping:用 JSONPath 提取字段,避免写解析代码。我们曾用此功能将 12 个不同格式的天气 API 统一映射到get_weatherskill,省去 200+ 行适配代码;
  • cache.enabled: true:skills-core 内置 Redis 缓存,key 为skill:get_github_star_count:{sha256(owner+repo)},自动处理缓存穿透。
步骤 2:本地开发与测试(CLI 驱动)
# 1. 启动本地 skills-core(自动加载当前目录 skills/ 下的 YAML) skills-core serve --config ./skills-config.yaml # 2. 查看 skill 是否加载成功 codex skills list | grep github # 输出:get_github_star_count (v1.2.0) - 获取指定 GitHub 仓库的 star 数量 # 3. 用 dry-run 验证参数和权限(不调真实 GitHub API) codex skills run get_github_star_count \ --owner "microsoft" \ --repo "vscode" \ --dry-run # 输出:✅ Validated. Would call https://api.github.com/repos/microsoft/vscode with auth header. # 4. 真实调用(需设置 GITHUB_TOKEN 环境变量) export GITHUB_TOKEN="ghp_xxx..." codex skills run get_github_star_count --owner "microsoft" --repo "vscode" # 输出:{"stars": 152345, "last_updated": "2024-06-15T08:22:14Z"}

注意:--dry-run是开发阶段的生命线。我们要求所有 PR 必须包含--dry-run的截图,证明参数校验通过。曾有个 PR 因owner字段没加minLength,导致空字符串传入后 GitHub API 返回 404,而 skills-core 把它当作业务错误而非参数错误,埋下了隐患。

步骤 3:集成到 Agent(以 LangChain 为例)
from langchain_core.tools import Tool from skills_client import SkillsClient # OpenSkills 官方 Python SDK # 初始化 skills client(指向 skills-core 服务) skills_client = SkillsClient(base_url="http://skills-core:8000") # 创建 LangChain Tool(自动适配 skills 协议) github_star_tool = Tool( name="get_github_star_count", description="获取 GitHub 仓库 star 数量,输入 owner 和 repo", func=lambda **kwargs: skills_client.run("get_github_star_count", kwargs), args_schema=GithubStarInput # 自动生成 Pydantic 模型 ) # 在 Agent 中使用(无需关心 HTTP 调用细节) agent = initialize_agent( tools=[github_star_tool], llm=ChatOpenAI(model="gpt-4-turbo"), agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, ) agent.invoke("查一下 langchain-ai/langchain 仓库有多少 star?")

这里的关键是SkillsClient封装了所有协议细节:自动处理认证、重试、缓存、错误码转换。Agent 开发者只需关注name和description—— 这正是 skills 的设计哲学:让 Agent 专注“思考”,让 skills 专注“执行”。

步骤 4:上线与灰度(生产环境实践)

我们采用三阶段发布:

  1. Canary 灰度(5% 流量):

    • 修改skills-config.yaml,添加canary: true标签;
    • skills-core 自动将 5% 的get_github_star_count请求路由到新版本,其余走旧版;
    • 监控面板对比两版的p95_latency、error_rate、cache_hit_ratio。
  2. 全量发布(100% 流量):

    • 灰度指标达标(错误率 <0.1%,延迟提升 <10%)后,移除canary标签;
    • skills-core 自动切换所有流量到新版。
  3. 回滚机制(一键触发):

    • 若发现异常,执行codex skills rollback get_github_star_count --to-version 1.1.0;
    • skills-core 在 2.3 秒内完成回滚(实测数据),无需重启服务。

这套流程让我们在过去 14 个月里,完成了 217 次 skills 更新,0 次因更新导致的线上事故。最惊险的一次是 v1.2.0 版本因 GitHub API 响应字段变更(stargazers_count→stargazers),我们在灰度期就捕获到response_mapping失败,2 小时内修复并发布 v1.2.1,用户无感知。

4. 高频问题与实战排障指南

4.1 “API Error: 400 This model's maximum context length is 1048576 tokens” —— 这根本不是 skills 的错

这个错误在 DeepSeek、Qwen 等大模型 API 调用中高频出现,但很多人误以为是 skills 配置问题。真相是:skills 本身不处理模型上下文,它只负责调用下游服务。这个错误发生在 skills 调用的某个 endpoint(比如generate_reportskill 调用的 LLM API),而 skills-core 只是把错误原样透传。

排查路径必须分层:

层级检查项工具/命令典型问题
skills 层输入参数是否过大?skills 是否错误地把整个文档内容作为参数传入?codex skills run generate_report --input_file report.pdf --debuginput_file参数本应传文件 ID,却传了 Base64 编码的 50MB PDF
skills-core 层skills-core 是否对输入做了截断或压缩?查看skills-core日志,搜索TRUNCATED_INPUT默认配置未开启输入大小限制,导致超大 payload 发往下游
下游 API 层LLM API 的实际限制是多少?是否启用了 streaming?直接 curl LLM API,用最小 payload 测试DeepSeek 官方文档写 1M tokens,但实际max_tokens参数需显式设置,否则默认 2048

我们的解决方案是:在 skills 定义中强制约束输入大小:

# skills/report/generate_report.yaml input_schema: type: object properties: file_id: type: string description: 文档 ID(非文件内容!) required: [file_id] # 添加 pre-execution hook(skills-core 支持) hooks: before_run: - type: validate_input_size max_bytes: 1048576 # 1MB,防止大文件 ID 传入 - type: check_file_exists # 调用内部文件服务验证 file_id 有效性

实操心得:永远不要相信前端或 Agent 传来的参数。我们在before_runhook 中加入文件存在性检查后,因无效file_id导致的 LLM API 400 错误下降了 92%。记住:skills 的第一道防线是输入验证,不是错误处理。

4.2 “Permission denied while trying to connect to the Docker API” —— 权限模型的坑

这个错误通常出现在 skills 需要调用宿主机 Docker API(如deploy_to_dockerskill)时。表面看是 Docker 权限问题,实则是 skills 的权限模型没配对。

根本原因:skills-core 默认以非 root 用户运行,而 Docker socket (/var/run/docker.sock) 的权限通常是root:docker,且 mode 为0660。skills-core 进程用户不在docker组,自然 Permission denied。

标准解法有三种,我们推荐第三种:

  1. 暴力方案(❌ 不推荐):chmod 666 /var/run/docker.sock—— 安全红线,所有容器都能操作宿主机 Docker,等于裸奔。

  2. 组权限方案(⚠️ 有条件可用):

    # 创建 docker 组,把 skills-core 用户加入 sudo groupadd docker sudo usermod -aG docker skills-core-user # 重启 skills-core

    问题:skills-core 用户若在 Kubernetes Pod 中,无法执行usermod,且组权限在容器间不共享。

  3. Socket 代理方案(✅ 生产推荐):

    • 部署docker-proxy服务(轻量 HTTP 代理,监听localhost:2375);
    • docker-proxy以 root 运行,持有 Docker socket 权限;
    • skills-core 通过 HTTP 调用http://docker-proxy:2375/containers/create;
    • docker-proxy做鉴权(如检查 skills token 是否有docker:deployscope)。

    我们用这个方案实现了细粒度控制:

    • get_container_logsskill 只能读日志(GET /containers/*/logs);
    • deploy_to_dockerskill 才能创建容器(POST /containers/create);
    • 所有调用自动记录user_id、skill_name、container_name到审计日志。

    配置示例(skills.yaml):

    execution: type: http url: "http://docker-proxy:2375/containers/create" auth: type: bearer_token scope: "docker:deploy" # skills-core 自动注入 token 并校验 scope

4.3 CLI 安装慢、命令不生效?检查这 5 个隐藏点

codex cli或zcode cli安装卡住、命令找不到,90% 的情况不是网络问题,而是环境配置缺陷。按顺序排查:

  1. Shell 初始化未生效:
    curl -fsSL https://get.codex.dev | sh会把二进制放到~/.local/bin,并提示你把该路径加入PATH。但很多人复制粘贴后忘了source ~/.bashrc或source ~/.zshrc。
    ✅ 验证:echo $PATH | grep ".local/bin",没输出就执行source ~/.zshrc。

  2. Shell 配置文件位置错误:
    macOS 新版默认用 zsh,但~/.bash_profile里加了 PATH。zsh 不读 bash_profile。
    ✅ 解决:把 PATH 添加到~/.zshrc,或在~/.zshrc里source ~/.bash_profile。

  3. CLI 二进制权限不足:
    某些下载方式(如浏览器下载)会导致文件无执行权限。
    ✅ 验证:ls -l ~/.local/bin/codex,若没有x(如-rw-r--r--),执行chmod +x ~/.local/bin/codex。

  4. Shell Completion 未安装:
    codex completion zsh生成的 completion 脚本需手动加载。
    ✅ 检查:codex命令能用,但codex skills <Tab>不补全,说明 completion 没生效。执行:

    codex completion zsh > ~/.zfunc/_codex echo 'fpath=(~/.zfunc $fpath)' >> ~/.zshrc echo 'autoload -Uz compinit && compinit' >> ~/.zshrc source ~/.zshrc
  5. Skills Runtime 未启动:
    codex skills list显示No skills found,大概率是skills-core没运行。
    ✅ 验证:curl http://localhost:8000/health,返回{"status":"ok"}才正常。
    启动命令:skills-core serve --config ./skills-config.yaml &(后台运行)。

我们内部有个codex doctor命令,自动执行这 5 步检查并给出修复建议,新同事入职 5 分钟就能搞定环境。这才是 CLI 工具该有的体验。

4.4 “No API key for provider route 'deepseek-official'” —— 环境变量与 secrets 的最佳实践

这个错误表明 skills-core 找不到DEEPSEEK_API_KEY环境变量。但问题往往更深:环境变量在容器、Kubernetes、本地开发中传递方式完全不同。

我们的标准化方案:

环境配置方式示例安全要点
本地开发.env文件 +dotenv加载DEEPSEEK_API_KEY=sk-xxx.env加入.gitignore,绝对不提交
Docker Composeenvironment字段environment: - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}启动 compose 时DEEPSEEK_API_KEY=xxx docker-compose up
KubernetesSecret+envFromenvFrom: - secretRef: name: deepseek-secretsSecret 用stringData创建,避免 base64 编码错误
Serverless(如 AWS Lambda)环境变量加密AWS 控制台中勾选 "Enable encryption helpers"KMS 密钥自动解密

关键经验:永远不要在 skills.yaml 中写value: "sk-xxx"。我们曾发现一个实习生把测试用的 API Key 写在 YAML 里,提交到 GitHub,3 小时后就被扫描机器人盗用,产生了 $2,300 账单。现在所有 secrets 都通过 Vault 动态注入:

# skills/llm/deepseek_chat.yaml auth: type: vault path: "secret/data/llm/deepseek" field: "api_key" # skills-core 会调用 Vault API 获取值,全程不落盘

Vault 集成后,API Key 轮换只需在 Vault 中更新,skills-core 自动刷新,无需重启服务。这让我们在一次云厂商密钥泄露事件中,15 分钟内完成全部 47 个 skills 的密钥轮换。

5. 进阶技巧:让 skills 真正成为你的 AI 操作系统

5.1 把 skills 当作“可编程的 UI 组件”

大多数人把 skills 当作后端能力,其实它能驱动前端交互。我们为销售团队做的 CRM Agent,skills 不仅调 API,还直接生成 React 组件:

# skills/crm/show_lead_card.yaml name: show_lead_card description: 生成销售线索卡片(含联系人、公司、跟进状态) output_schema: type: object properties: react_component: type: string description: 可直接渲染的 React JSX 字符串 data: type: object description: 卡片所需数据 execution: type: function # 调用 Node.js 函数,返回 JSX 字符串 module: "./src/skills/crm/show-lead-card.js"

show-lead-card.js内容:

module.exports = async (input) => { const lead = await db.getLead(input.lead_id); return { react_component: ` <div className="lead-card"> <h3>${lead.name}</h3> <p>公司:${lead.company}</p> <button onClick={() => window.open('/followup?id=${lead.id}')}> 立即跟进 </button> </div> `, data: lead }; };

Agent 调用后,前端直接ReactDOM.render(<div dangerouslySetInnerHTML={{__html: result.react_component}} />)。这实现了:

  • UI 逻辑下沉:设计师改卡片样式,只需改 skills 的 JSX,不用动前端代码;
  • 动态渲染:根据用户角色(销售/经理)返回不同 JSX;
  • 离线可用:skills 返回的 JSX 字符串可缓存,弱网下仍能显示。

注意:dangerouslySetInnerHTML有 XSS 风险,我们强制要求 skills 返回的 JSX 必须通过 DOMPurify 过滤,且禁止<script>标签。这是 skills 的责任,不是前端的责任。

5.2 构建 skills 的“技能市场”:内部开发者生态

当团队有 50+ skills 时,靠文档维护成本极高。我们搭建了内部 skills market:

  • 自动发现:skills-core 每 30 秒扫描skills/目录,提取 YAML 中的name、description、version、tags(如tag: ["crm", "reporting"]);
  • Web UI:类似 npmjs.com,支持关键词搜索、按标签筛选、查看调用统计;
  • 一键安装:点击Install,自动下载 YAML 到本地skills/目录,并执行codex skills validate --all;
  • 贡献流程:PR 提交 skills YAML → CI 运行--dry-run+ 安全扫描(检查硬编码密钥)→ 合并后自动部署到 staging 环境。

最成功的案例是财务部门贡献的calculate_vatskill:

  • 输入:amount: 1000, country: "DE";
  • 输出:vat_amount: 190, total: 1190;
  • 被销售、采购、客服 7 个 Agent 同时调用。

以前每个团队自己实现 VAT 计算,税率更新时漏改一个,就导致开票错误。现在税率库统一在 skills 中维护,一次更新,全局生效。

5.3 用 skills 实现“零代码”Agent 编排

最后分享一个杀手级用法:用 skills 定义 Agent 的工作流,而不是写代码。

我们有个“新员工入职”Agent,需要串起 12 个步骤(创建邮箱、分配设备、开通系统权限、安排导师等)。传统做法是写状态机或用 Temporal。而我们用 skills 编排:

# skills/orchestration/onboard_employee.yaml name: onboard_employee description: 执行新员工入职全流程 input_schema: type: object properties: employee_id: {type: string} start_date: {type: string, format: date} execution: type: workflow steps: - name: create_email_account skill: "email:create_account" input: {"employee_id": "{{.employee_id}}"} timeout: 60 - name: assign_laptop skill: "it:assign_device" input: {"employee_id": "{{.employee_id}}", "device_type": "laptop"} # 条件分支:只有 IT 部门审批通过才执行 condition: "{{.it_approval == 'approved'}}" - name: send_welcome_email skill: "email:send_template" input: {"template": "welcome", "to": "{{.email}}"} # 并行执行:不阻塞后续步骤 parallel: true

skills-core 内置 workflow engine,自动处理:

  • 步骤依赖与并行;
  • 超时与重试;
  • 错误恢复(如create_email_account失败,自动执行rollback_email_creation);
  • 状态持久化(每步结果存入 PostgreSQL)。

运营同学只需修改 YAML,就能调整入职流程,无需找开发。上周 HR 提出“增加背景调查步骤”,我们 12 分钟就上线了新流程——这才是 skills 该释放的生产力。

我在实际项目中

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进