ARTICLE DETAIL

资讯详情

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

Agent技能体系实战:构建可落地的agent-skills框架

Agent技能体系实战:构建可落地的agent-skills框架 这两年做 AI Agent 相关项目我踩得最深、也最绕不开的一个问题就是怎么让 LLM 智能体真正学会“用工具干活”。如果你也搞过基于 LLM 的 Agent 开发大概率会对agent-skills这个词不陌生——它正在被越来越多的团队当成“给智能体写技能”的体系化方案来讨论。说白了它就是一套让 LLM 知道“什么场景该调什么工具、参数怎么给、失败了怎么处理”的完整机制而不是简单地把几个函数扔给模型。简单说agent-skills 要解决两件大事一是 LLM 本身只会生成文本天生不懂怎么稳定地调用外部 API二是当技能数量越来越多时代码结构、上下文管理、权限控制会迅速失控最后变成“demo 能跑、生产难上”。这篇文章我会从技能定义规范、注册加载机制、调度引擎设计、实战复现到问题排查完整拆解一套可落地的 Agent 技能体系适合正在做 Agent 应用、想从“能跑”过渡到“架构能用”的开发者参考。1. agent-skills 的核心为什么智能体需要一套“技能体系”1.1 一个始终绕不开的痛点LLM 与工具之间隔着鸿沟先说个很基础但经常被忽略的事实LLM 本身是一个文本生成模型你问它问题它给你输出文字但如果你想让 Agent 去查订单、发邮件、改数据库它不能直接操作外部系统。行业内最常见的做法是借助各家模型服务商的 function calling / tool calling 能力把一批工具以 JSON Schema 的格式塞给模型让模型在回复中夹带一个结构化的“调用意图”然后由后端代码去真正执行。这个思路没问题可一旦工具数量超过一定阈值问题就来了。我见过不少项目初期只有三五个函数时跑得顺顺当当等业务一扩张技能列表膨胀到二十几个模型开始频繁“选择困难”明明该查订单却调了退款的接口参数张冠李戴甚至把两个毫不相关的工具串起来执行。最头疼的是代码层面每个工具函数都有自己的参数校验、错误处理、权限检查逻辑散落得到处都是维护成本直接翻倍。所以 agent-skills 本质上是把“工具函数”升级成“技能skill”。一个技能不再是孤立的函数实现而是由元数据、输入输出约定、前置条件、依赖策略、错误恢复逻辑共同组成的一个独立单元。LLM 只负责“决策”框架负责“执行”两边通过一套统一协议对话才不会越扯越乱。1.2 从一个实际业务出发技能库到底解决什么问题拿一个真实场景来讲假设你在做一个电商客服 Agent它至少需要这几个能力——查订单、处理退换货、计算运费、发工单、查库存。如果按老办法你得在 system prompt 里写一大段“你可以使用以下工具”然后把五个函数的 Schema 全贴进去。一开始好像也够用但用户一旦问出这种问题“我上周买的手机订单到哪了如果还没发货能帮我申请退款吗”这个请求就同时涉及两个技能查订单状态、申请退款。模型要先看懂第一句话要调 query_order第二句话要调 refund_apply而且退款前还得先确认订单状态。这件事让模型裸做虽然能跑通但很容易出错——比如它根据“退款”就把整个订单信息填进了退款申请连校验都没做。换成 agent-skills 的思路你需要做的是把 query_order 和 refund_apply 都封装成标准技能各自带着清晰的描述和参数约束调度引擎负责接收用户消息先定位到“订单查询”和“售后申请”两个候选技能再按顺序编排执行。模型只做选择题参数校验、依赖判断和异常兜底全部由技能层接管。这样整个系统的稳定性和可维护性和“把所有逻辑都压在 prompt 里”完全不是一个级别。2. 技能定义规范与统一接口给每个技能立规矩2.1 一份可落地的技能 Schema 设计技能规范是整个 agent-skills 的地基。我建议每个技能都用一份统一的 JSON Schema 来声明字段不需要多但每个字段都得有明确用途。我目前常用的模板长这样{ skill_name: query_order, description: 根据订单号查询订单状态、金额、物流信息, input_schema: { type: object, properties: { order_id: { type: string, description: 订单号例如 20250120123456必填 }, with_logistics: { type: boolean, description: 是否同时返回物流轨迹默认 false, default: false } }, required: [order_id] }, state_requirements: [user_authenticated], timeout_ms: 3000, retry: { max_attempts: 2, backoff_ms: 300 } }逐个字段讲一下设计的理由。skill_name是技能的唯一 ID命名建议用“动词_对象”的格式比如 query_order、apply_refund、create_ticket这样模型在阅读候选列表时能快速理解语义。description是写给模型看的不是写给代码看的——它一定要写清楚“这个技能在什么场景下用”甚至可以加一句“绝对不要在什么场景下用”等下我会展开讲。input_schema是模型生成参数时的约束边界里面每个字段的 description 也都很讲究必须包含“示例值”因为模型对具体例子的理解能力远远强于抽象描述。state_requirements是前置状态校验比如查订单前必须先确认用户已完成登录授权不然技能执行到一半才会发现没权限白白浪费一次调用。timeout_ms是给技能执行的硬性上限防止某个下游 API 卡住把整个 Agent 主循环拖死。retry则是针对瞬时错误的自动重试配置和超时配合使用基本能覆盖大部分网络抖动场景。2.2 函数实现与技能元数据分离一套代码多个模型通用定义好 Schema 之后还要解决一个重要问题同一个技能库怎么做到在不同 LLM 之间复用今天你可能用 OpenAI 的 GPT 系列明天可能换成 Claude或者某个开源模型总不能每换一个模型就重写一套技能逻辑。我的做法是把技能拆成两层元数据层和执行层。元数据层就是上面那份 JSON Schema它只负责告诉模型“有什么技能、参数长什么样”执行层是一段普通的 Python 函数只认输入字典、返回输出字典完全不关心这个参数是怎么被模型生成的。两者之间用一个统一接口对接# 统一技能接口输入 dict输出 dict def query_order_executor(params: dict) - dict: order_id params[order_id] with_logistics params.get(with_logistics, False) # 这里调用真实订单服务... return { status: ok, data: { order_id: order_id, status: SHIPPED, amount: 3999.00, logistics: [...] } }这个设计有什么好处第一底层模型随便换技能执行层的代码一行都不用动只要模型供应商支持 function calling就能把元数据单独抽出来喂给它。第二测试变得极其简单你可以脱离 LLM直接用构造好的参数调执行层做纯函数级别的单元测试。第三未来做技能市场、技能共享也有基础——别人只要按这个协议写一个执行函数再配一份 schema就能被你的 Agent 框架识别。结合我自己的经验这个分离的架构看起来多了一层抽象但带来的维护收益是实打实的。早期我把函数实现和提示词里的工具描述混在一起写结果每次改业务逻辑都要重新调 prompt极其痛苦。现在改技能函数不影响提示词改描述词不会碰业务代码两边彻底解耦。2.3 参数校验与错误码规范别让报错飘进 system prompt技能的返回值也必须定规矩。我见过最糟糕的写法是把 Python 堆栈异常直接往回抛模型看到一堆Traceback (most recent call last)完全不知道怎么回应给用户。正确的做法是每个技能无论成功还是失败都返回一个统一结构的字典成功时{ status: ok, data: { ... } }失败时{ status: error, error_code: ORDER_NOT_FOUND, message: 订单号 20250120123456 不存在请提醒用户核对订单号 }这里面有个关键细节error_code是给框架看的用来做逻辑判断和告警message是给模型看的而且必须包含“可恢复的动作提示”。比如“订单号不存在建议用户核对后重试”就比“订单不存在”有用得多因为模型拿到前者会自动组织出“您核实一下订单号是不是 20250120123456我再帮您查”这类回复拿到后者可能就只能干巴巴地说“查不到”。参数校验要内置到技能执行器的入口处用 Python 的jsonschema库做一遍严格校验。校验失败时返回一个固定错误码比如INVALID_PARAMETER并明确指出是哪个字段不合法而不是把异常继续往上抛。这才叫“技能层的自我修养”。3. 技能注册与动态加载像插件一样组装能力3.1 注册器设计从一个项目里的技能目录说起当技能数量达到十几个之后最忌讳的做法是手动维护一张全量技能清单。每次新增技能都要改注册表、改前端展示、改模型提示词漏一步就是线上事故。更好的方式是采用“约定优于配置”的自动注册机制。我的目录结构一般是这样的agent_project/ core/ # 框架层注册器、调度器、上下文管理 skills/ # 业务技能层每个技能一个文件 __init__.py order_skills.py refund_skills.py logistics_skills.py runtime/ main.py # Agent 主循环技能文件里用装饰器标注比如# order_skills.py from core.skill_registry import skill skill def query_order(params: dict) - dict: 查询订单状态 ... skill def list_user_orders(params: dict) - dict: 列出用户最近订单 ...注册器启动时扫描skills/目录下所有带skill装饰器的函数自动收集它们的函数名和 docstring组装为技能元数据并校验 Schema 是否合法。这样新增技能只需要加一个文件、写一个装饰器注册、校验、生效全部自动完成省掉的脑力劳动相当可观。有人问我为什么不用全量 JSON 配置文件来声明技能。我的回答是配置文件可以和代码分离得很好但一旦技能数量多了配置散落在外部文件里反而容易出现“代码改了配置忘改”的错位问题。把技能声明和执行逻辑放在同一个文件里用装饰器绑定至少能保证改技能的人不会只看代码、不更新描述。3.2 多技能依赖与禁用按业务场景打包技能集技能注册完还要解决“选择性加载”的问题。一个全能 Agent 并不需要在所有场景下加载所有技能。比如一个客服机器人分售前、售中、售后多条线售前接待根本不需要“申请退款”技能你硬塞给它模型反而可能在用户抱怨贵的时候错误触发退款操作。我引入了“技能包skill pack”的概念。每个技能可以声明自己属于哪个包调度引擎按业务场景决定加载哪几个包。比如售前包商品详情查询、库存查询、优惠券计算售中包订单查询、修改地址、催发货售后包退款申请、退货登记、工单创建加载时只把当前业务场景对应的技能 Schema 暴露给模型不相关的技能一律不可见。这个设计既控制了上下文长度又可以降低模型误选率还能配合权限做到“售前 Agent 根本调不了退款接口”。如果技能之间有依赖关系——比如“计算违约金”必须先查“订单详情”——也可以在技能声明里加一个depends_on字段由调度层在编排阶段解析而不是让模型自己去猜。3.3 沙箱与超时保护让技能失败不砸整个 Agent技能执行的安全性和稳定性是生产环境和实验 demo 的分水岭。我见过不少 Agent 挂了不是模型出错而是技能函数里一个网络请求没有设置超时直接阻塞了整个主循环。所以我的框架里所有技能都会被一个统一的执行沙箱包裹每个技能调用都强制走超时控制Pythonasyncio里用asyncio.wait_for同步代码用线程池 Future 超时外部网络请求只允许访问白名单域名防止模型被诱导去请求内网或本地端口高风险技能比如执行命令、写支付单运行在一次性子进程里用完即销毁避免把宿主进程搞挂技能执行失败只向模型返回结构化错误不暴露底层堆栈和敏感环境信息。把这些安全手段类比成管理一个实习生你给他明确的任务书Schema、限定工作区域沙箱、要求定时汇报超时机制、出问题迅速召回结构化错误返回。如果为了图省事让他拿着公司内网权限到处跑那只要一次误操作就是一场事故。4. 调度引擎的工作原理模型做选择框架做执行4.1 两种主流调度方式全自动工具调用 vs 意图技能路由技能就绪之后调度引擎就是大脑。目前主流有两种做法。第一种是全量工具调用也就是把技能库里所有技能的 Schema 一股脑塞给模型让模型在生成时直接选择并返回工具调用参数。这种做法的好处是实现简单模型原生支持适合技能数量不超过 5 个的小场景坏处是技能一多上下文会被撑爆而且模型很容易在十几个相似技能面前犯迷糊。第二种是意图识别 技能路由这也是 agent-skills 更推荐的做法框架先把技能目录压缩成一张极简的“技能卡片列表”只包含技能名和一句话描述发给模型模型先定位出最相关的 2~3 个技能框架再从技能库里取出这几个技能的完整 Schema进行精准注入最后模型只在这几个候选里做参数填充和最终调用。为什么第二种更稳因为模型不需要一次性处理二十几份详细 Schema它先做粗筛再做细决策每一步的负担都小很多。而且这给了系统一个中间层——“路由层”你可以在路由结果里做权限校验、AB 策略、敏感技能拦截。如果某个用户没有退款权限路由阶段就直接把 refund_* 技能从候选里摘掉根本不会进到模型那一层。我个人建议一开始做 Agent 就用第二种方式搭建框架哪怕技能很少也无妨。因为从 5 个技能扩张到 50 个技能是必然的一个支持路由的架构可以平滑承载增长而纯靠全量工具调用的方案到后期只能推倒重来。4.2 路由层 Rerank 与组合编排多个技能如何协同完成一件事路由层也不能只按模型的一次输出拍板。我通常会给路由层加一个“强规则优先”机制有些技能和某些关键词有非常稳定的对应关系比如用户消息里出现“退款”“退货”路由层直接给出refund_apply作为硬候选然后再结合模型对完整意图的判断进行 Rerank把硬命中结果和模型候选做一次去重和加权。这样做的好处很明显模型偶尔抽风不要紧规则兜底能把最核心的路径拉回来。技能编排则更复杂一些。还拿“退款”举例正常流程是查订单详情 → 判断订单状态是否符合退款条件 → 计算可退金额 → 提交退款申请。这是一条技能链不是单次调用。我的框架支持用一份简单的“技能编排配置”描述这种链式关系{ name: refund_flow, steps: [ { skill: query_order, required: true, next: validate_refund_eligibility }, { skill: validate_refund_eligibility, required: true, next: calc_refund_amount }, { skill: calc_refund_amount, required: true, next: apply_refund }, { skill: apply_refund, required: true } ] }调度引擎按顺序执行这些步骤前一步的输出会作为上下文传给后一步进行参数补全。重要的一点是不要让模型一次性生成整条链的所有参数。每到一个新步骤框架会把前几步执行结果的关键字段收集成一个“状态摘要”和该技能的参数 Schema 一起交给模型让模型只填空。这样即使某一步失败也能准确定位到是哪个环节出了问题而不是让模型从一团乱麻里猜。4.3 上下文压缩与记忆保留控制在上下文窗口内的技能提示技能体系还有一个常被忽略的收益——上下文压缩能力。如果不做技能路由20 个技能的完整 Schema 加起来可能直接烧掉上下文窗口的三分之一留给真实对话的余量就少了。而做了路由 技能卡片后基础指令可能只占 800 token 以内完整技能 Schema 只在被选中后才注入这就能把更多的上下文预算留给多轮对话和业务理解。实际操作中我会对每轮对话维护一个“历史摘要 最近轮次原文”的双层结构超过 6 轮之前的内容压缩成摘要最近 3 轮保留完整原文。当调度引擎需要给模型补充上下文时优先提供技能执行结果组成的“事实卡片”而不是把所有历史消息一股脑塞回去。这个策略在长对话场景下非常有效尤其适合客服、销售助理这类需要持续多轮交互的业务能在不扩容模型的前提下延长有效会话轮次。5. 实操演练从零搭一个低配版 agent-skills5.1 搭建目录与核心代码骨架理论讲完上点能直接跑的东西。我带你手写一个极简版 agent-skills 框架麻雀虽小五脏俱全主要包含三个部分技能装饰器、注册器、Agent 主循环。完整目录结构如下mini_skills/ core/ __init__.py registry.py runner.py skills/ __init__.py order_skills.py agent.py test_agent.py先看注册器core/registry.pyfrom __future__ import annotations import inspect from typing import Callable, Dict class SkillRegistry: def __init__(self): self._skills: Dict[str, Callable] {} self._metadata: Dict[str, dict] {} def register(self, func: Callable): skill_name func.__name__ self._skills[skill_name] func self._metadata[skill_name] { skill_name: skill_name, description: func.__doc__ or 暂无描述, } return func def get_skill(self, name: str): return self._skills[name] def catalog(self): return [ {skill_name: name, description: m[description]} for name, m in self._metadata.items() ] registry SkillRegistry() def skill(func): return registry.register(func)再定义一个最简技能执行器core/runner.pyimport time from concurrent.futures import ThreadPoolExecutor, TimeoutError def run_with_timeout(func, params: dict, timeout_ms: int 3000): executor ThreadPoolExecutor(max_workers1) future executor.submit(func, params) try: return future.result(timeouttimeout_ms / 1000) except TimeoutError: return {status: error, error_code: TIMEOUT, message: 技能执行超时请稍后重试} finally: executor.shutdown(waitFalse)这个执行器只是框架的最小骨架但已经覆盖了统一入参、统一超时这两个核心约束。5.2 5 分钟接入两个业务技能在skills/order_skills.py里注册两个技能演示标准写法和 docstring 的重要性from core.registry import skill skill def query_order(params: dict) - dict: 根据订单号查询订单状态、金额、物流信息。当用户问订单到哪了、发货没有、商品状态时使用。 order_id params.get(order_id, ) if order_id 20250120123456: return {status: ok, data: { order_id: order_id, status: SHIPPED, logistics: 已到达【上海市浦东新区】配送站预计今天送达 }} return {status: error, error_code: ORDER_NOT_FOUND, message: f订单 {order_id} 不存在请提醒用户核对订单号} skill def calc_shipping_fee(params: dict) - dict: 根据商品重量和收货地址计算运费。当用户询问运费多少钱、配送费多少时使用。 weight_kg params.get(weight_kg, 0) city params.get(city, ) base_fee 8 if city in (北京, 上海, 广州, 深圳) else 12 total base_fee max(0, weight_kg - 1) * 2 return {status: ok, data: {shipping_fee: total}}注意两个技能的行为找不到订单时message 里带了明确的“用户侧动作建议”运费计算不依赖外部服务纯本地得出方便演示。5.3 跑通一条完整链路从用户提问到技能执行结果回填接下来是 Agent 主循环agent.py我在这里用一个简化版的模型选择逻辑来模拟 LLM 的能力而不是真的调用大模型 API——毕竟重点看框架结构from core.registry import registry from core.runner import run_with_timeout def model_choose_skill(user_input: str, catalog: list) - str: # 极简意图匹配实际项目里这里应该是 LLM 调用 if 运 in user_input or 运费 in user_input or 快递 in user_input: return calc_shipping_fee if 订单 in user_input or 到哪 in user_input or 发货 in user_input: return query_order return None def extract_params(user_input: str, skill_name: str) - dict: if skill_name query_order: return {order_id: 20250120123456} if skill_name calc_shipping_fee: return {weight_kg: 2.5, city: 上海} return {} def main(): user_input 我在京东买了一个手机订单号20250120123456现在到哪了运费多少钱 catalog registry.catalog() skill_name model_choose_skill(user_input, catalog) if not skill_name: print(Agent抱歉我没有找到对应技能) return params extract_params(user_input, skill_name) fn registry.get_skill(skill_name) result run_with_timeout(fn, params, timeout_ms3000) if result[status] ok: print(Agent技能执行成功结果是, result[data]) else: print(Agent技能执行失败原因是, result[message]) if __name__ __main__: main()这段代码跑起来会输出类似“Agent技能执行成功结果是{...}”这种格式。看起来很简单但它已经形成了“技能目录 → 选择技能 → 参数提取 → 统一执行 → 结果规范返回”的完整闭环。真实项目中你需要把model_choose_skill替换成真正的 LLM 决策层把extract_params改成由模型按 input_schema 生成参数再把执行结果回填给模型组织自然语言回复。整个架构不需要变。这里比较容易踩的坑是直接把技能执行结果盲目传给用户。正确做法是把结果 data 作为“上下文事实”交给模型让它用自然语言重新组织一遍还要结合对话历史补充语气和细节。比如“订单已到达上海配送站预计今天送达”这句话应该是模型生成的而不是技能库硬编码返回的。有一个细节值得强调技能本身不要承担“组织自然语言”的职责。技能只负责面向业务流程输出结构化事实语言表达是 LLM 的强项。一旦你把话术写死在技能里那这个技能就只能服务这一种话术风格换个“活泼客服”的人格就废了。始终保持技能层“纯业务、纯事实、纯结构化”的边界才能让上层有足够的自由度去适配不同对话风格。6. 常见问题与排查技巧实录6.1 模型就是不调用技能怎么办这是新手最常见的问题。症状是用户问“订单查一下”模型却回“好的我来帮您查询”然后就没有下文了——它压根没触发 function call。原因一般有三个技能描述里没有说明“何时调用”模型意识不到这个场景应该走工具参数 Schema 过复杂必填字段超过四五个模型一算成本高干脆放弃没有给示例模型不知道调用之后会返回什么。我的解决方案是在技能描述里加“正面触发词 负面抑制词”。比如 query_order 的描述改成“当用户询问任意订单状态、物流进程、发货/到货时间时使用仅在纯闲聊、不含任何订单语境时忽略。” 另外给每个技能配一个极简的 few-shot 示例包含一次完整的 JSON 调用示例。实测下来模型工具调用率会有明显提升。另外参数 Schema 能做得多简单就做多简单。必填参数尽量控制在 2 个以内其他字段全部给默认值。模型也是“懒”的它偏好生成更简单的调用如果你把一个技能设计成必填 6 个参数模型大概率会绕开它。6.2 技能调用参数张冠李戴怎么排查参数填错的问题是第二大高频故障。典型症状模型把用户名字填进 order_id 字段或者把商品金额填进数量字段。排查时我一般先看技能描述里的字段示例够不够明确。比如order_id的描述如果只写“订单号”模型不知道订单号长什么样改成“订单号例如 20250120123456数字长度为 14 位”之后准确率会立刻提升。如果描述已经够清楚还是填错那就在执行层加一道规则校验。比如order_id字段进入执行器后先做一个正则匹配不满足格式的直接返回INVALID_PARAMETER错误并给出参考格式。注意这种规则校验不是要和 LLM 对抗而是给它一个“及时反馈”的机会——模型在下一轮看到错误码后通常会自己修正参数再请求一次。6.3 超时、并发与资源泄漏的经验技能执行偶尔卡死、内存不断往上涨这是生产环境最隐蔽的问题。通常有这几个来源某个 API 客户端没有设置超时每次技能调用都新建 HTTP Client用完不关闭数据库连接池耗尽导致请求排队。框架层能兜底的就是我前面提到的统一超时机制但根本解决还要靠技能实现者自己注意资源释放。我习惯在技能装饰器里增加一个finally钩子统一释放可能持有的资源。另外要求所有外部 API 客户端必须使用连接池禁止在技能内手动 new client。还有一个用得上的技巧给技能执行加一个“重试熔断”机制连续失败 3 次后该技能自动熔断 30 秒防止一个下游故障把所有 Agent 请求全部拖垮。6.4 一个成熟技能的自我修养版本、灰度与可观测性技能一旦投入生产就不能只靠“本地跑得好”来保证了。我给团队立了几条规矩每个技能必须带version字段发版记录到 changelog新技能先小流量灰度比如只让 10% 的请求路由到新技能对比错误率和耗时再逐步放量。每个技能的执行日志必须记录入参、出参、耗时、触发它的模型决策轨迹。这样出现问题时可以回溯到底是模型选错了技能还是技能本身有 bug。我还会按周维度统计所有技能的调用率和失败率。调用率为 0 的技能不一定是没用的大概率是路由层有问题模型看不到它。失败率偏高的技能会优先进入 review 队列。这些可观测性数据比模型本身的精度指标更能反映整个 Agent 系统的健康程度。6.5 安全边界不能把执行裸奔交给模型最后聊一个容易被忽视但非常重要的点技能执行的安全边界。模型本质上是一个概率系统你没法 100% 保证它不会在某个奇怪上下文里给某个高风险技能填出危险参数。所以在技能注册阶段就要给每个技能打上权限标签read-only、write、admin。调度引擎执行前必须检查当前会话身份是否具有权限。敏感操作创建订单、发起付款、删除数据一律要求用户二次确认这个确认动作也做成一个技能由 Agent 在操作前主动触发。此外外部网络请求要强制走白名单代理输入给技能的所有参数都要做基础清洗——尤其是会拼接到 SQL、命令行中的字段。这一点没有捷径必须从框架层面默认全 deny按需放行。宁可配置繁琐一点也别把裸奔的执行权交到模型手里。最后分享三个我长期受益的小习惯。第一所有技能名都用动词开头query_order、apply_refund、send_email一看就懂是干什么的对模型和开发者都友好。第二每个月清理一次超过 30 天未被调用的技能——它们不是没用而是大概率路由层出了问题留在库里只会增加模型的决策负担。第三在技能描述里明确写一句“不可用于某某场景”比如查运费技能注明“不用于计算退款金额”这能显著减少模型跨域误用。agent-skills 不是一次性工程它是需要持续迭代、持续观测的技能资产。体系搭建起来之后后续每新增一个技能都是在往这套方法论里添加资产整体的 Agent 能力就会越来越厚而不是越来越乱。
返回列表