1. 从“skills”这个标题说起我为什么盯上了 Agent Skills第一次看到“skills”这个标题我脑子里蹦出来的不是某个具体产品而是一整套正在成型的智能体能力体系。最近圈子里聊得最多的几个词——Agent Skills、Google Cloud、GKE、Genkit、Gemini——其实指向的是同一件事怎么让一个智能体不只是“会聊天”而是真正具备可复用、可组合、可部署的技能。这跟以前我们写死一个 prompt、调一个 API 完全不是一个思路。我接触 Agent Skills 这个概念最早是从一些开源智能体框架的文档里看到的。当时我的第一反应是这不就是把函数调用包装了一层吗但真正动手在 Google Cloud 上跑通一条链路之后我发现事情没那么简单。Skills 更像是一种能力契约——它定义了智能体在什么场景下、用什么工具、按什么顺序、产出什么结果。这背后牵扯到工具注册、上下文管理、权限控制、部署形态等一系列工程问题。这篇文章适合谁看如果你正在用 Gemini 或者 Genkit 做智能体原型或者你已经在 GKE 上跑了一些服务想把这些服务变成智能体可以调用的“技能”那这篇内容应该能帮你少走一些弯路。如果你只是听说过 Agent Skills 但还没动手我也会从最基础的概念讲起尽量用生活化的类比把原理说清楚。整篇内容基于我在实际项目中的操作记录和踩坑经验不是官方文档的复述而是“一个从业者真正会怎么干”的视角。2. Agent Skills 到底是什么拆开来看它的核心结构2.1 从“函数调用”到“技能”的认知升级很多人第一次接触 Agent Skills会把它等同于 OpenAI 的 function calling 或者 Gemini 的 tool use。我一开始也这么想但实际用下来发现Skills 的抽象层级更高。函数调用解决的是“模型怎么触发一个外部接口”而 Skills 解决的是“智能体怎么拥有一项可管理的能力”。打个比方函数调用像是你给一个员工一部电话告诉他“需要查库存就打这个号码”。而 Skills 像是你给这个员工一本操作手册里面写清楚了“查库存”这项技能的适用场景、输入格式、输出规范、异常处理流程甚至还包括“查完之后要同步给谁”。前者是通道后者是能力封装。在 Google Cloud 的体系里Agent Skills 通常和 Genkit 配合使用。Genkit 是一个用于构建 AI 功能的框架它提供了工具注册、流程编排、模型调用等基础能力。而 Skills 是在这个基础上把一组相关的工具调用、提示词模板、后处理逻辑打包成一个可复用的单元。你可以把它理解为一个“技能包”里面既有代码逻辑也有自然语言描述方便智能体在运行时决定是否调用。2.2 Skills 的三个核心组成描述、工具、执行逻辑我拆过几个实际项目里的 Skill 定义发现它们基本都包含三个部分。第一部分是自然语言描述这部分是给模型看的用来说明这个技能是干什么的、什么时候该用、输入输出大概是什么样。第二部分是工具绑定也就是这个技能实际会调用哪些底层函数或 API。第三部分是执行逻辑包括参数校验、错误处理、结果格式化等。这三部分缺一不可。我见过有人只写了工具绑定没写描述结果模型根本不知道什么时候该调用这个技能。也见过描述写得很漂亮但执行逻辑里没做参数校验导致模型传了一个空值进来整个流程直接崩掉。所以我的经验是描述要写得像给一个新员工看的操作说明工具绑定要尽量原子化执行逻辑要假设“模型一定会传错参数”来做防御。2.3 为什么 Google Cloud 和 GKE 在这个话题里频繁出现Agent Skills 本身是一个抽象概念但你要把它跑起来就需要一个运行环境。Google Cloud 提供了从模型调用到部署的一整套工具链而 GKE 则是把这些技能部署成可扩展服务的主流选择。我自己的项目就是先把 Skill 在本地用 Genkit 跑通然后打包成容器推到 GKE 上以服务的形式暴露出来。这样做的好处是智能体的其他部分比如对话管理、上下文存储可以独立部署技能服务也可以独立扩缩容。坏处是链路变长了排查问题的时候需要同时看好几个地方。后面我会专门讲怎么排查这类问题。3. 环境准备从零搭建一个可用的 Skills 开发环境3.1 账号与权限那些容易卡住新手的细节在 Google Cloud 上做任何事第一步都是账号和权限。我这里不展开讲注册流程只说几个我实际踩过的坑。第一个坑是项目选择。Google Cloud 的控制台里可以创建多个项目每个项目有独立的资源和权限。我建议专门为 Agent Skills 创建一个新项目不要和现有的生产项目混在一起。因为后面你会频繁地启用 API、创建服务账号、部署服务混在一起容易误操作。第二个坑是服务账号的权限粒度。默认的服务账号权限太大直接拿来用不符合最小权限原则。我的做法是创建一个自定义角色只包含必要的权限比如调用 Vertex AI、读写 Cloud Storage、推送到 Artifact Registry。具体需要哪些权限取决于你的 Skill 实际会调用哪些服务。我一般会先给一个比较宽的权限跑通之后再逐步收紧这样比一开始就卡在权限问题上要高效。第三个坑是API 启用。Google Cloud 的很多服务默认是关闭的你需要手动启用。我至少遇到过三次“代码没问题但就是报权限错误”最后发现是某个 API 没启用。建议在项目初始化的时候把可能用到的 API 都列一个清单一次性启用。3.2 本地开发工具链Genkit 的安装与初始化Genkit 是我目前用得最顺手的智能体开发框架之一。它的安装很简单但初始化的时候有几个选项需要留意。我用的是 Node.js 版本通过 npm 安装。安装完成后运行初始化命令它会问你几个问题用哪个模型提供商、要不要生成示例代码、项目结构怎么组织。我的建议是如果你打算用 Gemini就选 Google AI 作为提供商。如果你打算用 Vertex AI 上的模型就选 Vertex AI。这两个的配置方式略有不同后面调用的时候 API 也不一样。我一开始选错了后来迁移花了不少时间。初始化完成后你会得到一个基本的项目结构里面有一个flows目录和一个tools目录。flows是用来定义工作流的tools是用来定义工具的。而 Skills 通常是在这两者之上再做一层封装。我一般会把 Skill 定义放在一个单独的skills目录里每个 Skill 一个文件方便管理。3.3 GKE 集群的创建与基础配置如果你只是本地开发可以跳过这一步。但如果你想让 Skill 以服务的形式运行GKE 集群是绕不开的。我创建集群的时候主要关注几个参数节点数量、机器类型、网络配置。节点数量我一般选 3 个这样可以做滚动更新不会因为一个节点挂掉就整个服务不可用。机器类型我选的是 e2-standard-44 核 16G对于大多数 Skill 服务来说够用了。如果你的 Skill 需要调用大模型可能需要更大的内存因为模型调用的响应体有时候会很大。网络配置方面我建议开启私有节点只通过负载均衡器暴露必要的端口。这样更安全也更容易做访问控制。创建集群大概需要几分钟期间你可以去准备容器镜像。4. 核心实操从零写一个可用的 Agent Skill4.1 定义 Skill 的描述让模型知道“什么时候该用”写 Skill 描述是我觉得最考验功力的一步。描述写得好模型就能在正确的时机调用正确的技能描述写得差模型要么不调用要么乱调用。我的经验是描述要包含四个要素技能名称、适用场景、输入说明、输出说明。技能名称要简短且语义明确比如“查询订单状态”就比“订单相关操作”要好。适用场景要写清楚“当用户询问订单物流信息时使用”而不是“用于订单查询”。输入说明要列出所有参数及其类型比如“订单号字符串必填”。输出说明要描述返回值的结构比如“返回一个包含状态和预计送达时间的对象”。我一般会先用中文写一版描述然后翻译成英文。因为大多数模型对英文描述的理解更准确。翻译的时候要注意不要直译而是用模型更容易理解的表达方式。比如“查询订单状态”翻译成“Retrieve order status”就比“Query order status”更常见。4.2 绑定工具把现有 API 包装成 Skill 可调用的函数工具绑定这一步本质上就是写一个函数把外部 API 的调用封装起来。我以查询订单状态为例假设你有一个 REST API 可以查询订单。你需要写一个函数接收订单号作为参数调用这个 API然后返回结果。这里有几个细节需要注意。第一参数校验。模型传过来的参数不一定是合法的你可能需要检查订单号是否为空、格式是否正确。第二错误处理。API 调用可能会失败你需要捕获异常并返回一个模型能理解的错误信息而不是直接抛出一个堆栈。第三超时设置。外部 API 的响应时间不确定你需要设置一个合理的超时时间避免整个流程卡住。我一般会用 try-catch 包裹 API 调用然后在 catch 里返回一个结构化的错误对象比如{ error: 订单不存在, code: ORDER_NOT_FOUND }。这样模型可以根据错误码决定下一步怎么做比如提示用户重新输入订单号。4.3 编写执行逻辑参数校验、错误处理与结果格式化执行逻辑是 Skill 的“大脑”它决定了技能在实际运行时的行为。我通常会把执行逻辑分成三步预处理、调用、后处理。预处理阶段做参数校验和默认值填充。比如订单号如果为空就直接返回错误不进入调用阶段。调用阶段就是执行工具绑定里的函数。后处理阶段对返回结果做格式化比如把 API 返回的原始 JSON 转换成一个更易读的文本或者提取关键字段。这里有一个我踩过的坑不要在后处理阶段做太复杂的逻辑。我曾经在一个 Skill 里做了大量的数据转换和计算结果导致响应时间过长模型等不及就超时了。后来我把这些逻辑拆到了独立的工具里Skill 只负责编排响应时间就降下来了。4.4 本地测试用 Genkit 的开发者界面快速验证Genkit 提供了一个本地开发者界面可以让你在不部署的情况下测试 Skill。我一般会在这个界面里模拟各种输入包括正常输入、边界输入和异常输入。正常输入就是符合预期的参数边界输入比如空字符串、超长字符串异常输入比如不存在的订单号。测试的时候要特别关注模型的调用行为。有时候 Skill 本身没问题但模型就是不调用它。这时候你需要检查描述是否清晰、工具名称是否容易混淆。我遇到过一次两个 Skill 的名称太相似模型总是调错。后来我把其中一个改名问题就解决了。5. 部署到 GKE把 Skill 变成可扩展的服务5.1 容器化Dockerfile 的关键配置把 Skill 部署到 GKE第一步是写 Dockerfile。我一般用 Node.js 的官方镜像作为基础镜像然后把代码复制进去安装依赖暴露端口最后启动服务。关键配置有几个。第一多阶段构建。先用一个阶段安装依赖和构建再用一个更小的镜像作为运行时。这样可以减小镜像体积加快部署速度。第二环境变量。不要把敏感信息写死在代码里而是通过环境变量传入。GKE 支持从 Secret 中读取环境变量这样更安全。第三健康检查。在 Dockerfile 里定义一个健康检查端点GKE 会定期调用这个端点来判断服务是否正常。我一般会把健康检查端点设为/health返回一个简单的 JSON比如{ status: ok }。这样 GKE 的负载均衡器就知道这个实例是健康的可以把流量导进来。5.2 推送到 Artifact Registry 并创建 Deployment镜像构建完成后需要推送到 Artifact Registry。我一般会先创建一个 Docker 仓库然后把镜像打上标签推上去。标签我习惯用latest加上一个日期比如latest-20240115这样方便回滚。创建 Deployment 的时候我关注几个参数副本数、资源限制、环境变量。副本数我一般设 2 到 3 个保证高可用。资源限制我设 CPU 500m、内存 512Mi对于大多数 Skill 服务来说够用了。环境变量从 Secret 中读取包括 API 密钥、数据库连接串等。创建完成后GKE 会自动拉取镜像并启动 Pod。你可以用kubectl get pods查看状态。如果 Pod 一直处于CrashLoopBackOff说明启动有问题需要看日志排查。5.3 暴露服务Service 与 Ingress 的配置要点Pod 启动后需要创建一个 Service 来暴露它。我一般用 ClusterIP 类型的 Service只在集群内部暴露。然后创建一个 Ingress把外部流量导进来。Ingress 的配置里我一般会设置一个路径规则比如/skills/*转发到 Skill 服务。这里有一个细节超时设置。Ingress 默认的超时时间可能比较短如果 Skill 的响应时间较长需要调大超时时间。我一般会设成 60 秒给模型调用留足时间。另外如果你需要 HTTPS还需要配置证书。GKE 支持自动管理证书你只需要在 Ingress 里声明域名即可。不过证书签发需要时间第一次部署的时候可能要等几分钟。6. 常见问题与排查技巧实录6.1 模型不调用 Skill描述与工具绑定的排查思路模型不调用 Skill 是最常见的问题之一。我一般会按以下顺序排查先看描述是否清晰再看工具名称是否容易混淆最后看输入参数是否匹配。描述方面我建议用“当用户...时使用”这样的句式而不是“这个技能用于...”。前者更接近模型的决策逻辑。工具名称方面避免使用过于宽泛的名称比如“查询”就比“查询订单状态”更容易被误调用。输入参数方面确保参数名称和描述一致不要出现“订单号”和“order_id”混用的情况。如果以上都没问题可以尝试在描述里加一些示例。比如“例如当用户说‘我的订单到哪了’时调用这个技能”。模型对示例的理解通常比抽象描述更好。6.2 部署后报权限错误服务账号与 API 启用的检查清单部署后报权限错误我一般会检查三件事服务账号是否有足够的权限、API 是否已启用、网络是否可达。服务账号权限方面我建议先用一个权限较大的账号跑通然后再逐步收紧。API 启用方面可以在 Google Cloud 控制台的“API 和服务”页面查看确保所有依赖的 API 都是“已启用”状态。网络方面如果 Skill 需要访问外部 API确保 GKE 集群的出口网络是通的。我遇到过一次集群的 NAT 网关没配置好导致外部 API 调用全部超时。6.3 响应超时从模型调用到网络链路的逐层排查响应超时是另一个高频问题。我一般会从模型调用开始排查然后是 Skill 内部逻辑最后是网络链路。模型调用方面检查模型的响应时间是否正常。如果模型本身就很慢那 Skill 再快也没用。Skill 内部逻辑方面检查是否有耗时的操作比如大量数据转换、循环调用外部 API。网络链路方面检查 Ingress 的超时设置、Service 的负载均衡策略、Pod 的资源限制。我遇到过一次Pod 的 CPU 限制设得太低导致请求排队响应时间飙升。后来把 CPU 限制调大问题就解决了。所以资源限制不要设得太紧留一些余量。6.4 常见问题速查表问题现象可能原因排查方法解决方案模型不调用 Skill描述不清晰检查描述是否包含适用场景用“当用户...时使用”句式重写模型调用错误的 Skill工具名称太相似对比多个 Skill 的名称重命名增加区分度部署后报权限错误服务账号权限不足查看服务账号的 IAM 角色添加必要权限或换用更大权限账号部署后报权限错误API 未启用检查 API 和服务页面启用缺失的 API响应超时模型调用慢单独测试模型调用换用更快的模型或优化提示词响应超时Skill 内部逻辑耗时加日志定位耗时步骤拆分逻辑异步处理响应超时网络链路问题检查 Ingress 和 Service 配置调大超时时间检查 NAT 网关Pod 启动失败镜像拉取失败查看 Pod 事件检查镜像地址和权限Pod 启动失败环境变量缺失查看 Pod 日志检查 Secret 配置7. 一些实操心得与避坑建议7.1 描述文件要像“给新员工的操作手册”我写 Skill 描述的时候会想象自己在给一个新员工写操作手册。这个新员工很聪明但对你公司的业务一无所知。所以描述里不能有内部术语不能有缩写不能有“你懂的”这种假设。每一个参数都要解释清楚每一个返回值都要说明含义。我一般会写一个模板包含以下几个部分技能名称、一句话描述、适用场景、输入参数表、输出格式、示例。这个模板我用了很多次效果很稳定。7.2 工具绑定要“原子化”不要做太多事工具绑定我坚持一个原则一个工具只做一件事。比如“查询订单”和“取消订单”应该是两个工具而不是一个工具根据参数决定做什么。这样做的好处是模型更容易理解每个工具的用途也更容易组合使用。如果确实需要多个步骤我会把它们拆成多个工具然后在 Skill 的执行逻辑里编排。这样虽然代码多了一些但可维护性和可测试性都更好。7.3 部署前一定要在本地跑通全链路我见过太多人本地测试只测了 Skill 本身没测模型调用结果部署上去之后发现模型根本不调用。所以我的建议是部署前一定要在本地跑通全链路包括模型调用、工具绑定、执行逻辑、结果返回。Genkit 的开发者界面可以模拟模型调用我一般会在这里做全链路测试。测试通过后再打包部署这样成功率会高很多。7.4 日志要打够但不要打太多日志是排查问题的关键但日志太多也会影响性能。我一般会在关键节点打日志比如 Skill 开始执行、工具调用开始、工具调用结束、Skill 执行结束。每个日志包含请求 ID、时间戳、关键参数。这样排查问题的时候可以通过请求 ID 把整个链路串起来。不要在日志里打敏感信息比如 API 密钥、用户密码。也不要在循环里打日志那样日志量会爆炸。7.5 版本管理Skill 的迭代与回滚策略Skill 是会迭代的今天能用不代表明天还能用。所以版本管理很重要。我一般会给每个 Skill 打一个版本号比如v1.0.0。部署的时候用版本号作为镜像标签而不是latest。这样回滚的时候只需要把 Deployment 的镜像标签改回上一个版本即可。另外我会保留最近三个版本的镜像更早的可以清理掉节省存储空间。8. 后续可以怎么扩展如果你已经跑通了一个基本的 Skill接下来可以考虑几个扩展方向。第一个方向是多 Skill 编排。把多个 Skill 组合起来完成更复杂的任务。比如“查询订单”加“发送通知”就是一个完整的订单状态通知流程。第二个方向是动态 Skill 加载。把 Skill 定义存储在数据库或配置中心运行时动态加载这样不用重新部署就能更新 Skill。第三个方向是Skill 监控与告警。给每个 Skill 加上调用次数、成功率、平均响应时间等指标接入监控系统及时发现异常。我个人在实际操作中的体会是Agent Skills 这个方向还在快速演进很多最佳实践还没有定型。所以不要追求一步到位先跑通一个最小可用版本然后根据实际使用情况逐步优化。踩过的坑多了自然就有感觉了。