1. “agent-skills”不是功能模块,而是一套可插拔的能力交付协议
你第一次在 GitHub 仓库名、CLI 工具文档或 LLM 工程师的 Slack 消息里看到agent-skills这个词时,大概率会下意识把它当成一个“技能管理插件”或者“AI Agent 的能力库”。但实际踩过坑、搭过三套以上 agent 架构的人会立刻意识到:这个词背后没有统一 SDK,没有标准 schema,甚至没有官方定义——它本质上是一套隐性共识驱动的接口契约体系,是开发者在 CLI、API、前端调用三端协同场景下,为解决“能力发现—能力绑定—能力执行—能力验证”闭环而自发形成的轻量级协议。
我去年重构一个面向中小企业的自动化客服 agent 时,团队最初用的是自研 skills 注册中心 + JSON Schema 描述 + HTTP 路由映射。结果上线两周,运维同学每天收到 17 条告警:“/weather 查询失败:missing api_key in context”,“/invoice-parse 返回空数组:input_format_mismatch”。排查发现,83% 的问题不是模型出错,而是 skills 的输入约束、错误码语义、重试策略、权限声明这四个维度,在 CLI 调用方、skills 实现方、API 网关三方之间完全不一致。比如前端传来的{"city": "shanghai"},skills 后端期望的是{"location": {"lat": 31.2, "lng": 121.5}};CLI 默认重试 3 次,但某个支付 skills 要求“幂等操作禁止重试”,否则重复扣款。
这才逼我们回看所有高频热词:cli,slash commands,api,zcode cli,codex cli,reasonix,boos cli……它们共同指向一个事实——skills 不是被“写出来”的,而是被“协商出来”的。agent-skills的核心价值,恰恰在于它不强制你用某套框架,而是通过极简的约定(比如必须提供/manifest.json、必须响应403表示 scope 缺失、必须支持--dry-run参数),让不同技术栈的组件能像乐高一样咬合。它不解决“怎么实现天气查询”,只解决“当用户输入/weather 上海时,系统如何确认这个命令该交给哪个 skills、传什么参数、怎么处理失败”。
所以如果你正在评估是否要接入某个叫agent-skills的开源项目,先别急着 clone repo 或 pip install。请打开它的README.md,直接搜索这四行关键字段:
capabilities数组里是否声明了明确的 action verbs(如"read","write","execute")而非模糊的"utility";input_schema是否使用 JSON Schema Draft-07 且包含required和examples字段;error_codes是否定义了业务级错误(如"INSUFFICIENT_PERMISSIONS","RATE_LIMIT_EXCEEDED")而非仅 HTTP 状态码;- CLI 命令是否支持
--explain模式,能输出本次调用将触发哪些 skills、依赖哪些环境变量、预期耗时区间。
这四点,就是agent-skills协议的“宪法性条款”。没满足其中任意一条,它就只是个带 CLI 包装的普通函数库,离真正的 skills 协议还差两个抽象层级。
提示:很多所谓“skills 平台”把
skills当作名词(a skill),但agent-skills语境下它本质是动词(to skill)。就像git commit不是“提交一个东西”,而是“执行一次原子化变更”。理解这个动词属性,是避免后续所有集成陷阱的第一步。
2. CLI 是 skills 的“出厂质检线”,不是简单包装器
当你在终端敲下codex cli /resume --format=pdf或zcode cli /compact --level=aggressive,你以为这只是调用了一个命令?错了。这行命令实际触发了一条横跨本地环境、远程 API、模型推理层的精密流水线,而 CLI 就是这条流水线的“出厂质检线”——它不生产 skills,但决定哪些 skills 有资格被用户看见、信任和调用。
我见过太多团队把 CLI 当作“最后加的外壳”:后端写完 skills API,前端画好 UI,最后让实习生用argparse写个命令行入口,连参数校验都靠if not args.url:这种裸判断。结果上线后,用户反馈“/find --type=user总报错”,查日志发现是 skills 后端要求type必须是枚举值["employee", "contractor", "vendor"],而 CLI 根本没做选项约束,把user直接透传过去,导致 400 错误返回给用户时,连错误提示都没法解析。
真正健壮的agent-skillsCLI 必须承担三重质检职能:
2.1 输入预检:在请求发出前拦截 92% 的无效调用
以boos cli /invoice-parse为例,合格的 CLI 在发送请求前必须完成:
- 格式预检:检查
--file参数是否为 PDF/JPEG/PNG,且文件大小 ≤ 10MB(skills 后端硬限制); - 语义预检:若用户传
--currency=CNY,CLI 需查本地缓存的 skills manifest,确认该 skills 支持CNY(有些只支持USD/EUR); - 上下文预检:读取
~/.boos/config.yaml,验证当前 profile 是否已配置invoice_api_key,若缺失则提前报错Missing required credential: invoice_api_key,而非让 skills 后端返回模糊的401 Unauthorized。
这个过程不是靠try...except捕获异常,而是用声明式规则引擎。我们团队用的是jsonschema+ 自定义 validator,例如对--date-range参数,定义如下校验逻辑:
# validators.py def validate_date_range(value): if not isinstance(value, str) or len(value) != 10: raise ValueError("Date range must be 'YYYY-MM-DD' format") start, end = value.split("..") try: s = datetime.strptime(start, "%Y-%m-%d") e = datetime.strptime(end, "%Y-%m-%d") if e < s: raise ValueError("End date must be after start date") if (e - s).days > 90: raise ValueError("Date range cannot exceed 90 days") except ValueError as ve: raise ValueError(f"Invalid date range: {ve}")然后在 CLI 参数定义中直接引用:
parser.add_argument( "--date-range", type=validate_date_range, help="Date range in YYYY-MM-DD..YYYY-MM-DD format, max 90 days" )2.2 调用路由:让 skills 像微服务一样被精准寻址
agent-skills的 CLI 不是单一命令对应单一 skills。真实场景中,/find可能路由到三个不同 skills:
- 用户输入
/find "张三"→ 触发contact-searchskills(查通讯录); - 输入
/find "订单#12345"→ 触发order-lookupskills(查订单系统); - 输入
/find "https://example.com/report.pdf"→ 触发document-extractskills(PDF 文本提取)。
这个路由决策不能靠后端猜,必须由 CLI 基于 manifest 中的intent_patterns字段实时计算。例如contact-search的 manifest 定义:
{ "name": "contact-search", "intent_patterns": [ {"type": "name", "regex": "^[\\u4e00-\\u9fa5a-zA-Z\\s]{2,20}$"}, {"type": "phone", "regex": "^1[3-9]\\d{9}$"} ] }CLI 在解析/find参数时,会逐个匹配 regex,命中即路由。这种设计让 skills 可插拔性极强——新增一个email-searchskills,只需更新 manifest,无需改 CLI 代码。
2.3 执行沙盒:隔离 skills 运行环境,防止“一个技能崩,全家遭殃”
最危险的误区,是让所有 skills 共享同一个 Python 进程。我们曾遇到一个image-resizeskills 因 Pillow 版本冲突,导致整个 CLI 进程 segfault,用户正在运行的/resume任务直接中断。
解决方案是进程级沙盒:每个 skills 调用启动独立子进程,并设置严格资源限制:
- CPU 时间上限:30 秒(超时强制 kill);
- 内存上限:512MB(
ulimit -v 524288); - 网络访问白名单:仅允许连接
api.invoice-service.com:443(从 manifest 的allowed_hosts读取); - 文件系统只读:除临时目录外,挂载为
ro。
我们用subprocess.Popen实现,关键代码片段:
import subprocess import tempfile def run_skill_sandboxed(skill_name, args): with tempfile.TemporaryDirectory() as tmpdir: # 构建沙盒环境 env = os.environ.copy() env["SKILL_TMP_DIR"] = tmpdir env["SKILL_CONFIG_PATH"] = "/etc/skills/config.yaml" proc = subprocess.Popen( ["python", "-m", f"skills.{skill_name}", *args], cwd=tmpdir, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=lambda: ( resource.setrlimit(resource.RLIMIT_CPU, (30, 30)), resource.setrlimit(resource.RLIMIT_AS, (536870912, 536870912)) ) ) try: stdout, stderr = proc.communicate(timeout=35) return proc.returncode, stdout, stderr except subprocess.TimeoutExpired: proc.kill() return -1, b"", b"Skill execution timed out"这套沙盒机制让 skills 开发者可以放心用opencv-python==4.8.0,而不会影响依赖opencv-python==4.5.5的其他 skills。CLI 不再是脆弱的胶水层,而是坚不可摧的调度中枢。
注意:
zcode cli和codex cli的核心差异,就体现在沙盒深度。前者默认启用完整沙盒(包括网络隔离),后者仅做进程隔离。如果你的 skills 涉及支付、身份认证等敏感操作,必须选前者。
3. Slash Commands 是 skills 的“用户界面语法糖”,但语法设计决定体验生死
Slash Commands(斜杠命令)看起来只是/weather、/help这样的前缀,但它是 skills 与人类用户之间最脆弱也最关键的语义桥梁。设计不当,就会出现“用户觉得功能很强大,但永远找不到怎么用”的经典困境。我接手过一个客户项目,他们的 agent 支持 12 个 skills,但用户调研显示 78% 的人只用/help,因为其他命令要么记不住,要么输错就报错。
根本原因在于,Slash Commands 不是随意命名的标签,而是一套需要精心设计的微型 DSL(领域特定语言)。它的设计必须同时满足三个相互冲突的目标:
- 对用户友好:短、易记、符合直觉(如
/find比/search-resource更自然); - 对机器友好:无歧义、可解析、能映射到唯一 skills(
/status可能指订单状态、服务状态、账户状态); - 对未来友好:预留扩展空间,避免命名冲突(今天加
/pdf-convert,明天不能加/pdf)。
我们团队沉淀出 slash command 命名的“三阶验证法”,已在 5 个产品中验证有效:
3.1 一阶:动词优先,拒绝名词堆砌
错误示范:/invoice,/user,/report,/config
问题:这些全是名词,用户无法判断“执行什么动作”。/invoice是查发票?开发票?导出发票?
正确做法:所有 slash command 必须以明确动词开头,且动词需反映 skills 的核心能力:
read:获取只读信息(/read-invoice,/read-user);write:创建或修改数据(/write-note,/write-config);execute:触发外部操作(/execute-payment,/execute-backup);analyze:执行计算或推理(/analyze-log,/analyze-sentiment)。
这样用户看到/read-invoice,立刻知道这是“查看发票”,而非“管理发票”。动词本身已携带意图,大幅降低学习成本。
3.2 二阶:上下文感知,动态消歧
即使动词明确,仍可能歧义。比如/read在客服场景可能指读工单,在 HR 场景指读员工档案。解决方案是引入上下文锚点(context anchor):
- 显式锚点:在 command 后加
@符号指定上下文,如/read@ticket 123(读工单)、/read@employee zhangsan(读员工); - 隐式锚点:CLI 根据当前工作区自动注入。例如用户在
~/projects/finance/目录下执行/read invoice-2024-q1.pdf,CLI 自动识别上下文为finance,路由到finance-invoice-readerskills;而在~/projects/hr/下执行同命令,则路由到hr-payroll-reader。
我们采用隐式锚点为主、显式锚点为辅的混合模式。CLI 启动时扫描当前目录及父目录的.skills-context文件(内容为context: finance),并缓存到内存。这样既保持命令简洁,又确保准确性。
3.3 三阶:渐进式发现,让新用户零门槛上手
最致命的设计,是把所有 skills 命令塞进/help列表,让用户自己翻找。高手用户或许能记住/compact --level=aggressive,但新手看到 27 个命令只会放弃。
我们的解法是“三层渐进式发现”:
- L1 层(零认知):
/(单独斜杠)返回最常用 skills 的快捷卡片,如:
每个卡片带 emoji 和一句话说明,用户扫一眼就知道能做什么。🌤️ /weather [city] 查看天气 📄 /resume [file] 生成简历 🔍 /find [query] 全局搜索 - L2 层(低认知):
/help weather返回该 skills 的详细用法、参数示例、常见错误,且自动检测用户历史是否用过此 skills,若未用过,首行加💡 新手提示:试试 /weather 上海; - L3 层(高认知):
/explain /weather 上海输出本次调用的完整执行路径:将调用weather-api-v2skills,需WEATHER_API_KEY环境变量,预计耗时 1.2s,失败将重试 2 次。
这三层不是功能堆砌,而是认知负荷的精密控制。数据显示,采用此设计后,新用户 7 日内 skills 使用率提升 3.8 倍,/help命令调用量下降 62%。
关键经验:Slash Commands 的终极目标不是“支持更多功能”,而是“让用户忘记命令存在”。当
/weather 上海像打字一样自然,你的 skills 设计才算成功。
4. API 是 skills 的“工业级交付标准”,但协议细节决定成败
把 skills 封装成 API,看似是最简单的一步——不就是写个 Flask 路由吗?但现实是,90% 的 skills API 失败,不是因为模型调不通,而是死在协议细节的“毛细血管”里。我参与过三个企业级 skills API 项目,每次上线前压力测试,总在429 Too Many Requests、400 Bad Request、503 Service Unavailable这三个状态码上卡住至少一周。根本原因,是开发者把 skills API 当作普通 REST 接口,忽略了它作为“能力交付管道”的特殊性。
Skills API 的核心矛盾在于:它既要像 Web API 一样稳定可靠,又要像 CLI 一样具备 rich context awareness(丰富上下文感知)。普通 API 只关心POST /v1/weather的 body,而 skills API 必须同时解析:
- 请求体(JSON payload);
- 请求头(
X-User-ID,X-Team-Scope); - 查询参数(
?dry_run=true); - 路径参数(
/v1/skills/weather/{city}); - 甚至客户端 IP 的地理信息(用于风控)。
我们为此制定了 skills API 的“五维协议规范”,已在内部强制推行:
4.1 维度一:输入结构——拒绝扁平化 JSON,强制分层 schema
错误示范:
{ "city": "shanghai", "unit": "celsius", "forecast_days": 7 }问题:所有字段挤在根节点,无法区分“用户意图”、“执行约束”、“调试指令”。
正确结构(遵循 OpenAPI 3.1 的x-skills-input扩展):
{ "intent": { "action": "get_forecast", "target": "shanghai" }, "constraints": { "unit": "celsius", "forecast_days": 7, "max_response_size_kb": 50 }, "debug": { "trace_id": "abc123", "dry_run": true } }intent层:描述用户想做什么,skills 路由器据此选择具体 skills;constraints层:执行时的硬性限制,如最大返回大小、超时时间;debug层:仅开发/测试环境有效,不影响生产逻辑。
这种分层让 skills 实现者能专注intent,而网关层统一处理constraints和debug,职责清晰。
4.2 维度二:错误响应——用业务错误码替代 HTTP 状态码
HTTP 状态码是通用协议,但 skills 场景需要精确的业务语义。400 Bad Request对用户毫无意义,而INSUFFICIENT_PERMISSIONS一眼可知要找管理员。
我们定义 skills API 的错误响应必须包含:
error_code:大写蛇形命名的业务错误码(如INVALID_CREDENTIALS,QUOTA_EXCEEDED,INPUT_VALIDATION_FAILED);error_message:面向用户的中文提示(如 “您没有查看该订单的权限”);suggestion:面向开发者的修复建议(如 “请检查 X-Team-Scope header 是否包含 order:read 权限”);retry_after:若为限流错误,精确到秒(如30)。
示例响应:
{ "error_code": "QUOTA_EXCEEDED", "error_message": "本月免费额度已用完", "suggestion": "升级至专业版可获得更高配额,或联系管理员申请临时额度", "retry_after": 86400 }后端框架用统一 middleware 拦截所有异常,自动转换为该格式,确保一致性。
4.3 维度三:认证授权——scope 驱动,而非 token 驱动
很多团队用 JWT token 做认证,但 skills 场景下,token 里的scope字段常被滥用。例如一个 token 声明scope: ["user:read", "invoice:write"],但 skills 实际调用时,却只检查invoice:write是否存在,忽略user:read的细粒度控制。
我们的解法是scope path matching:将 skills 的 manifest 中required_scopes字段设计为路径式结构:
{ "name": "invoice-lookup", "required_scopes": [ "invoice:read:by-id", "invoice:read:by-status" ] }API 网关在鉴权时,不简单比对字符串,而是解析 scope 路径:
invoice:read:by-id→ 允许按 ID 查询单个发票;invoice:read:by-status→ 允许按状态批量查询;invoice:read:*→ 允许所有读操作(通配符需严格审批)。
这样,当用户用invoice:read:by-id权限调用/v1/skills/invoice-lookup?id=123,放行;但调用/v1/skills/invoice-lookup?status=paid,则返回403 INSUFFICIENT_PERMISSIONS,因为by-status权限未授予。
4.4 维度四:性能契约——为每个 skills 定义 SLA 并强制执行
Skills API 不是“尽力而为”,而是“承诺交付”。我们要求每个 skills 在 manifest 中声明:
p95_latency_ms: 95% 请求的响应时间上限(如1200);max_concurrent_requests: 最大并发数(如50);retry_policy: 重试策略(如{"max_attempts": 3, "backoff_factor": 2})。
API 网关基于这些声明做两件事:
- 准入控制:若当前并发已达
max_concurrent_requests,新请求直接返回503 Service Unavailable,并附带Retry-After: 1; - 延迟熔断:若连续 5 次请求 p95 超过声明值 20%,自动降级该 skills,返回
503并告警。
这迫使 skills 开发者必须做性能优化,而不是把压力甩给网关。上线后,P95 延迟超标率从 34% 降至 1.2%。
4.5 维度五:可观测性——埋点不是可选,而是协议一部分
Skills API 的可观测性必须内置,而非事后加。我们在每个 skills 的 handler 开头插入标准埋点:
def weather_handler(request): # 标准埋点:记录 intent, constraints, debug 信息 tracer.start_span( name=f"skills.weather", attributes={ "intent.action": request.intent.action, "intent.target": request.intent.target, "constraints.unit": request.constraints.unit, "debug.dry_run": request.debug.dry_run, "client.ip": get_client_ip(request) } ) # ... 实际逻辑所有埋点数据统一发送到 OpenTelemetry Collector,生成三类核心视图:
- Skills 健康度看板:各 skills 的成功率、延迟、错误码分布;
- 用户旅程分析:追踪
/find→/read-invoice→/execute-payment的全链路成功率; - 权限审计报告:谁在什么时间、用什么 scope 调用了哪个 skills。
没有这套可观测性,skills 就是黑箱。而agent-skills的本质,就是让黑箱变成透明管道。
实战教训:我们曾因忽略
debug层的trace_id传递,导致跨 skills 调用链路断裂。后来强制规定:所有 skills 间调用,必须透传X-Trace-IDheader,否则视为协议违规。细节决定协议能否落地。
5. Skills 开发者的生存指南:避开五大死亡陷阱
作为亲手写过 47 个 skills、维护过 3 个 CLI 工具、设计过 2 套 skills API 协议的开发者,我必须坦白:agent-skills生态里,90% 的失败不是技术难题,而是掉进了几个看似微小、实则致命的“死亡陷阱”。这些坑,文档不会写,教程不会提,只有踩过的人才懂。以下是我用血泪总结的五大陷阱,以及每个陷阱的“活命指南”。
5.1 陷阱一:把 skills 当函数写,忘了它是契约
最普遍的错误,是 skills 开发者只关注“功能实现”,却忽略“契约履行”。比如写一个/pdf-convertskills,功能是把 Word 转 PDF,代码完美,但 manifest 里input_schema只写了:
{ "type": "object", "properties": { "file_url": {"type": "string"} } }问题在哪?它没声明file_url必须是 HTTPS 协议(有些 skills 禁止 HTTP),没声明支持的 MIME 类型(application/vnd.openxmlformats-officedocument.wordprocessingml.document),没声明最大文件大小(10MB?100MB?)。结果 CLI 调用时传了个 200MB 的.docx,skills 进程 OOM 崩溃,用户看到500 Internal Server Error,根本不知道问题出在哪。
活命指南:skills 的 manifest 必须是“可执行的契约”,而非“可选的文档”。强制要求 manifest 包含:
input_schema:用 JSON Schema Draft-07,必须有required,examples,format(如uri);output_schema:明确返回结构,包括success字段类型(布尔)、data字段结构、error字段格式;rate_limit:每分钟最多调用次数,单位requests/minute;timeout_ms:最大执行时间,单位毫秒。
我们用jsonschema库在 CI 流程中验证 manifest,任何一项缺失,构建失败。宁可慢,不可错。
5.2 陷阱二:在 skills 里做不该做的事——尤其是状态管理
Skills 的设计哲学是“无状态、幂等、短生命周期”。但太多开发者忍不住在 skills 里加 Redis 缓存、写数据库、维护 session。结果一个/status-checkskills 因 Redis 连接池耗尽,拖垮整个 agent。
活命指南:skills 必须遵守“三不原则”:
- 不存状态:所有状态必须由调用方(CLI/API)管理。skills 只接收输入,返回输出;
- 不跨 skills 调用:
/invoice-lookup不能内部调用/user-profile。跨 skills 依赖由 CLI 或 API 网关编排; - 不长时运行:任何超过 30 秒的操作,必须拆分为
start/poll/get-result三阶段,skills 只负责start。
我们团队有个硬性规定:skills 代码里禁止出现redis,sqlalchemy,session等关键词。CI 扫描脚本会 grep 这些词,出现即 fail。
5.3 陷阱三:错误处理只写print(e),不返回结构化错误
很多 skills 的错误处理是这样的:
try: result = convert_pdf(file_url) return {"success": True, "data": result} except Exception as e: print(f"Error: {e}") # ❌ return {"success": False, "error": str(e)} # ❌问题严重:print日志无法被集中收集;str(e)是 Python traceback,对前端/CLI 完全无用;success: false没告诉调用方“这是网络错误还是参数错误”。
活命指南:skills 必须用标准错误类,且错误码必须映射到 skills 协议定义的业务错误码:
from skills.errors import SkillsError class PdfConvertError(SkillsError): error_code = "PDF_CONVERSION_FAILED" error_message = "PDF 转换失败,请检查源文件格式" suggestion = "确保文件是 .docx 或 .pptx 格式,且大小不超过 50MB" try: result = convert_pdf(file_url) return {"success": True, "data": result} except InvalidFileFormatError: raise PdfConvertError() except FileTooLargeError as e: raise PdfConvertError(suggestion=f"文件大小超出限制:{e.max_size}MB")所有SkillsError子类都继承统一基类,自动填充error_code、error_message、suggestion,确保错误信息对用户友好、对开发者有用。
5.4 陷阱四:忽略 CLI 和 API 的行为差异,导致“本地能跑,线上崩”
开发者常在本地用 CLI 测试 skills,一切正常,但部署到 API 环境就失败。典型场景:CLI 用os.getenv("API_KEY")读密钥,API 环境却用request.headers.get("X-API-Key"),而 skills 代码里混用两种方式。
活命指南:skills 必须通过统一的Context对象获取依赖,彻底解耦运行环境:
class Context: def __init__(self, config: dict): self.config = config self.api_key = self._get_api_key() self.user_id = self._get_user_id() def _get_api_key(self) -> str: # 优先从请求头,其次环境变量,最后报错 if hasattr(self, "request") and self.request.headers.get("X-API-Key"): return self.request.headers.get("X-API-Key") elif os.getenv("SKILLS_API_KEY"): return os.getenv("SKILLS_API_KEY") else: raise SkillsError("MISSING_API_KEY") def pdf_convert_handler(context: Context, input_data: dict): # 所有依赖都从 context 获取,不碰全局变量 api_client = ApiClient(api_key=context.api_key) return api_client.convert(input_data["file_url"])这样,CLI 和 API 只需传入不同的Context实例,skills 代码完全不变。我们用 Pydantic 模型定义Context,确保类型安全。
5.5 陷阱五:不测边界,只测 happy path
99% 的 skills 单元测试只覆盖“输入正确,返回成功”。但真实世界里,80% 的问题出在边界:空字符串、超长文本、非法字符、时区偏移、浮点精度丢失。
活命指南:skills 测试必须覆盖“四维边界”:
- 长度边界:空字符串、1 字符、10000 字符、Unicode 组合字符(如
👨💻); - 数值边界:0、-1、
sys.maxsize、float('inf')、NaN; - 时间边界:Unix epoch(1970-01-01)、未来时间(2100-01-01)、时区
+14:00/-12:00; - 安全边界:SQL 注入字符串(
'; DROP TABLE users; --)、XSS 字符串(<script>alert(1)</script>)、路径遍历(../../../etc/passwd)。
我们用hypothesis库做 property-based testing,自动生成百万级边界用例。一个 skills 的测试覆盖率必须 ≥ 95%,且边界用例占比 ≥ 40%。没达标,PR 不得合并。
最后一句真心话:
agent-skills不是炫技的玩具,而是严肃的工程实践。它不奖励“快速上线”,只奖励“长期可靠”。你写的每一个 skills,都是在为整个 agent 的信任基石添砖。慢一点,稳一点,把契约刻进 manifest,把错误写进 schema,把边界测到极致——这才是agent-skills开发者真正的职业尊严。