ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

agent-skills:TypeScript+NX的AI能力契约建模范式

agent-skills:TypeScript+NX的AI能力契约建模范式 1. “agent-skills”不是库名而是工程级能力抽象范式你搜“agent-skills”首页几乎全是 GitHub 仓库、Nx 工作区里的子项目、TypeScript 类型定义文件甚至还有 NestJS Controller 的接口签名片段——但它根本不是一个 npm 包也不是某个开源框架的官方模块。我第一次看到这个词是在一个金融风控中台的 Monorepo 代码审查里libs/agent-skills/src/lib/credit-approval.ts。当时以为是某家 AI 公司自研的 Agent SDK结果点进去发现它连package.json都没有只有一堆.ts文件和index.ts导出声明。后来在三个不同行业的客户现场电商履约中台、工业设备远程诊断平台、政务智能审批系统都撞见了同名目录结构/libs/agent-skills/。它们共性极强——不封装运行时逻辑只定义能力契约不暴露执行函数只导出类型与协议不依赖任何 AI 框架却能无缝接入 LangChain、LlamaIndex、甚至自研推理网关。这才是“agent-skills”的真实身份一种在 TypeScript Nx 架构下沉淀出的领域能力建模规范本质是把“Agent 能做什么”这件事从模糊的业务描述变成可静态检查、可版本管理、可跨团队复用的类型系统。它解决的不是“怎么调大模型”而是“怎么让十个团队写的 Agent 模块能互相理解”。比如电商侧定义的OrderCancellationSkill和物流侧的DeliveryRescheduleSkill必须共享同一套SkillInput结构、同一套错误码枚举、同一套元数据字段scope: order | logistics | finance。这种一致性靠文档管不住靠会议说不清但靠agent-skills这个包的类型导出编译器就能强制校验。你写错一个字段名TS 直接报错“Property cancellationReason does not exist on type OrderCancellationInput”。提示别急着npm install agent-skills——它不存在于 npm registry。它的“安装”方式是在 Nx 工作区里执行nx g nrwl/workspace:library agent-skills --publishable --importPathyour-org/agent-skills然后手动填充类型定义。这是刻意为之的设计能力契约必须由业务方自己定义不能外包给第三方库。这个模式之所以在 2024 年密集出现核心驱动力是LLM 应用落地进入“拼接时代”。单个 Agent 已无法覆盖复杂业务流比如“处理客诉”需要调用订单查询、库存校验、赔付计算、短信通知四个子技能而各子技能又分属不同团队开发。没有统一的能力契约集成就是一场灾难A 团队传来的userId是字符串B 团队期待的是数字C 团队返回的status是success | failedD 团队却用OK | ERROR。agent-skills就是为终结这种混乱而生的——它不写业务逻辑只写“语言规则”。2. 为什么必须用 Nx TypeScript 实现三重不可替代性有人问用普通 npm 包不行吗用单独的 Git 仓库管理类型定义不行吗用 JSON Schema 描述技能接口不行吗答案是在企业级 LLM 应用场景下这三者全部失效。我拿实际踩过的坑来说明。2.1 单独 npm 包的版本地狱去年帮一家保险科技公司做保全服务 Agent 改造。他们最初用独立 npm 包insure/agent-contract管理技能类型版本号打到v3.7.2。问题爆发在一次跨团队协作核保团队升级了PolicyValidationSkillInput新增了riskAssessmentLevel: low | medium | high字段但理赔团队的ClaimProcessingAgent还在用v3.5.0调用时直接抛出TypeError: Cannot read property riskAssessmentLevel of undefined。更糟的是因为 npm 包是语义化版本^3.5.0允许自动升级到3.7.2导致线上环境随机崩溃——某些节点装了新包某些没装。Nx 的解决方案简单粗暴所有技能类型定义必须和使用它的 Agent 代码在同一工作区。当你在apps/claim-processor中引用insure/agent-skillsNx 编译时会强制进行本地符号解析而不是去 node_modules 查找。这意味着修改libs/agent-skills/src/lib/policy-validation.ts后运行nx build claim-processor会立刻触发类型检查如果新增字段未被消费方处理TS 编译失败CI 直接卡住版本号根本不需要。Nx 通过project.json中的targets.build.options.outputPath控制构建产物路径所有依赖都是源码级链接不存在“版本不一致”概念。2.2 TypeScript 类型即契约比 JSON Schema 更锋利的刀JSON Schema 看似通用但在 Agent 技能场景下有致命缺陷。举个真实例子某政务系统要求“身份证识别技能”必须支持港澳居民来往内地通行证回乡证和台湾居民来往大陆通行证台胞证。用 JSON Schema 定义输入{ type: object, properties: { idNumber: { type: string }, idType: { enum: [ID_CARD, HONGKONG_PERMIT, TAIWAN_PERMIT] } } }问题来了前端传idType: HONGKONG_PERMIT后端技能实现里却写了if (input.idType HK_PERMIT)—— JSON Schema 校验通过运行时直接undefined。TypeScript 的解决方案是// libs/agent-skills/src/lib/id-verification.ts export type IdType ID_CARD | HONGKONG_PERMIT | TAIWAN_PERMIT; export interface IdVerificationInput { idNumber: string; idType: IdType; // 注意这里是类型不是字符串字面量 } // 在技能实现中 export const verifyId: SkillIdVerificationInput, IdVerificationOutput { execute: async (input: IdVerificationInput) { switch (input.idType) { // TS 编译器强制要求覆盖所有字面量 case ID_CARD: return handleIdCard(input); case HONGKONG_PERMIT: return handleHkPermit(input); // 拼错TS 立刻报错 case TAIWAN_PERMIT: return handleTwPermit(input); // default: throw new Error(Unknown idType); // 缺少此行TS 提示 not all code paths return a value } } };这才是真正的契约类型定义不仅约束输入格式更约束执行分支的完备性。JSON Schema 做不到这点Swagger/OpenAPI 也做不到。只有 TypeScript 的字面量联合类型 exhaustive switch才能把“漏处理某种证件类型”这种低级错误拦截在编译阶段。2.3 Nx 的拓扑感知让技能复用率提升 300%Nx 最被低估的能力是它的项目拓扑图Project Graph。当你运行nx graph它会自动生成一张可视化依赖图清晰标出哪些 Agent 应用依赖了agent-skills哪些技能类型被多少个 Agent 引用哪些类型长期无人使用可标记为 deprecated。我们曾用这个能力重构某车企的售后服务 Agent。原系统有 12 个独立 Node.js 服务各自维护一套“预约维修技能”字段名五花八门bookingTime/appointmentTime/scheduleAt。通过 Nx 拓扑分析发现其中 9 个服务实际只用到了bookingTime和vehicleVin两个字段。于是我们做了三件事在libs/agent-skills/src/lib/service-booking.ts中精简定义export interface ServiceBookingInput { bookingTime: Date; // 统一命名强制 ISO 8601 字符串 vehicleVin: string; // 统一长度校验17位 // 移除所有历史遗留字段serviceType, dealerCode, customerName... }运行nx dep-graph --filedep-graph.html确认所有依赖方都已适配对剩余 3 个需要特殊字段的服务新建ServiceBookingExtendedInput类型明确标注deprecated use ServiceBookingInput instead。结果技能复用率从 0%每个服务自定义提升到 75%9/12 服务直接复用且后续新增“上门取车”技能时直接继承ServiceBookingInput只需扩展pickupAddress: string字段——拓扑图自动标记出所有受影响的 Agent确保灰度发布无遗漏。注意Nx 的拓扑能力依赖于严格的导入路径。务必禁用allowSyntheticDefaultImports并配置tsconfig.base.json中的baseUrl: .和paths映射。否则import { Skill } from your-org/agent-skills会被解析为相对路径拓扑图将失效。3. 从零搭建 agent-skills 工作区手把手拆解每一步意图现在我们动手搭建一个最小可行的agent-skills工作区。重点不是命令本身而是每个命令背后的设计意图——为什么这里必须用 Nx为什么那个配置不能省略为什么文件结构要长成这样。3.1 初始化为什么不用 create-react-app 或 Vite第一步永远是npx create-nx-workspacelatest my-agent-platform \ --presetapps \ --appNamecore-gateway \ --packageManagerpnpm \ --nxCloudfalse关键参数解析--presetapps选择“应用型”预设而非npm-publish或react。因为agent-skills本质是类型库不是 UI 组件或 CLI 工具--appNamecore-gateway这个应用将是所有 Agent 的统一入口HTTP API / gRPC Server它必须存在否则 Nx 无法构建完整的依赖拓扑--packageManagerpnpm必须用 pnpm。它的硬链接机制能让libs/agent-skills的修改实时反映到apps/core-gateway中无需pnpm run buildyarn 和 npm 的 node_modules 复制机制会导致类型缓存不一致--nxCloudfalse关闭 Nx Cloud。企业内网环境通常无法访问其服务且agent-skills的类型定义变更无需远程缓存。提示如果已有 Vue/React 前端项目不要用--presetapps。正确做法是先nx add nrwl/web添加 Web 插件再nx g nrwl/web:app frontend创建前端应用。agent-skills必须作为独立 library 存在不能混在 app 目录下。3.2 创建 skills 库--publishable的真实含义执行nx g nrwl/workspace:library agent-skills \ --publishable \ --importPathmy-org/agent-skills \ --directorylibs这里--publishable是关键陷阱。很多人以为它表示“可以发布到 npm”其实不然。在 Nx 中--publishable的真实作用是启用buildtarget并生成dist/libs/agent-skills目录下的package.json和类型声明文件.d.ts。即使你永不发布这个 flag 也必须加——因为core-gateway需要引用构建后的类型定义而非源码源码引用会导致循环依赖检测失败。生成的libs/agent-skills/project.json中targets.build.options.outputPath默认是dist/libs/agent-skills。但请立即修改为outputPath: dist/libs/agent-skills, main: libs/agent-skills/src/index.ts, tsConfig: libs/agent-skills/tsconfig.lib.json, assets: [libs/agent-skills/*.md]为什么改main因为 Nx 默认生成libs/agent-skills/src/lib/agent-skills.ts但我们需要index.ts作为统一入口。创建libs/agent-skills/src/index.ts// libs/agent-skills/src/index.ts export * from ./lib/skill-definition; export * from ./lib/error-codes; export * from ./lib/common-types; // 不要导出具体技能实现只导出契约3.3 定义核心类型skill-definition.ts 的设计哲学在libs/agent-skills/src/lib/skill-definition.ts中写下第一行export type SkillId string { __brand: SkillId };这个看似多余的类型是整个架构的基石。string { __brand: SkillId }利用了 TypeScript 的“品牌化类型Branded Types”技巧它让SkillId和普通string完全不兼容。你不能把const id order-cancel-001直接赋值给SkillId类型变量必须显式转换const skillId: SkillId order-cancel-001 as SkillId; // 或更安全的工厂函数 export const createSkillId (id: string): SkillId id as SkillId;为什么这么麻烦因为 Agent 调用链中skillId是路由关键。如果允许任意字符串就可能出现前端传skillId: cancel-order小写短横线后端技能注册表里存的是cancelOrder驼峰路由中间件匹配失败返回 404。用品牌化类型就能在编译期捕获所有非法赋值。我们甚至在 CI 中加入检查# nx workspace-lint --fix # 然后 grep 所有 as SkillId 出现的位置人工审核是否合理接着定义技能执行契约export interface SkillInput {} export interface SkillOutput {} export interface SkillI extends SkillInput, O extends SkillOutput { id: SkillId; description: string; inputSchema: Recordstring, unknown; // 运行时 JSON Schema 校验用 execute: (input: I) PromiseO; }注意inputSchema字段它不是 TypeScript 类型而是运行时校验用的 JSON Schema。因为前端传来的 HTTP Body 是any必须在execute前做二次校验。我们约定所有技能实现必须提供inputSchema且字段名与 TypeScript 接口严格一致通过zod自动生成。3.4 构建与验证让类型错误成为上线前的最后防线执行nx build agent-skills会生成dist/libs/agent-skills/index.d.ts。打开它你会看到export declare type SkillId string { __brand: SkillId; }; export declare interface SkillInput { } export declare interface SkillOutput { } export declare interface SkillI extends SkillInput, O extends SkillOutput { id: SkillId; description: string; inputSchema: Recordstring, unknown; execute: (input: I) PromiseO; }现在在apps/core-gateway/src/main.ts中引用import { SkillId, Skill } from my-org/agent-skills; // 错误示范直接用字符串 const badId: SkillId order-cancel; // TS 报错Type string is not assignable to type SkillId // 正确示范 const goodId: SkillId order-cancel as SkillId; // 但需确保此处有业务逻辑校验最关键的验证步骤修改libs/agent-skills/src/lib/skill-definition.ts故意删掉inputSchema字段保存。然后运行nx build core-gateway—— 编译失败错误信息精准指向Skill接口缺失属性。这证明类型契约已穿透整个工作区任何破坏契约的行为都会在构建阶段被拦截。实操心得在nx.json中配置targetDefaults: { build: { dependsOn: [^build] } }确保构建core-gateway前自动构建所有依赖项包括agent-skills。否则可能因缓存导致类型不一致。4. 技能实现层如何让 TypeScript 类型驱动真实业务逻辑agent-skills只定义契约不写实现。但实现层必须严格遵循契约否则整个体系崩塌。我们以“订单取消技能”为例展示如何用 TypeScript 类型驱动开发全流程。4.1 从类型定义开始先写接口再写代码在libs/agent-skills/src/lib/order-cancellation.ts中定义import { SkillId, Skill, SkillInput, SkillOutput } from ../skill-definition; export interface OrderCancellationInput extends SkillInput { orderId: string; cancellationReason: out-of-stock | customer-request | fraud-suspicion; refundMethod?: original-payment | store-credit; } export interface OrderCancellationOutput extends SkillOutput { status: cancelled | partially-cancelled | rejected; refundAmount?: number; cancelledItems: Array{ sku: string; quantity: number }; } export const ORDER_CANCELLATION_SKILL_ID: SkillId order-cancellation as SkillId; export const orderCancellationSkill: SkillOrderCancellationInput, OrderCancellationOutput { id: ORDER_CANCELLATION_SKILL_ID, description: Cancel an existing order and process refund, inputSchema: { type: object, required: [orderId, cancellationReason], properties: { orderId: { type: string, minLength: 1 }, cancellationReason: { enum: [out-of-stock, customer-request, fraud-suspicion] }, refundMethod: { type: string, enum: [original-payment, store-credit], nullable: true } } }, execute: async (input: OrderCancellationInput) { // 实现逻辑在此处 } };注意三点OrderCancellationInput继承SkillInput确保所有技能输入都有统一基类cancellationReason使用字面量联合类型而非string杜绝拼写错误inputSchema的enum值与 TypeScript 类型严格一致避免前后端不一致。4.2 实现层用 Zod 自动同步类型与 Schema手写inputSchema容易出错。我们用zod自动生成pnpm add zod -w在libs/agent-skills/src/lib/order-cancellation.ts中import { z } from zod; const OrderCancellationInputSchema z.object({ orderId: z.string().min(1), cancellationReason: z.enum([out-of-stock, customer-request, fraud-suspicion]), refundMethod: z.enum([original-payment, store-credit]).optional() }); export type OrderCancellationInput z.infertypeof OrderCancellationInputSchema; // 自动导出 JSON Schema export const orderCancellationInputSchema OrderCancellationInputSchema.schema;然后在技能定义中export const orderCancellationSkill: SkillOrderCancellationInput, OrderCancellationOutput { // ... inputSchema: orderCancellationInputSchema, execute: async (input: OrderCancellationInput) { // TS 编译器保证 input 一定是合法的 OrderCancellationInput // 无需手动校验 input.orderId 存在与否 } };这样类型定义和运行时校验完全同步。修改zodschemaTS 类型自动更新反之亦然。我们曾用此方案在 3 个团队间同步了 27 个技能的输入输出定义零次因类型不一致导致的线上故障。4.3 错误处理用类型收束所有异常分支Agent 技能的错误必须结构化。我们定义统一错误码// libs/agent-skills/src/lib/error-codes.ts export const ERROR_CODES { VALIDATION_FAILED: VALIDATION_FAILED, SERVICE_UNAVAILABLE: SERVICE_UNAVAILABLE, BUSINESS_RULE_VIOLATED: BUSINESS_RULE_VIOLATED, EXTERNAL_API_ERROR: EXTERNAL_API_ERROR } as const; export type ErrorCode typeof ERROR_CODES[keyof typeof ERROR_CODES]; export interface SkillError { code: ErrorCode; message: string; details?: Recordstring, unknown; }在技能实现中export const orderCancellationSkill: SkillOrderCancellationInput, OrderCancellationOutput { // ... execute: async (input: OrderCancellationInput) { try { // 业务逻辑 return { status: cancelled, ... }; } catch (error) { if (error instanceof ValidationError) { throw { code: ERROR_CODES.VALIDATION_FAILED, message: error.message, details: error.validationErrors } satisfies SkillError; // TS 强制类型匹配 } throw { code: ERROR_CODES.SERVICE_UNAVAILABLE, message: Order service unavailable, details: { originalError: error } } satisfies SkillError; } } };satisfies SkillError是 TypeScript 4.9 的新特性它确保抛出的对象结构符合SkillError类型但不改变其运行时类型。这样调用方可以安全地做类型守卫try { await orderCancellationSkill.execute(input); } catch (error) { if (code in error error.code ERROR_CODES.BUSINESS_RULE_VIOLATED) { // 特定错误处理 } }4.4 测试驱动用类型断言代替 mock测试orderCancellationSkill时我们不 mock 任何东西而是用类型断言验证契约// libs/agent-skills/src/lib/order-cancellation.spec.ts import { orderCancellationSkill, OrderCancellationInput } from ./order-cancellation; describe(orderCancellationSkill, () { it(should accept valid input, () { // TS 编译期保证以下对象符合 OrderCancellationInput 类型 const validInput: OrderCancellationInput { orderId: ORD-12345, cancellationReason: customer-request }; // 运行时测试 expect(orderCancellationSkill.execute(validInput)).resolves.toEqual( expect.objectContaining({ status: cancelled }) ); }); it(should reject invalid cancellationReason, () { // 以下代码 TS 编译失败证明类型约束生效 // const invalidInput: OrderCancellationInput { // orderId: ORD-12345, // cancellationReason: unknown-reason // ❌ TS Error // }; }); });这种测试方式把 70% 的边界条件检查交给了 TypeScript 编译器测试代码专注验证业务逻辑而非类型合法性。5. 生产就绪semantic-release 如何与 agent-skills 协同演进agent-skills的类型定义一旦发布就是所有 Agent 的“宪法”。因此它的版本演进必须极度谨慎。我们采用semantic-release Nx 的组合实现零人工干预的自动化发布且每次发布都附带精确的变更影响分析。5.1 配置 semantic-release只发布类型不发布逻辑在libs/agent-skills/project.json中添加releasetargetrelease: { executor: semantic-release/exec:exec, options: { cmd: pnpm run release:types } }在package.json中定义脚本scripts: { release:types: semantic-release --branches main --no-ci --dry-runfalse }关键配置release.config.jsmodule.exports { plugins: [ semantic-release/commit-analyzer, semantic-release/release-notes-generator, [ semantic-release/exec, { // 只在类型定义变更时发布 prepare: pnpm run build:types cp dist/libs/agent-skills/package.json dist/libs/agent-skills/ } ], semantic-release/npm, semantic-release/github ], // 重点只分析 libs/agent-skills/src/lib/ 下的 .ts 文件变更 branches: [main], tagFormat: agent-skills-v${version}, preset: conventionalcommits };为什么只分析src/lib/因为agent-skills的唯一价值是类型定义。src/index.ts、src/lib/*.ts的变更才触发发布README.md或测试文件的修改不应产生新版本。5.2 变更类型识别如何判断是 breaking changesemantic-release依赖commit-analyzer解析提交信息但类型变更的 breaking 判断不能只看 commit message。我们在 CI 中加入自定义检查# 在 semantic-release 之前运行 pnpm exec tsd --name agent-skills # 运行 tsd 检查类型兼容性tsdTypeScript Definition Tester是一个专门检查类型兼容性的工具。它会拉取上一个版本的my-org/agent-skills类型声明将当前dist/libs/agent-skills/index.d.ts与之对比如果发现OrderCancellationInput删除了refundMethod字段则判定为breaking change要求 commit message 必须包含BREAKING CHANGE:如果只是新增字段则视为minor如果只修改注释则视为patch。这个检查比 conventional commits 更可靠因为开发者可能忘记写BREAKING CHANGE:但tsd会强制拦截。5.3 影响范围报告让每个发布都附带“宪法修订说明”每次semantic-release成功发布都会在 GitHub Release 页面生成一份Changelog。但我们额外生成一份Impact Report# 在 release 脚本末尾 pnpm exec nx graph --fileimpact-report.html --focusagent-skills这个 HTML 文件会显示哪些应用core-gateway,frontend,mobile-app依赖了agent-skills这些应用中哪些技能类型被本次变更影响例如OrderCancellationInput每个受影响的应用其package.json中的my-org/agent-skills版本号。运维团队拿到这份报告就知道core-gateway必须升级到v2.1.0frontend可以暂缓因为它只用到了IdVerificationInput未受影响mobile-app需要同步修改因为它的OrderCancellationInput使用了已删除的字段。实操心得在nx.json中配置affectedBy: [libs/agent-skills]让nx affected --targetbuild自动识别所有受影响的应用。发布后一键执行nx affected --targetbuild --parallel3确保所有依赖方都能通过构建。6. 踩坑实录那些让团队加班到凌晨的 agent-skills 陷阱再完美的设计也会在真实战场中遭遇意外。我把过去两年踩过的最痛的 5 个坑按严重程度排序附上根因分析和永久解决方案。6.1 坑TS 类型在构建后丢失__brand信息现象本地开发一切正常SkillId类型校验有效但部署到生产环境后const id: SkillId test as SkillId;竟然能通过运行时校验导致路由匹配失败。根因TypeScript 的品牌化类型string { __brand: SkillId }是纯编译期概念构建后的 JavaScript 中__brand字段被完全擦除。而我们的core-gateway在运行时用typeof id string做基础校验失去了类型保护。解决方案用 runtime brand 检查替代编译期 brand。在libs/agent-skills/src/lib/common-types.ts中export class SkillId { private readonly __brand: SkillId SkillId; constructor(public readonly value: string) { if (!value || typeof value ! string) { throw new Error(SkillId must be non-empty string); } } toString() { return this.value; } } export const createSkillId (value: string): SkillId new SkillId(value); // 运行时校验 export const isSkillId (value: unknown): value is SkillId value instanceof SkillId;这样SkillId变成一个真实存在的类构建后仍保留instanceof检查能力。所有技能调用前强制执行if (!isSkillId(skillId)) { throw new ValidationError(Invalid skillId, { code: INVALID_SKILL_ID }); }6.2 坑Nx 的--with-deps导致循环依赖误报现象在apps/core-gateway中引用libs/agent-skills同时libs/agent-skills又需要引用libs/shared-utils含日志工具。执行nx build core-gateway --with-deps时Nx 报错“Circular dependency detected: libs/agent-skills - libs/shared-utils - apps/core-gateway”。根因--with-deps会递归构建所有依赖项而shared-utils又依赖core-gateway的配置如环境变量读取形成隐式循环。解决方案严格分层禁止跨层引用。定义三层架构libs/agent-skills契约层只依赖types/node,zod绝不引用任何业务代码libs/shared-utils工具层只依赖types/node,lodash可被所有层引用apps/core-gateway应用层可引用agent-skills和shared-utils但agent-skills不能反向引用它。在nx.json中配置implicitDependenciesimplicitDependencies: { package.json: { dependencies: *, devDependencies: * }, libs/agent-skills/tsconfig.json: { libs/agent-skills: * } }6.3 坑Zod schema 与 TypeScript 类型不同步现象修改zodschema 增加字段但忘记更新z.infer类型导致OrderCancellationInput缺少新字段技能实现中访问input.newField时 TS 不报错运行时报undefined。根因z.infer是类型层面的推导不校验运行时 schema 是否匹配。解决方案用zod-to-json-schema生成 schema 并 diff。在 CI 中添加pnpm exec zod-to-json-schema libs/agent-skills/src/lib/order-cancellation.ts temp-schema.json git diff --no-index --quiet schema.json temp-schema.json || (echo Zod schema mismatch! exit 1)6.4 坑semantic-release 发布后Nx 缓存导致本地构建失败现象agent-skills发布 v2.0.0core-gateway更新package.json中的版本号但nx build core-gateway仍使用旧版类型编译失败。根因Nx 默认启用cacheDirectory缓存了旧版node_modules/my-org/agent-skills。解决方案在nx.json中配置cacheableOperationscacheableOperations: [build, test], targetDependencies: { build: [ { target: build, projects: dependencies } ] }并强制 CI 清理缓存nx reset pnpm install nx build core-gateway6.5 坑团队成员绕过 agent-skills直接写硬编码技能现象新入职工程师在apps/core-gateway/src/skills/order-cancel.ts中直接实现技能不引用libs/agent-skills导致类型不一致后续集成失败。根因缺乏强制约束机制。解决方案用 ESLint 规则封死后门。在.eslintrc.json中添加rules: { no-restricted-imports: [ error, { patterns: [ { group: [./src/skills/*], message: Skills must be defined in libs/agent-skills, not in apps/ } ] } ] }并在 CI 中运行pnpm exec eslint apps/core-gateway/**/*.{ts,tsx} --fix这些坑每一个都曾让我们团队连续加班 36 小时。现在它们都变成了自动化检查的一部分——不是靠人盯而是靠机器守。7. 未来演进agent-skills 如何支撑 AI 原生架构agent-skills当前聚焦于类型契约但这只是起点。结合 TypeScript 5.0 的新特性以及 Nx 17 的拓扑增强它正在向更深层演进。7.1 类型即文档用 JSDoc 自动生成 OpenAPI我们正在实验在OrderCancellationInput接口上添加 JSDoc/** * openapi * components: * schemas: * OrderCancellationInput: * type: object * required: [orderId, cancellationReason] * properties: * orderId: *
返回列表