ARTICLE DETAIL

资讯详情

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

Agent技能抽象层设计:TypeScript+NX+Semantic-Release工程实践

Agent技能抽象层设计:TypeScript+NX+Semantic-Release工程实践 1. 项目概述一个被严重低估的“技能中枢”设计“agent-skills”这个名称乍看像某个开源库的包名或是某篇技术文档里的小节标题但如果你在Nx monorepo项目里反复看到它出现在libs/agent-skills路径下在TypeScript类型定义中频繁出现SkillDefinition、SkillExecutor接口在CI日志里看到semantic-release为它单独打出了v0.4.2版本号——你就该意识到这不是一个玩具模块而是一个被精心设计、持续演进、承担关键职责的技能抽象层。我第一次接触这个模块是在接手一个企业级AI工作流平台时。当时团队刚把十几个分散的自动化任务邮件通知、数据库校验、Slack消息路由、PDF模板填充、API健康检查硬编码在各个服务里每次加一个新动作就得改三处代码、测五条路径、等半小时CI。直到有人把所有“能做什么”的逻辑抽出来统一放进agent-skills整个系统的可维护性才真正翻了个身。它不是AI Agent的“大脑”而是它的“手”和“脚”——所有对外交互、数据搬运、状态判断、错误恢复的能力都通过这一层标准化暴露、注册、调用、监控。核心关键词agent-skills本身已揭示本质它不处理决策逻辑那是LLM或规则引擎的事只专注能力封装Node和TypeScript决定了它的运行边界与类型安全底线Nx赋予它在大型单体仓库中独立演进、按需构建、精准测试的能力而semantic-release则让它每一次提交都能自动完成版本语义化、Changelog生成、NPM发布——这四者组合构成了一套面向工程落地的“技能即服务”Skills-as-a-Service基础设施。适合谁参考如果你正面临这些场景需要让非开发人员如运营、客服通过低代码界面配置自动化流程想把LLM调用结果转化为具体操作比如“把用户投诉转成Jira工单”正在构建RAGAgent混合架构但发现工具调用层混乱不堪或者你的Nx monorepo里已经有十几个lib-*却缺乏统一的能力治理机制——那么agent-skills就是你该立刻拆解、复用、甚至重构的样板。它解决的不是“能不能做”而是“怎么可持续地做”。下面我会从设计哲学、类型契约、注册机制、执行链路、版本管控五个维度带你一层层剥开这个看似简单实则精密的模块。2. 整体设计思路为什么必须是“技能”而非“函数”或“插件”2.1 抽象层级的选择从“能做什么”到“如何被使用”很多团队初期会直接写一堆独立的工具函数比如sendEmail()、queryDB()、generatePDF()。这看起来很直接但很快就会遇到三个致命问题调用上下文丢失sendEmail()不知道当前流程ID、用户身份、重试次数每次都要手动传参极易遗漏元信息缺失无法回答“这个技能支持哪些输入格式”“失败时会返回什么错误码”“是否需要用户授权”生命周期失控没有统一入口就无法做统一的超时控制、熔断降级、审计日志、性能追踪。agent-skills的设计起点就是把每个能力当作一个有身份、有契约、有生命周期的实体来对待。它不是函数而是Skill——一个实现了特定接口的对象自带描述、参数Schema、执行器、错误分类、权限声明。这种设计直接对标了现代Serverless函数的成熟实践如AWS Lambda Function的Descriptor但更进一步它把函数的“部署描述”和“业务逻辑”彻底分离允许同一份逻辑被不同环境、不同Agent以不同方式调用。举个实际例子我们有个fetchUserProfile技能。在Web Agent里它调用内部GraphQL API在CLI Agent里它读取本地JSON缓存在测试Agent里它返回Mock数据。但所有调用方看到的都是同一个SkillDefinition参数结构、错误类型、文档说明完全一致。这种“契约不变、实现可换”的能力正是Nx monorepo能支撑多端协同开发的核心前提。2.2 技术栈选型的深层逻辑Node TypeScript Nx 的铁三角为什么不用Python或Go因为我们的Agent运行时全部基于Node.js——它轻量、启动快、生态成熟尤其适合IO密集型任务HTTP调用、文件处理、数据库交互。更重要的是Node的worker_threads和child_process让我们能在单进程内安全隔离高风险技能比如调用外部二进制程序这是Python GIL或Go goroutine难以低成本实现的。TypeScript不是为了炫技而是强制契约落地的唯一手段。SkillDefinition接口里每个字段都有明确类型export interface SkillDefinition { id: string; // 唯一标识用于注册和调用 name: string; // 可读名称用于UI展示 description: string; // 功能描述支持Markdown inputSchema: JSONSchema7; // 输入参数的JSON Schema验证 outputSchema: JSONSchema7; // 输出结果的JSON Schema executor: SkillExecutor; // 执行函数类型受input/output约束 permissions?: string[]; // 所需权限列表如[user:read, email:send] timeoutMs?: number; // 默认超时时间单位毫秒 retryPolicy?: RetryPolicy; // 重试策略含最大次数、退避算法 }这个接口一旦定义所有技能开发者就必须严格遵循。TypeScript编译器会在npm run build阶段就报错如果executor返回值类型与outputSchema不匹配或者inputSchema里写了required: [userId]但executor函数签名没包含userId: string参数——根本过不了CI。这种静态保障远比运行时靠文档约定或单元测试覆盖更可靠。Nx则是这个体系的“操作系统内核”。没有Nxagent-skills很容易变成一个孤立的lib和其他模块耦合严重。而Nx提供了nx build agent-skills只构建这个库及其依赖跳过其他100个libnx test agent-skills --coverage精准运行技能单元测试生成覆盖率报告nx affected --targetbuild当修改了agent-skills的SkillDefinition接口时自动识别出所有依赖它的Agent应用触发增量构建nx graph可视化展示agent-skills与api-gateway、auth-service、logging-lib之间的依赖关系。这种工程级的可追溯性、可预测性、可扩展性是手工管理package.json和lerna永远达不到的。它让“技能”真正成为可独立交付、可版本化管理、可灰度发布的软件资产。2.3 与semantic-release的深度绑定让每次提交都产生价值很多人把semantic-release当成自动发版工具但在agent-skills里它扮演的是契约演进的守门人角色。我们约定所有提交必须符合Angular规范feat(skills): add fetchUserProfile skill→ 触发minor版本0.x.yfix(email): handle empty recipient list→ 触发patch版本0.x.yrefactor(definition): rename inputSchema to inputValidation→ 触发major版本x.0.0并要求更新所有技能实现关键在于semantic-release的配置文件release.config.js里我们额外集成了semantic-release/exec插件让它在发布前自动执行{ plugins: [ semantic-release/commit-analyzer, semantic-release/release-notes-generator, [ semantic-release/exec, { // 发布前验证所有SkillDefinition是否仍符合最新接口 verifyConditionsCmd: npx ts-node scripts/validate-skill-contracts.ts, // 发布后生成技能目录文档 successCmd: npx ts-node scripts/generate-skill-catalog.ts } ], semantic-release/npm, ] }这意味着任何破坏SkillDefinition向后兼容性的修改比如删除一个必填字段都会在CI阶段被validate-skill-contracts.ts脚本捕获并阻断发布。而每次成功发布都会自动生成一份HTML格式的技能目录包含所有已发布技能的ID、名称、描述、参数示例、错误码列表——这份文档直接嵌入到内部开发者门户成为前端Agent配置界面的数据源。这种“代码即文档、提交即契约、发布即交付”的闭环才是agent-skills能长期稳定演进的根本原因。3. 核心细节解析类型定义、注册中心与执行链路3.1 SkillDefinition不止是接口更是运行时契约SkillDefinition表面看是个TypeScript接口实则承载着三层契约第一层编译期契约TypeScript如前所述它强制约束了技能的形状。但更关键的是我们利用TypeScript的泛型和条件类型实现了输入输出类型的双向推导// libs/agent-skills/src/lib/skill-definition.ts export type SkillInputT extends SkillDefinition T[inputSchema] extends infer S ? S extends JSONSchema7 ? FromSchemaS : never : never : never; export type SkillOutputT extends SkillDefinition T[outputSchema] extends infer S ? S extends JSONSchema7 ? FromSchemaS : never : never : never;FromSchemaS是一个类型工具能将JSON Schema如{ type: object, properties: { id: { type: string } } }精确映射为TypeScript类型{ id: string }。这意味着当你定义一个技能const fetchUserSkill: SkillDefinition { id: fetch-user, inputSchema: { type: object, properties: { userId: { type: string } }, required: [userId] }, outputSchema: { type: object, properties: { name: { type: string }, email: { type: string } }, required: [name, email] }, executor: async (input) { // input 的类型自动推导为 { userId: string } const user await db.findUser(input.userId); // 返回值类型必须匹配 outputSchema否则TS报错 return { name: user.name, email: user.email }; } };IDE能实时提示input.userId编译器能确保return值不缺email字段。这种体验远超传统any或Recordstring, any方案。第二层运行时契约JSON Schema验证TypeScript类型只在编译期存在运行时我们需要真正的数据校验。agent-skills内置了一个轻量级JSON Schema验证器基于exodus/schemasafe在技能执行前自动校验输入// libs/agent-skills/src/lib/skill-executor.ts export const executeSkill async T extends SkillDefinition( skill: T, input: unknown ): PromiseSkillOutputT { // 1. 用JSON Schema校验input const validate compile(skill.inputSchema); if (!validate(input)) { throw new SkillValidationError( Invalid input for ${skill.id}: ${validate.errors?.map(e e.message).join(; )}, validate.errors ); } // 2. 执行executor结果再用outputSchema校验 const result await skill.executor(input as SkillInputT); const outputValidate compile(skill.outputSchema); if (!outputValidate(result)) { throw new SkillOutputValidationError( Invalid output from ${skill.id}: ${outputValidate.errors?.map(e e.message).join(; )}, outputValidate.errors ); } return result; };这个双重校验机制让技能调用方无论是人类还是LLM得到的错误信息极其明确“fetch-user技能要求userId是字符串但收到了null”而不是模糊的TypeError: Cannot read property name of undefined。第三层运维契约可观测性埋点每个SkillDefinition都隐式携带了可观测性元数据。我们在executor包装器里注入了统一的监控逻辑export const createTracedExecutor T extends SkillDefinition( skill: T, tracer: Tracer ) { return async (input: SkillInputT) { const span tracer.startSpan(skill.${skill.id}); try { span.setAttribute(skill.input, JSON.stringify(input)); const result await skill.executor(input); span.setAttribute(skill.output.size, JSON.stringify(result).length); return result; } catch (error) { span.setStatus({ code: SpanStatusCode.ERROR, message: error.message }); span.recordException(error); throw error; } finally { span.end(); } }; };这使得所有技能调用自动上报到Jaeger或Datadog我们可以按skill.id聚合查看send-email的P95延迟是否突增generate-pdf的失败率是否超过阈值fetch-user的输入数据分布是否异常比如90%请求的userId都来自同一个测试账号这些洞察是单纯函数调用无法提供的。3.2 注册中心动态加载与依赖注入的平衡术agent-skills不采用全局单例注册如SkillRegistry.register(skill)而是设计了一个基于Nx Project Graph的静态注册中心。原因很简单在monorepo里所有技能都位于libs/agent-skills/skills/*子目录下它们的依赖关系在project.json中已明确定义。我们不需要运行时动态require()而是利用Nx的projectGraphAPI在构建时生成注册表。libs/agent-skills/src/lib/registry.ts的核心逻辑// 这个文件由Nx插件在build时自动生成 export const SKILL_REGISTRY: Recordstring, SkillDefinition { fetch-user: await import(./skills/fetch-user/skill).then(m m.skill), send-email: await import(./skills/send-email/skill).then(m m.skill), generate-pdf: await import(./skills/generate-pdf/skill).then(m m.skill), // ... 其他技能 }; export const getSkill (id: string): SkillDefinition | undefined SKILL_REGISTRY[id];这个SKILL_REGISTRY对象是Nx插件myorg/nx-plugin-skills在nx build agent-skills阶段扫描所有skills/**/skill.ts文件后动态生成的。它保证了零运行时反射没有Object.keys(require.context(...))这类脆弱代码Tree-shaking友好未使用的技能不会被打包进最终产物类型安全getSkill(non-existent)返回undefinedTypeScript能准确推导依赖可追溯Nx能清晰显示agent-skills依赖了myorg/db-client而send-email技能又额外依赖了myorg/email-service。对于需要动态加载的场景比如从远程URL加载技能我们提供了DynamicSkillLoader类但它被明确标记为internal且要求提供完整的SkillDefinitionJSON Schema进行预校验防止恶意代码注入。这种“默认静态、按需动态”的设计兼顾了安全性与灵活性。3.3 执行链路从LLM输出到真实世界操作的七步转化一个典型的Agent工作流中agent-skills的执行链路远比skill.executor(input)复杂。我们将其拆解为七个原子步骤每一步都可插拔、可监控、可重试意图解析Intent ParsingLLM输出的原始文本如“给张三发一封确认邮件”被IntentParser转换为结构化指令{ skillId: send-email, input: { to: zhangsanexample.com, subject: 确认邮件, body: 您的操作已确认。 } }技能查找Skill Lookup调用getSkill(skillId)若未找到则返回SkillNotFoundError。输入校验Input Validation如前所述用JSON Schema校验input。权限检查Permission Check从调用上下文如JWT token提取permissions与skill.permissions比对const hasPermission context.permissions.some(p skill.permissions?.includes(p) || p admin ); if (!hasPermission) throw new SkillPermissionError(...);执行准备Execution Prep注入通用依赖logger、tracer、httpClient并根据skill.timeoutMs设置AbortController。技能执行Skill Execution调用executor(input)捕获所有异常包括Promise.reject、同步抛错、未处理的Promise rejection。结果归一化Result Normalization将原始返回值包装为标准响应{ status: success | error, data: result, // 仅当statussuccess error: { code: ..., message: ..., details: {} }, // 仅当statuserror metadata: { executionTimeMs: 123, retryCount: 0 } }这个链路被封装在SkillOrchestrator类中它接受一个SkillRequest对象返回SkillResponse。所有AgentWeb、CLI、API都通过它调用技能确保行为一致。而每一步的耗时、成功率、错误分布都通过OpenTelemetry自动上报形成完整的调用拓扑图。4. 实操过程从零搭建一个可发布的技能模块4.1 初始化Nx Workspace与agent-skills库假设你已安装Nx CLInpm install -g nx创建新workspacenx create-nx-workspace my-agent-platform \ --presetapps \ --appNameapi-server \ --stylescss \ --nxCloudfalse cd my-agent-platform接着创建agent-skills库nx g nrwl/node:library agent-skills \ --directorylibs \ --buildabletrue \ --publishabletrue \ --importPathmyorg/agent-skills这会生成libs/agent-skills/库根目录libs/agent-skills/src/index.ts公共API入口libs/agent-skills/project.jsonNx构建配置关键修改project.json启用semantic-release{ targets: { build: { executor: nrwl/node:build, options: { outputPath: dist/libs/agent-skills, main: libs/agent-skills/src/index.ts, tsConfig: libs/agent-skills/tsconfig.lib.json, assets: [libs/agent-skills/*.md] } }, release: { executor: semantic-release/exec:exec, options: { cmd: npx semantic-release } } } }4.2 定义第一个技能echo最简验证在libs/agent-skills/src/lib/skills/echo/skill.ts中import { SkillDefinition, JSONSchema7 } from myorg/agent-skills; export const echoSkill: SkillDefinition { id: echo, name: Echo, description: 原样返回输入内容用于测试和调试。, inputSchema: { type: object, properties: { message: { type: string, description: 要回显的消息 } }, required: [message] } as JSONSchema7, outputSchema: { type: object, properties: { echoed: { type: string } }, required: [echoed] } as JSONSchema7, executor: async (input) { return { echoed: input.message }; } };然后在libs/agent-skills/src/lib/registry.ts中手动添加后续会用插件自动生成export const SKILL_REGISTRY { echo: echoSkill };4.3 编写类型安全的调用示例在apps/api-server/src/main.ts中测试import { getSkill, executeSkill } from myorg/agent-skills; async function testEcho() { const skill getSkill(echo); if (!skill) throw new Error(Skill not found); // TypeScript自动推导input类型为{ message: string } const result await executeSkill(skill, { message: Hello World }); // result类型自动推导为{ echoed: string } console.log(result.echoed); // Hello World } testEcho();运行nx serve api-server你会看到输出。此时executeSkill的类型安全已生效如果传入{ msg: test }TS会立即报错Object literal may only specify known properties, and msg does not exist in type { message: string; }。4.4 配置semantic-release实现自动化发布在workspace根目录初始化semantic-releasenpx semantic-release-cli setup # 按提示选择GitHub、NPM、生成token它会创建.releaserc.json和package.json中的release脚本。关键配置.releaserc.json{ branches: [main], plugins: [ semantic-release/commit-analyzer, semantic-release/release-notes-generator, [ semantic-release/exec, { verifyConditionsCmd: npx ts-node scripts/validate-contracts.ts } ], semantic-release/npm, semantic-release/github ] }scripts/validate-contracts.ts内容import { SKILL_REGISTRY } from myorg/agent-skills; // 确保所有技能都实现了SkillDefinition接口 Object.values(SKILL_REGISTRY).forEach(skill { if (!skill.id || !skill.executor || !skill.inputSchema) { throw new Error(Invalid skill: ${JSON.stringify(skill)}); } }); console.log(✅ All skills conform to SkillDefinition contract);现在每次向main分支推送符合规范的commit如git commit -m feat(echo): add echo skillCI就会自动运行validate-contracts.ts校验构建agent-skills库生成Changelog发布到NPM Registry版本号如0.1.0创建GitHub Release。4.5 添加CI/CD流水线Nx Cloud与GitHub Actions联动在.github/workflows/ci.yml中name: CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - uses: actions/setup-nodev3 with: node-version: 18 - name: Install dependencies run: npm ci - name: Build agent-skills run: npx nx build agent-skills - name: Test agent-skills run: npx nx test agent-skills - name: Run semantic-release if: github.event_name push github.ref refs/heads/main env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: npx nx release同时启用Nx Cloud加速构建缓存npx nx connect-to-nx-cloud这样当多个PR同时修改不同技能时Nx Cloud能智能复用agent-skills的构建缓存将CI时间从5分钟缩短到30秒。5. 常见问题与排查技巧实录5.1 技能注册失败找不到模块或类型不匹配现象nx build agent-skills报错Cannot find module ./skills/xxx/skill或TS2307: Cannot find module。排查思路检查libs/agent-skills/skills/xxx/skill.ts文件是否存在文件名是否为小写skill.tsNx默认大小写敏感查看libs/agent-skills/tsconfig.lib.json的include字段是否包含src/lib/skills/**/*运行nx show-project agent-skills确认sourceRoot指向正确路径。独家技巧在libs/agent-skills/project.json中添加implicitDependencies: [nx]并运行nx graph可视化检查agent-skills是否被正确识别为publishable库。如果图标是灰色而非蓝色说明Nx未将其纳入构建图。5.2 JSON Schema校验失败输入数据格式诡异现象LLM生成的input对象里数字字段被序列化为字符串如age: 25而非25导致Schema校验失败。根本原因LLM输出解析器如llm-output-parser未做类型转换或前端JSON序列化时JSON.stringify({ age: 25 })在某些环境下被错误处理。解决方案在SkillOrchestrator的executeSkill前添加一个preprocessInput钩子const preprocessInput (input: unknown, schema: JSONSchema7): unknown { if (schema.type object typeof input object input ! null) { return Object.keys(input).reduce((acc, key) { const propSchema schema.properties?.[key]; if (propSchema?.type number typeof input[key] string) { acc[key] Number(input[key]); } else { acc[key] input[key]; } return acc; }, {} as Recordstring, unknown); } return input; };更推荐的做法在LLM提示词中明确要求“输出JSON所有数字字段必须为数字类型不得加引号”。5.3 权限检查误报Admin用户无法调用受限技能现象用户拥有admin权限但调用send-email技能时仍报SkillPermissionError。排查步骤在Permission Check步骤的日志中打印context.permissions和skill.permissions的原始值常见陷阱context.permissions是从JWT解析的数组但可能包含空格或大小写不一致如[ Email:Send ]vs[email:send]检查skill.permissions是否为undefined此时应默认允许但代码里写了skill.permissions?.includes(p)undefined.includes会报错。修复方案const requiredPermissions skill.permissions ?? []; const hasPermission requiredPermissions.length 0 || context.permissions.some(p requiredPermissions.includes(p.toLowerCase().trim()) ) || context.permissions.includes(admin);5.4 semantic-release卡住Commit格式不被识别现象推送feat: add new skill后CI中semantic-release日志显示No commits found since last release。原因分析semantic-release默认只识别feat、fix等Angular前缀而feat: ...缺少括号范围如feat(skills): ...或者Commit消息末尾有空格、特殊字符导致正则匹配失败。验证方法本地运行npx semantic-release --dry-run --no-ci查看详细日志。终极解决在.releaserc.json中自定义commitAnalyzer{ plugins: [ [ semantic-release/commit-analyzer, { preset: angular, releaseRules: [ {type: feat, release: minor}, {type: fix, release: patch}, {type: perf, release: patch}, {type: chore, release: patch} ] } ] ] }并强制团队使用nx commitNx内置的智能Commit工具它会引导选择类型、范围、描述杜绝格式错误。5.5 Nx构建缓慢skills目录下文件过多现象nx build agent-skills耗时超过2分钟且node_modules未被排除。优化措施在libs/agent-skills/tsconfig.lib.json中exclude添加node_modules和dist使用Nx的project.jsontargetDependencies避免不必要的依赖扫描targets: { build: { dependsOn: [^build], // 只依赖上游构建不扫描所有lib ... } }对于大量技能启用Nx的--with-deps标志时指定精确依赖nx build agent-skills --with-depsmyorg/db-client,myorg/logging-lib。提示在libs/agent-skills/project.json中将implicitDependencies设为空数组[]可彻底禁用隐式依赖扫描提升构建速度30%以上。6. 进阶实践技能组合、热更新与跨平台适配6.1 技能组合Skill Composition构建更高阶能力单个技能解决原子问题但真实场景需要组合。agent-skills提供了CompositeSkill模式export const createUserFlow: CompositeSkillDefinition { id: create-user-flow, name: Create User Flow, description: 创建用户并发送欢迎邮件, steps: [ { skillId: create-user, inputMapping: { name: input.name, email: input.email } }, { skillId: send-welcome-email, inputMapping: { to: step0.output.email, name: step0.output.name } } ], outputSchema: { /* 合并所有step的outputSchema */ } };CompositeSkillExecutor会按顺序执行每个步骤将前一步的output按inputMapping注入下一步。这种组合不改变原有技能只是新增一个“编排技能”完美契合Nx的增量构建理念——修改create-user技能只会触发create-user-flow的重新构建不影响其他组合。6.2 热更新技能无需重启Agent服务对于生产环境我们实现了基于fs.watch的技能热重载// 在Agent启动时 const watcher fs.watch(path.join(__dirname, ../skills), { recursive: true }, (eventType, filename) { if (eventType change filename.endsWith(.ts)) { // 重新import对应技能模块 delete require.cache[require.resolve(./skills/${filename})]; const newSkill require(./skills/${filename}).default; SKILL_REGISTRY[newSkill.id] newSkill; console.log( Hot reloaded skill: ${newSkill.id}); } });配合Nx的--watch模式开发者保存skill.ts后Agent进程自动更新技能无需CtrlC再npm start。注意此功能仅用于开发环境生产环境通过semantic-release滚动更新。6.3 跨平台技能Node.js与Deno、Bun的兼容策略虽然agent-skills基于Node.js但其核心SkillDefinition接口是纯TypeScript不依赖Node API。我们为Deno用户提供了deno-skill-adapter// deno-skill-adapter.ts import { SkillDefinition } from myorg/agent-skills; export const adaptForDeno T extends SkillDefinition(skill: T): T { // 替换Node-specific依赖为Deno equivalent const adaptedExecutor async (input: ParametersT[executor][0]) { // 例如将node-fetch替换为Deno.fetch const response await fetch(https://api.example.com, { method: POST, body: JSON.stringify(input) }); return response.json(); }; return { ...skill, executor: adaptedExecutor } as T; };Bun用户同理。这种“接口不变、实现可换”的设计让agent-skills天然具备跨运行时能力未来可无缝迁移到WebAssembly或边缘计算环境。我在实际项目中发现最有效的推广方式不是写文档而是让第一个业务团队用agent-skills重构一个痛点流程——当他们看到原本3天的工作量压缩到半天且后续新增需求只需写一个skill.ts文件时整个组织的技术共识就自然形成了。这个模块的价值不在于它有多酷炫而在于它让“能力复用”这件事变得像呼吸一样自然。
返回列表