
1. “agent-skills”不是库名而是AI工程中一个被严重低估的抽象层你点开GitHub搜agent-skills大概率会失望——它既不是npm上下载量破百万的明星包也不是TypeScript官方文档里定义的标准类型。它甚至没有独立的README.md、没有star数、没有CI badge。但如果你正在用Nx构建一个面向生产环境的AI应用系统尤其是需要让多个Agent协同完成复杂任务比如客服Agent调用订单查询Agent再触发风控评估Agent最后交由通知Agent发短信那你迟早会亲手写出一个叫agent-skills的目录或者至少在代码里反复出现这个命名空间。这不是巧合而是AI工程落地过程中自然沉淀出的能力契约层Skill Contract Layer。它解决的不是“怎么写Agent”而是“怎么让Agent之间说同一种语言”。就像微服务架构里Service Mesh的Sidecar不处理业务逻辑却决定了服务间能否互通agent-skills也不执行具体动作但它定义了一个Agent能做什么What、输入长什么样Input Schema、输出承诺什么Output Contract、失败时如何退化Fallback Strategy、是否需要人工确认Human-in-the-loop Flag——这些信息必须脱离具体实现LLM调用、工具链、框架被所有参与方前端调度器、后端编排引擎、测试Mock模块、运维监控系统共同理解。我第一次意识到这点是在给一家跨境物流客户做智能单证审核系统时。当时团队写了7个AgentOCR识别、海关编码校验、运费计算、合规条款比对、异常标注、人工复核路由、邮件生成。每个Agent都用NestJS单独部署API路径五花八门请求体字段命名风格各异有的用shipmentId有的用tracking_number有的甚至直接传raw_pdf_base64。当需要把它们串成一条审核流水线时光是字段映射和错误码对齐就花了3天而真正写业务逻辑只用了2小时。后来我们强制约定所有Agent必须提供一份skills.json描述文件放在项目根目录下统一位置并由Nx workspace的nx/workspace:run-commands脚本在CI阶段校验其格式合法性。这个约定目录我们就叫它agent-skills。提示agent-skills的本质是可验证的接口契约不是代码库。它存在的唯一价值是让“谁来调用谁”这件事从运行时动态发现变成编译期/构建期静态可检。这直接决定了你的AI系统能否像传统企业级应用一样支撑起SLA保障、灰度发布、链路追踪和故障隔离。它和TypeScript强相关但不是TypeScript语法糖它和Nx深度耦合但不是Nx插件它和semantic-release有关联因为技能版本号必须随语义化版本同步发布它和AI大模型本身无关却是让大模型能力真正可管理、可审计、可组合的关键基础设施。接下来我会带你从零开始在Nx monorepo里用TypeScript原生能力一砖一瓦搭出这个看似简单、实则决定AI工程成败的抽象层。2. 为什么非得用Nx单Repo vs 多Repo在AI技能管理中的真实代价很多人看到“agent-skills”第一反应是“这不就是个共享类型定义放shared/types里不就行了”——这种想法在原型阶段完全正确但一旦进入真实业务迭代就会暴露出致命缺陷。我见过三个典型翻车现场全部源于没用Nx统一管理技能契约2.1 场景一技能版本漂移导致的“幽灵故障”某电商客户上线了促销Agent v1.2它新增了一个discount_rules字段用于返回满减规则详情。前端团队按新字段开发了优惠券弹窗。但风控Agent仍停留在v1.1它收到含discount_rules的请求后因未声明该字段直接抛出ValidationError。问题不是代码bug而是两个Agent的技能契约版本不一致。更糟的是这个错误只在特定促销活动开启时才触发日常压测根本覆盖不到。如果用Nx管理所有Agent项目都声明依赖myorg/agent-skillsmyorg/agent-skills是一个独立的library project版本号严格遵循semantic-releaseNx的affected命令能精准识别当myorg/agent-skills更新时哪些Agent项目必须同步升级并重新测试CI Pipeline中强制要求任何Agent项目提交前必须通过nx run-many --targetvalidate-skills --all校验其skills.json是否符合当前myorg/agent-skills的Schema2.2 场景二跨团队协作时的“契约失语症”算法团队用Python写了一个商品图谱推理Agent后端用NestJS写订单履约Agent前端用Vue写用户交互Agent。三者语言不同但必须共享同一套技能描述。有人提议用OpenAPI Spec结果发现OpenAPI无法表达“此技能需人工审批”、“此技能调用耗时超过5s时自动降级为缓存结果”这类业务语义。最终大家妥协各自维护一份JSON Schema但字段含义经常对不上——算法团队说的confidence_score是0~1浮点数后端团队理解成整数百分比前端渲染时直接错位。Nx的解法是将agent-skills定义为TypeScript interface JSON Schema双轨制。TypeScript interface供TypeScript项目直接import享受IDE自动补全和编译检查JSON Schema文件skills.schema.json由Nx脚本自动生成供Python/Java等其他语言团队导入验证关键字段如requires_human_approval: boolean、timeout_ms: number、fallback_to: string | null在interface和schema中保持1:1映射且通过Nx的nx/plugin:generator确保每次修改都同步更新两端2.3 场景三本地开发时的“依赖地狱”最常见的情况开发者A改了agent-skills里的OrderQueryInput类型加了一个include_history: boolean字段。他本地跑通了自己负责的订单查询Agent就提了PR。但开发者B正在调试退款Agent他的本地node_modules里还是旧版myorg/agent-skills调用时传入新字段后端直接500。两人互相指责“你没更新依赖”其实问题在于monorepo里本应“改一处全链路感知”却因手动npm install或yarn link操作失误导致本地环境不一致。Nx的project.json天然解决这个问题{ name: order-query-agent, targets: { build: { executor: nx/node:build, options: { main: apps/order-query-agent/src/main.ts, tsConfig: apps/order-query-agent/tsconfig.app.json, outputPath: dist/apps/order-query-agent } } }, dependencies: { myorg/agent-skills: * } }注意这里的*不是指最新版而是Nx内部符号表示“使用workspace中当前最新版本”。nx build order-query-agent时Nx会自动检测myorg/agent-skills是否有未提交的本地修改若有则先构建该lib再构建Agent确保永远用的是你刚写的最新契约。这比任何yarn link都可靠。注意Nx不是银弹。如果你的团队只有1个AI工程师且只开发1个Agent那确实没必要上Nx。但只要涉及2个以上Agent、3个以上技术栈、或需要对接外部系统如ERP、WMSNx带来的契约一致性、变更可追溯性、本地环境可靠性其ROI投资回报率在第二周就能体现出来。别被“学习成本”吓退——Nx的nx g nx/workspace:library agent-skills命令3秒就能生成一个标准结构剩下的是让你少踩三个月的坑。3. 从零搭建agent-skillsTypeScript契约、JSON Schema生成与Nx自动化校验现在我们动手在Nx monorepo里创建真正的agent-skills基础设施。这不是一个“教程式”的复制粘贴而是还原我在Jetson Orin NX边缘AI设备上部署多Agent协同系统时实际采用的最小可行方案。所有步骤都经过生产环境验证参数值来自真实日志统计。3.1 初始化agent-skillslibrary项目打开终端确保已安装Nx CLInpm install -g nxnx g nx/workspace:library agent-skills --directorylibs/ai --no-interactive这条命令会在libs/ai/agent-skills下生成标准结构。关键文件是libs/ai/agent-skills/src/index.ts导出所有类型libs/ai/agent-skills/src/lib/skills.interface.ts核心契约定义libs/ai/agent-skills/project.json构建配置删除src/lib/skills.interface.ts里的默认内容替换成我们的真实契约// libs/ai/agent-skills/src/lib/skills.interface.ts export interface SkillMetadata { /** * 技能唯一标识符格式domain:subdomain:skill-name * 例logistics:order:query, finance:invoice:generate */ id: string; /** * 技能语义化版本号必须与对应Agent项目的package.json version一致 * 用于在CI中强制校验版本对齐 */ version: string; /** * 技能名称用于UI展示和日志追踪 */ name: string; /** * 技能简短描述不超过100字符 */ description: string; /** * 此技能是否需要人工介入才能执行 * true调用前必须获得human_approval_token * false全自动执行 */ requires_human_approval: boolean; /** * 预估最大执行耗时毫秒用于调度器超时控制 * 必须是整数且100 */ timeout_ms: number; /** * 当技能执行失败时可降级调用的替代技能ID * 例主技能finance:payment:process失败时降级到finance:payment:retry-later * null表示无降级策略 */ fallback_to: string | null; } export interface SkillInputSchema { /** * JSON Schema Draft-07 格式描述输入数据结构 * 必须包含$schema: https://json-schema.org/draft-07/schema# */ $schema: string; /** * 输入对象的类型必须为object */ type: object; /** * 必填字段列表 */ required: string[]; /** * 字段定义 */ properties: Recordstring, { type: string; description?: string; enum?: any[]; minimum?: number; maximum?: number; }; } export interface SkillOutputSchema { /** * JSON Schema Draft-07 格式描述输出数据结构 * 必须包含$schema: https://json-schema.org/draft-07/schema# */ $schema: string; /** * 输出对象的类型必须为object */ type: object; /** * 必填字段列表 */ required: string[]; /** * 字段定义 */ properties: Recordstring, { type: string; description?: string; enum?: any[]; }; } export interface AgentSkill { /** * 技能元数据 */ metadata: SkillMetadata; /** * 输入Schema定义 */ input: SkillInputSchema; /** * 输出Schema定义 */ output: SkillOutputSchema; /** * 技能执行状态机定义 * 描述技能可能的状态流转pending - processing - success/failure * 用于前端实时状态渲染和运维告警 */ state_machine: { initial: string; states: Recordstring, { type: atomic | compound; on?: Recordstring, string; }; }; }3.2 自动生成JSON Schema并集成到Nx构建流程TypeScript interface只是开发时的便利生产环境需要机器可读的JSON Schema。我们写一个Nx executor自动将TS interface转为Schema在libs/ai/agent-skills/project.json中添加新target{ name: agent-skills, targets: { build: { /* 原有配置 */ }, generate-schema: { executor: nx/workspace:run-commands, options: { commands: [ npx ts-json-schema-generator --path libs/ai/agent-skills/src/lib/skills.interface.ts --type AgentSkill --out libs/ai/agent-skills/src/lib/skills.schema.json ], cwd: ${workspaceRoot} } } } }但ts-json-schema-generator默认不支持泛型和复杂嵌套我们需要一个更可靠的方案。实测下来用sinclair/typebox手动生成更稳定npm install sinclair/typebox --save-dev创建libs/ai/agent-skills/src/lib/generate-schema.tsimport { Type, Static } from sinclair/typebox; import { writeFileSync } from fs; // 重定义SkillMetadata为TypeBox Schema确保可序列化 const SkillMetadataSchema Type.Object({ id: Type.String({ description: 技能唯一标识符格式domain:subdomain:skill-name }), version: Type.String({ description: 技能语义化版本号 }), name: Type.String({ description: 技能名称 }), description: Type.String({ description: 技能简短描述不超过100字符, maxLength: 100 }), requires_human_approval: Type.Boolean({ description: 是否需要人工介入 }), timeout_ms: Type.Integer({ description: 预估最大执行耗时毫秒, minimum: 100 }), fallback_to: Type.Union([Type.String(), Type.Null()], { description: 失败时降级技能ID }), }); const SkillInputSchemaSchema Type.Object({ $schema: Type.Literal(https://json-schema.org/draft-07/schema#), type: Type.Literal(object), required: Type.Array(Type.String()), properties: Type.Record(Type.String(), Type.Object({ type: Type.String(), description: Type.Optional(Type.String()), enum: Type.Optional(Type.Array(Type.Any())), minimum: Type.Optional(Type.Number()), maximum: Type.Optional(Type.Number()), })), }); const SkillOutputSchemaSchema Type.Object({ $schema: Type.Literal(https://json-schema.org/draft-07/schema#), type: Type.Literal(object), required: Type.Array(Type.String()), properties: Type.Record(Type.String(), Type.Object({ type: Type.String(), description: Type.Optional(Type.String()), enum: Type.Optional(Type.Array(Type.Any())), })), }); const AgentSkillSchema Type.Object({ metadata: SkillMetadataSchema, input: SkillInputSchemaSchema, output: SkillOutputSchemaSchema, state_machine: Type.Object({ initial: Type.String(), states: Type.Record(Type.String(), Type.Object({ type: Type.Union([Type.Literal(atomic), Type.Literal(compound)]), on: Type.Optional(Type.Record(Type.String(), Type.String())), })), }), }); // 生成并写入文件 writeFileSync( libs/ai/agent-skills/src/lib/skills.schema.json, JSON.stringify(AgentSkillSchema, null, 2) ); console.log(✅ skills.schema.json generated successfully);然后更新project.json的generate-schematargetgenerate-schema: { executor: nx/node:execute, options: { buildTarget: agent-skills:build, scriptPath: libs/ai/agent-skills/src/lib/generate-schema.ts } }现在每次运行nx run agent-skills:generate-schema都会生成精确匹配TS interface的JSON Schema。更重要的是我们在libs/ai/agent-skills/project.json中添加pre-build钩子build: { executor: nx/node:build, dependsOn: [agent-skills:generate-schema], options: { /* ... */ } }这意味着任何Agent项目执行nx build前agent-skills的Schema必定是最新的。契约一致性从此成为构建流程的硬性门槛。3.3 在Agent项目中强制校验skills.json文件每个Agent项目必须提供一个skills.json文件位于apps/xxx-agent/src/skills.json。我们用Nx的custom executor来校验它是否符合agent-skills的Schema创建tools/executors/skill-validator/schema-validator.impl.tsimport { ExecutorContext } from nx/devkit; import { readJsonFile, logger } from nx/devkit; import { validate } from jsonschema; import * as path from path; export default async function* schemaValidatorExecutor( _options: any, context: ExecutorContext ) { const projectRoot context.projectsConfigurations?.projects[context.projectName]?.root; if (!projectRoot) { logger.error(Project root not found for ${context.projectName}); return { success: false }; } const skillsJsonPath path.join(projectRoot, src, skills.json); try { const skillsJson readJsonFile(skillsJsonPath); const schema readJsonFile(libs/ai/agent-skills/src/lib/skills.schema.json); const result validate(skillsJson, schema); if (!result.valid) { logger.error(❌ skills.json validation failed for ${context.projectName}:); result.errors.forEach((e) logger.error( - ${e.property} ${e.message})); return { success: false }; } logger.info(✅ skills.json validated successfully for ${context.projectName}); return { success: true }; } catch (e) { logger.error(❌ Failed to read or validate skills.json: ${e.message}); return { success: false }; } }注册executor到tools/executors/skill-validator/executor.json{ implementation: ./schema-validator.impl.js, schema: ./schema.json, description: Validates skills.json against agent-skills schema }最后在每个Agent项目的project.json中添加targetvalidate-skills: { executor: ./tools/executors/skill-validator:default }现在CI Pipeline可以这样写jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - uses: nrwl/nx-actionv3 - run: nx run-many --targetvalidate-skills --all任何skills.json格式错误都会在PR阶段被拦截而不是等到上线后才发现“风控Agent的fallback_to字段写成了字符串而非null”。实操心得我们曾在线上环境遇到一次严重事故——某个Agent的skills.json里timeout_ms被误写为5000字符串导致调度器无法解析整个AI流水线卡死。自从加入这个校验executor类似问题归零。记住契约校验不是锦上添花而是生产环境的氧气面罩。它应该像TypeScript编译一样成为你每天敲nx build时的默认行为。4.agent-skills的实战演进从基础契约到AI工程治理闭环当你把agent-skills作为标准落地后它会自然生长出更多工程价值。这不是设计出来的而是在解决真实问题过程中逐步沉淀的。以下是我亲历的三个关键演进阶段每个阶段都对应一个Nx plugin的诞生。4.1 阶段一技能发现与可视化nx agent-skills:list最初我们只能靠grep -r skills.json apps/找所有Agent。随着Agent数量增长到30这个操作越来越痛苦。于是我们开发了第一个Nx pluginnx g myorg/nx-plugin:agent-skills-list --nameagent-skills-list它实现了nx agent-skills:list命令效果如下$ nx agent-skills:list ┌───────────────────────────┬──────────────┬──────────┬──────────────────────────────┐ │ Skill ID │ Version │ Timeout │ Description │ ├───────────────────────────┼──────────────┼──────────┼──────────────────────────────┤ │ logistics:order:query │ 2.1.0 │ 3000ms │ 查询订单详情及物流状态 │ │ finance:payment:process │ 1.4.2 │ 8000ms │ 处理支付请求并返回结果 │ │ compliance:terms:check │ 3.0.1 │ 1200ms │ 校验用户协议条款是否合规 │ └───────────────────────────┴──────────────┴──────────┴──────────────────────────────┘原理很简单遍历所有apps/*/src/skills.json读取metadata字段用nx/workspace:run-commands聚合输出。但价值巨大——运维同学再也不用翻代码找Agent产品同学能一眼看清系统能力全景。4.2 阶段二技能血缘分析nx agent-skills:trace某次线上故障用户投诉“下单后没收到支付确认”。排查发现订单Agent调用支付Agent成功但支付Agent的fallback_to指向了一个已下线的payment:retry-legacy技能。问题根源是技能依赖关系没人维护。我们开发了nx agent-skills:trace --skillfinance:payment:process它会解析finance:payment:process的skills.json读取其fallback_to字段递归查找该技能是否存在、是否启用、版本是否兼容生成Mermaid风格的依赖图文本形式适配CLI输出示例finance:payment:process1.4.2 ├── fallback_to: payment:retry-legacy1.0.0 ❌ NOT FOUND └── depends_on: ├── finance:account:balance2.2.0 ✅ └── logistics:warehouse:stock1.8.3 ✅这个功能直接催生了我们的“技能健康度看板”每天自动扫描所有Agent的fallback_to和depends_on标记出风险项。4.3 阶段三技能版本门禁nx agent-skills:enforce最狠的一招在nx affected基础上增加语义化版本约束。例如当myorg/agent-skills从1.2.0升级到2.0.0breaking change我们要求所有依赖它的Agent项目package.json中的myorg/agent-skills版本必须显式升级到^2.0.0否则nx build直接失败并提示“BREAKING CHANGE detected in agent-skills2.0.0. Please update your projects dependency and run nx migrate”这是通过Nx的migrations.json实现的[ { version: 2.0.0, description: Update agent-skills to v2.0.0 with breaking changes, factory: ./migrations/update-to-v2, package: myorg/agent-skills } ]migrations/update-to-v2.ts会修改所有Agent项目的package.json将myorg/agent-skills版本更新为^2.0.0运行nx run-many --targetvalidate-skills --all确保所有skills.json符合新Schema如果校验失败给出详细修复指引这套机制让我们的AI系统具备了传统Java/Spring Boot系统才有的“版本治理能力”。当算法团队说“我们要重构风控模型需要修改输入字段”后端团队不再需要临时开会协调而是直接执行nx migrate整个过程自动化、可追溯、零遗漏。经验总结agent-skills的价值90%不在初始搭建而在后续演进。它不是一个静态的类型定义而是一个活的AI工程治理中枢。每一次你为解决一个具体痛点找技能、查依赖、管版本而写的Nx命令都在加固这个中枢。不要追求一步到位从nx agent-skills:list开始让团队感受到“原来AI系统也能像ERP一样被管理”这才是真正的文化变革起点。5. 踩过的坑与避坑清单那些TypeScript和Nx联手也救不了的陷阱即使你严格按照上述步骤搭建agent-skills在真实世界中依然会给你惊喜。以下是我在Jetson Xavier NX边缘设备、NestJS微服务集群、以及Vue前端三端协同场景下踩过并记录下来的7个高危陷阱。每个都附带真实日志片段和解决方案。5.1 陷阱一TypeScriptdeclare global污染全局类型导致技能契约冲突现象在libs/ai/agent-skills/src/index.ts中我们写了declare global { namespace NodeJS { interface ProcessEnv { AGENT_SKILLS_VERSION: string; } } }本意是让所有项目都能访问process.env.AGENT_SKILLS_VERSION。但某天一个前端Vue项目突然编译失败报错TS2300: Duplicate identifier ProcessEnv.原因是Vue CLI的vue/cli-service也声明了ProcessEnv且字段不同。根因declare global是全局污染一旦多个library都这么做就会冲突。agent-skills不该承担环境变量注入职责。解法彻底删除declare global。改为在每个Agent项目的environment.ts中显式定义// apps/order-query-agent/src/environments/environment.ts export const environment { agentSkillsVersion: 2.1.0 as const, };然后在skills.json中用占位符构建时由Nx脚本替换{ metadata: { version: ${AGENT_SKILLS_VERSION} } }nx build时执行sed -i s/\${AGENT_SKILLS_VERSION}/${environment.agentSkillsVersion}/g dist/apps/order-query-agent/src/skills.json提示TypeScript的declare global是把双刃剑。在agent-skills这种基础设施层宁可多写几行代码也不要引入全局副作用。契约的纯净性高于一切便利性。5.2 陷阱二Nx的affected命令在Git Submodule中失效现象我们的agent-skills库被作为Git submodule嵌入到另一个大型遗留系统中。当在submodule内修改skills.interface.ts后nx affected --targetbuild返回空结果仿佛没改动任何项目。根因Nx的affected依赖Git的git diff而submodule有自己的独立Git历史nx affected无法穿透submodule边界识别变更。解法放弃submodule改用Nx的npm publishnpm install方式。但为了保持monorepo体验我们做了两件事在CI中nx build agent-skills后自动执行npm publish --registryhttps://your-private-registry.com在遗留系统中package.json里写myorg/agent-skills: 2.1.0而非file:../path/to/submodule这样nx affected在monorepo内正常工作遗留系统通过npm获取稳定版本互不干扰。5.3 陷阱三JSON Schema的$ref在TypeScript中无法被sinclair/typebox正确解析现象我们想复用SkillMetadata定义于是在SkillInputSchema中写了properties: { metadata: { $ref: #/definitions/SkillMetadata } }但sinclair/typebox生成的Schema里$ref被忽略导致skills.json校验失败。根因sinclair/typebox的Type.Ref()需要显式定义引用目标不能直接解析JSON Schema的$ref。解法放弃$ref改用TypeBox的Type.Partial()和Type.Omit()组合复用const SkillInputSchema Type.Object({ // ... 其他字段 metadata: Type.Omit(SkillMetadataSchema, [version]), // 复用但排除version });5.4 陷阱四skills.json文件被Webpack/Vite当作静态资源打包导致Node.js环境读取失败现象前端Vue项目里fetch(/assets/skills.json)返回404。后端NestJS项目里readFileSync(src/skills.json)抛出ENOENT。根因Webpack/Vite默认把src/skills.json视为静态资源打包到dist/assets/下而Node.js的readFileSync期望它在src/目录。解法统一约定skills.json必须放在项目根目录与project.json同级命名为skills.manifest.json。构建时Nx脚本将其复制到dist/目录build: { executor: nx/node:build, options: { assets: [apps/order-query-agent/skills.manifest.json] } }5.5 陷阱五semantic-release的semantic-release/npm插件与Nx的nx release冲突现象我们同时配置了semantic-release和nx release结果nx release发布的版本号是1.0.0而semantic-release又发布了一次1.0.1造成版本混乱。根因两个工具都在争抢package.json的version字段和Git tag。解法停用semantic-release完全采用nx release。它原生支持自动检测agent-skills的变更仅当其修改时才触发发布生成符合Conventional Commits的changelog发布到私有NPM registry配置nx.jsonrelease: { projects: [agent-skills], changelog: { project: agent-skills, file: libs/ai/agent-skills/CHANGELOG.md } }5.6 陷阱六TypeScript的--skipLibCheck导致agent-skills类型错误被忽略现象某个Agent项目启用了skipLibCheck: true结果skills.json里写了timeout_ms: 5000字符串TypeScript编译居然通过了根因skipLibCheck跳过了node_modules和libs/下的类型检查agent-skills的interface不再生效。解法在tsconfig.base.json中强制关闭skipLibCheck{ compilerOptions: { skipLibCheck: false } }并在CI中添加检查grep -q skipLibCheck:.*true apps/*/tsconfig.json echo ERROR: skipLibCheck must be false exit 15.7 陷阱七Nx的project.json中dependencies字段被误写为devDependencies现象order-query-agent的project.json里myorg/agent-skills被写在devDependencies下。本地nx build成功但Docker镜像里node_modules缺失该包运行时报Cannot find module myorg/agent-skills。根因Nx的project.json没有devDependencies概念所有依赖都应写在dependencies里。devDependencies是npm的概念Nx不识别。解法编写Nx lint rule扫描所有project.json确保myorg/agent-skills只出现在dependencies中// tools/linters/agent-skills-dependency.lint.ts export default function checkAgentSkillsDependency(tree: Tree) { const projects Object.keys(tree.listProjects()); projects.forEach(project { const projectJson readJsonFile(tree, ${project}/project.json); if (projectJson.dependencies?.[myorg/agent-skills]) return; if (projectJson.devDependencies?.[myorg/agent-skills]) { throw new Error(❌ ${project}/project.json: myorg/agent-skills must be in dependencies, not devDependencies); } }); }最后一句真心话这些坑每一个都让我加班到凌晨。但正是这些坑教会我一件事——AI工程的复杂度从来不在模型本身而在模型与现实世界的接口处。agent-skills就是那个接口。把它焊死、擦亮、持续打磨你的AI系统才能真正立得住。