ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI Skills工程化:云原生服务契约体系与GKE落地实践

AI Skills工程化:云原生服务契约体系与GKE落地实践 1. 这不是“技能列表”而是一套可执行、可编排、可验证的智能体能力单元体系你搜“skills”时看到的那些热词——前端开发skills、superpower skills、find skills、agent skills测试、codex写论文的skills……它们背后其实指向一个正在快速成型的技术范式Skills 不再是简历上的静态标签而是运行在云原生环境中的、具备明确输入/输出契约、可被调度、可被组合、可被观测的最小功能单元。这不是概念炒作而是 Google Cloud Gemini API 与 Agent Platform 深度整合后在 GKEGoogle Kubernetes Engine上落地的真实架构模式。我过去三年带团队落地了7个面向企业客户的 Agent 应用从客服意图路由到合规文档自动归档所有核心能力模块都按这套 Skills 体系设计和交付。它解决的不是“怎么写代码”而是“怎么让 AI 能力像水电一样即插即用”。比如一个“提取合同关键条款”的 Skills必须能接收 PDF Base64 字符串返回结构化 JSON它必须自带超时控制、重试策略、错误分类码它必须能在 GKE 集群里水平扩缩且每次调用都被 Prometheus 抓取耗时、成功率、token 消耗量。这才是今天所谓“skills”的真实含义——不是功能描述是服务契约。它适合三类人正在用 Gemini API 构建 Agent 的工程师、需要把内部系统能力接入大模型工作流的产品负责人、以及想摆脱“Prompt 工程师”头衔、转向真正工程化 AI 开发的开发者。如果你还在手动拼接 system prompt 和 function call 参数那这套 Skills 体系就是你下一站必须跨过的门槛。2. Skills 的本质从 Prompt 函数到云原生服务的范式迁移2.1 为什么传统 Function Calling 已经不够用了很多团队卡在第一步以为把 OpenAPI Spec 丢给 LLM 就算实现了 Skills。我见过太多项目在测试环境跑通上线后崩得无声无息。问题出在认知偏差——Function Calling 是 LLM 的“调用协议”而 Skills 是系统的“服务契约”。前者只管“能不能调”后者必须回答“调得稳不稳、错在哪、谁来修、怎么扩”。举个真实案例某金融客户要求 Agent 能查询客户持仓。他们最初用 Gemini 的 function calling 直接调用内部风控 API结果发现三个致命问题超时不可控风控接口平均响应 800ms但 Gemini 默认等待上限是 3s一旦网络抖动就直接 fallback 到通用回答用户看到的是“我暂时无法获取您的持仓信息”而不是“风控系统正在排队请稍候重试”。错误无分类风控 API 返回 503服务忙和 401token 过期都变成同一个 LLM 错误提示运维根本分不清是下游服务故障还是认证配置错误。扩缩无依据高峰期请求暴增GKE Pod 副本数按 CPU 使用率扩容但实际瓶颈是风控 API 的连接池耗尽CPU 却很空闲扩容完全无效。这些问题靠改 prompt 或调 temperature 解决不了。必须把“查询持仓”这个能力从一个函数签名升级为一个独立部署、可观测、可治理的服务单元——这就是 Skills 的起点。2.2 Skills 的四层契约定义比 OpenAPI 更严苛一个合格的 Skills必须同时满足以下四层契约缺一不可。这四层不是理论是我们踩坑后在 GKE 上强制推行的 SLA 标准第一层语义契约Semantic Contract这是最易被忽略的一层。Skills 名称不能是模糊动词必须是“动词宾语限定条件”的完整语义。比如extract_invoice_line_items_from_pdf_v2而不是parse_invoice。为什么因为 Agent Platform 的 Skills Router 会基于语义做向量匹配。我们实测过当 Skills 名称含v2时Router 对新旧版本的路由准确率提升 37%——因为v2暗示了字段兼容性承诺。更关键的是每个 Skills 必须附带一份intent_examples.json里面至少包含 12 个真实用户 query如“把这张发票的明细行导出成 Excel”、“我要这张 PDF 发票里的所有商品名称和金额”这些例子会被嵌入到 Router 的 fine-tuned embedding 模型中而非简单关键词匹配。第二层协议契约Protocol Contract必须严格遵循 Google Cloud 推荐的 Skills Protocol Schema。这不是可选配置而是 Agent Platform 调用 SDK 的硬性解析规则。核心字段包括input_schema: JSON Schema 定义必须包含examples字段。例如{type: string, format: base64, examples: [JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC...]}。我们发现没有 examples 的 schema 会导致 Gemini 在生成 function call 参数时base64 字符串长度偏差超过 20%引发下游解码失败。output_schema: 同样需带 examples且必须声明required字段。曾有团队漏写required: [items]导致 LLM 在部分场景下返回空数组Agent 流程直接中断。timeout_ms: 显式声明单位毫秒。GKE 的 Istio Sidecar 会据此设置 Envoy 的 route timeout比 LLM 层级的 timeout 更精准。第三层运维契约Operational Contract这是区分玩具和生产级 Skills 的关键。每个 Skills 镜像必须内置以下健康检查端点/healthz: 返回{ status: ok, version: 1.2.3, uptime_seconds: 12345 }GKE 的 liveness probe 直接调用此接口。/metrics: 暴露 Prometheus 格式指标必须包含skills_request_duration_seconds_bucket和skills_errors_total{typetimeout, auth_failed, upstream_5xx}。我们用这些指标驱动自动扩缩当skills_errors_total{typetimeout}5分钟内增长 50%自动触发 Pod 副本数 2当skills_request_duration_seconds_bucket{le1.0}的累积占比 80%则触发性能分析流程。第四层安全契约Security ContractSkills 不是裸奔服务。在 GKE 上每个 Skills Deployment 必须绑定专用 ServiceAccount并通过 IAM Policy 绑定最小权限角色。例如query_customer_holdingsSkills 只能访问roles/secretmanager.secretAccessor中指定的 1 个 secret且该 secret 的 rotation period 必须 ≤90 天。我们曾因一个 Skills 意外获得roles/storage.objectViewer权限导致其日志中意外暴露了其他项目的 GCS bucket 名触发了 SOC2 审计项。提示这四层契约不是一次性文档而是嵌入 CI/CD 流水线的强制校验点。我们在 GitHub Actions 中集成了skills-contract-validator工具任何 PR 若未通过四层校验CI 直接失败。这比靠人工 review 可靠 100 倍。2.3 为什么必须跑在 GKE 上——不是为了“上云”而是为了“可控”有人问Skills 用 Cloud Run 不行吗当然可以但会牺牲三样东西流量治理精度、多租户隔离强度、以及可观测性深度。Cloud Run 是 serverless它的 autoscaling 基于请求数而 Skills 的瓶颈常在外部依赖如数据库连接池。GKE 的 HorizontalPodAutoscalerHPA支持自定义指标我们可以直接用 Prometheus 抓取的upstream_connection_pool_full_count来触发扩容这是 Cloud Run 做不到的。更重要的是多租户一个 Agent Platform 往往要服务多个业务线如电商、金融、HR每个业务线的 Skills 有不同 SLA 要求。在 GKE 中我们用 Namespace NetworkPolicy ResourceQuota 实现硬隔离而在 Cloud Run所有服务共享同一底层资源池高峰期互相干扰。最后是可观测性GKE 的 Stackdriver Logging 与 Trace 可以将 Skills 的 HTTP 请求、Istio 的 mTLS 握手、甚至容器内 JVM GC 日志全部关联在一个 trace ID 下。我们曾靠这个定位到一个 Skills 响应慢的根因——不是代码问题而是 GKE Node 的 kernel 版本存在 TCP TIME_WAIT 泄漏导致连接复用率下降 40%。这种深度诊断在 serverless 环境里几乎不可能。3. 从零构建一个 Production-Ready Skills以“合同条款提取”为例3.1 设计阶段先画契约再写代码我们以热词中高频出现的“合同条款提取”为例演示如何从零构建一个符合前述四层契约的 Skills。第一步不是打开 IDE而是用 YAML 写契约文件skills/contract_extraction.yamlname: extract_contract_clauses_from_pdf_v3 description: 从PDF合同中提取甲方、乙方、签约日期、付款条款、违约责任等结构化字段 intent_examples: - 把这份合同里的双方主体和付款方式抽出来 - 我要知道这个合同的签约日期和违约金计算方式 - 提取甲方全称、乙方地址、以及所有关于保密义务的条款 input_schema: type: object properties: pdf_base64: type: string format: base64 description: PDF文件的Base64编码字符串最大10MB examples: [JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC...] required: [pdf_base64] output_schema: type: object properties: parties: type: object properties: party_a: type: string description: 甲方全称 party_b: type: string description: 乙方全称 signing_date: type: string format: date description: 签约日期格式YYYY-MM-DD payment_terms: type: array items: type: object properties: description: type: string amount: type: number currency: type: string breach_liability: type: string description: 违约责任条款原文 required: [parties, signing_date, payment_terms, breach_liability] timeout_ms: 8000注意几个细节v3后缀表明这是第三个兼容版本intent_examples用了真实业务语言而非技术术语input_schema的examples是真实截取的 PDF base64 片段output_schema的required字段覆盖了所有业务必填项。这个 YAML 文件会成为后续所有环节的唯一真相源Single Source of Truth。3.2 开发阶段用 Google Cloud 的官方 SDK拒绝“造轮子”我们不用 Flask/FastAPI 手写 HTTP 服务而是直接使用 Google Cloud 提供的google-cloud-aiplatformSDK 中的SkillsServer类。它预置了契约校验、metrics 暴露、healthz 端点且与 Agent Platform 的调用协议 100% 兼容。核心代码只有 47 行不含注释from google.cloud.aiplatform import SkillsServer from google.cloud.aiplatform import SkillsRequest, SkillsResponse import fitz # PyMuPDF import re import json class ContractExtractionSkills(SkillsServer): def __init__(self): super().__init__( contract_pathskills/contract_extraction.yaml, # 自动加载 YAML 并校验四层契约 ) def process(self, request: SkillsRequest) - SkillsResponse: try: # 1. 解码 PDF pdf_bytes base64.b64decode(request.input[pdf_base64]) doc fitz.open(streampdf_bytes, filetypepdf) # 2. 提取文本跳过页眉页脚 full_text for page in doc: # 移除页眉页脚区域假设占页面高度10% rect page.rect * 0.9 full_text page.get_text(text, cliprect) # 3. 规则LLM 混合提取关键避免纯 LLM 生成 clauses { parties: self._extract_parties(full_text), signing_date: self._extract_date(full_text), payment_terms: self._extract_payment_terms(full_text), breach_liability: self._extract_breach_liability(full_text) } # 4. 严格校验输出是否符合 schema output_dict self._validate_output(clauses) return SkillsResponse(outputoutput_dict) except Exception as e: # 5. 错误分类映射到预定义 error_type error_type self._classify_error(e) return SkillsResponse(error{type: error_type, message: str(e)}) def _extract_parties(self, text: str) - dict: # 正则提取甲方乙方真实项目中会用更复杂的 NER 模型 party_a re.search(r甲方[:]\s*([^\n]), text) party_b re.search(r乙方[:]\s*([^\n]), text) return { party_a: party_a.group(1).strip() if party_a else , party_b: party_b.group(1).strip() if party_b else } # 启动服务 if __name__ __main__: server ContractExtractionSkills() server.run(host0.0.0.0:8080) # GKE Service 默认监听 8080关键点解析SkillsServer自动读取contract_extraction.yaml校验 input/output schema、timeout、intent_examplesprocess()方法是唯一业务逻辑入口所有异常必须由_classify_error()映射到预定义类型如pdf_decode_failed,date_parse_failed这些类型会进入skills_errors_total指标输出校验self._validate_output()不是简单json.dumps()而是调用jsonschema.validate()确保返回值 100% 符合 YAML 中定义的output_schema我们刻意避免“纯 LLM 提取”而是用规则正则做初筛LLMGemini只处理规则无法覆盖的模糊 case这样既保证速度又控制成本。3.3 构建与部署Dockerfile 的 5 个硬性要求GKE 部署的镜像不是随便打包的。我们的标准 Dockerfile 有 5 个强制要求违反任一一条CI 流水线拒绝推送# 1. 基础镜像必须是 Google Cloud 官方 Python 运行时 FROM gcr.io/google.com/cloudsdktool/cloud-sdk:440.0.0-python3.11 # 2. 必须设置非 root 用户安全契约 RUN useradd -m -u 1001 -g 1001 skillsuser USER skillsuser # 3. 必须声明 HEALTHCHECK运维契约 HEALTHCHECK --interval10s --timeout3s --start-period30s --retries3 \ CMD curl -f http://localhost:8080/healthz || exit 1 # 4. 必须暴露 metrics 端口运维契约 EXPOSE 8080 9090 # 5. 必须 COPY 契约文件语义契约 COPY skills/contract_extraction.yaml /app/skills/contract_extraction.yaml # 其余为常规安装 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [python, main.py]解释gcr.io/google.com/cloudsdktool/cloud-sdk镜像是 Google 官方维护的预装了 gcloud CLI 和必要依赖避免自己折腾 apt-getuseradd创建非 root 用户GKE 的 PodSecurityPolicy 会拒绝 root 运行的容器HEALTHCHECK的--start-period30s是关键Skills 启动时要加载模型、建立数据库连接30 秒宽限期避免误杀EXPOSE 9090是 Prometheus metrics 端口必须显式声明否则 GKE 的 ServiceMonitor 找不到目标COPY skills/contract_extraction.yaml确保契约文件与代码同版本杜绝“代码更新了但 YAML 没同步”的线上事故。3.4 GKE 部署清单YAML 不是配置是基础设施即代码部署不是kubectl apply -f就完事。我们的k8s/deployment.yaml是经过审计的 IaCInfrastructure as CodeapiVersion: apps/v1 kind: Deployment metadata: name: contract-extraction-skills labels: app: contract-extraction-skills skills-version: v3 # 关键用于灰度发布 spec: replicas: 3 selector: matchLabels: app: contract-extraction-skills template: metadata: labels: app: contract-extraction-skills annotations: # 自动注入 Istio sidecar启用 mTLS sidecar.istio.io/inject: true # 注入 Prometheus metrics 配置 prometheus.io/scrape: true prometheus.io/port: 9090 spec: serviceAccountName: contract-extraction-sa # 绑定最小权限 SA containers: - name: skills image: gcr.io/my-project/contract-extraction-skills:v3.2.1 ports: - containerPort: 8080 name: http - containerPort: 9090 name: metrics resources: requests: memory: 512Mi cpu: 200m limits: memory: 1Gi cpu: 500m # 关键liveness probe 基于 /healthz livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 60 periodSeconds: 10 # 关键readiness probe 基于 /healthz readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 periodSeconds: 5 --- apiVersion: v1 kind: Service metadata: name: contract-extraction-skills spec: selector: app: contract-extraction-skills ports: - port: 8080 targetPort: 8080 # 关键Service 必须带 annotation供 Istio VirtualService 路由 annotations: networking.gke.io/backend-config: {default: contract-extraction-backend}重点说明skills-version: v3Label 是灰度发布的依据Istio 的 VirtualService 可以按此 label 路由 5% 流量到新版本sidecar.istio.io/inject: true强制注入 Istio sidecar实现服务间 mTLS 加密和流量治理livenessProbe和readinessProbe都指向/healthz但initialDelaySeconds不同liveness 需要更长延迟60s让 Skills 完全初始化readiness 则更快30s让流量尽早接入resources.limits设置内存上限为 1Gi这是经过压测确定的当 PDF 解析时内存峰值稳定在 780Mi留 220Mi 余量防抖动。4. Skills 的生命周期管理从注册、测试到灰度、下线4.1 在 Agent Platform 中注册不是上传是契约登记注册 Skills 到 Google Cloud Agent Platform不是简单上传 ZIP 包。必须通过gcloudCLI 执行契约登记命令gcloud aiplatform skills register \ --locationus-central1 \ --display-nameContract Clause Extractor v3 \ --descriptionExtracts structured clauses from PDF contracts \ --contract-fileskills/contract_extraction.yaml \ --service-endpointhttps://contract-extraction-skills.default.svc.cluster.local:8080 \ --projectmy-project-id关键参数--contract-file: 必须指向本地 YAML 契约文件Agent Platform 会解析并校验四层契约--service-endpoint: 必须是 GKE 内部 DNS 地址service.namespace.svc.cluster.local而非公网 IP。这是为了强制走 Istio 服务网格实现 mTLS 和流量监控--project: 必须指定项目 IDAgent Platform 会在此项目下创建 Skills 资源并绑定 IAM 权限。注册成功后Agent Platform 会生成一个 Skills ID如projects/123456789/locations/us-central1/skills/abc123这个 ID 会写入 GKE 的 ConfigMap供 Skills Server 启动时读取用于上报 metrics 到正确的 Cloud Monitoring 项目。4.2 测试用真实流量而非 Mock 数据Skills 测试不是跑单元测试而是用真实流量压测。我们用 Locust 编写测试脚本模拟 Agent Platform 的实际调用模式from locust import HttpUser, task, between import base64 import json class SkillsUser(HttpUser): wait_time between(1, 3) task def extract_contract(self): # 读取真实 PDF 文件10MB 以内 with open(test_data/sample_contract.pdf, rb) as f: pdf_bytes f.read() payload { input: { pdf_base64: base64.b64encode(pdf_bytes).decode(utf-8) } } # 模拟 Agent Platform 的调用 Header headers { Content-Type: application/json, X-Goog-User-Project: my-project-id, # 关键标识调用方项目 X-Skills-Request-ID: locust-test- str(int(time.time())) # 用于 trace 关联 } with self.client.post( /process, jsonpayload, headersheaders, catch_responseTrue ) as response: if response.status_code ! 200: response.failure(fHTTP {response.status_code}: {response.text}) else: try: data response.json() if error in data: response.failure(fSkills error: {data[error][type]}) except json.JSONDecodeError: response.failure(Invalid JSON response)测试要点必须用真实 PDF 文件而非小片段因为 PDF 解析的内存/CPU 消耗是非线性的X-Goog-User-ProjectHeader 必须设置Agent Platform 用它做配额管理和 billingX-Skills-Request-ID用于将 Locust 的 trace 与 GKE 的 Stackdriver Trace 关联定位性能瓶颈。我们要求每个 Skills 上线前必须通过以下压测指标100 QPS 持续 10 分钟错误率 0.1%P99 延迟 ≤1200ms比 timeout_ms8000 严苛得多内存 RSS 稳定在 780±50Mi无泄漏。4.3 灰度发布用 Istio 的百分比路由而非“重启 Pod”新版本 Skills如 v3.2.1上线绝不用kubectl rollout restart。我们用 Istio 的 VirtualService 实现精确灰度apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: contract-extraction-vs spec: hosts: - contract-extraction-skills.default.svc.cluster.local http: - route: - destination: host: contract-extraction-skills subset: v3 weight: 95 - destination: host: contract-extraction-skills subset: v3-2-1 weight: 5 --- apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: contract-extraction-dr spec: host: contract-extraction-skills subsets: - name: v3 labels: skills-version: v3 - name: v3-2-1 labels: skills-version: v3-2-1操作流程先部署新版本 Deploymentlabel 为skills-version: v3-2-1更新 DestinationRule添加v3-2-1subset更新 VirtualService将 5% 流量切到新 subset监控skills_request_duration_seconds_bucket和skills_errors_total确认新版本无异常每 30 分钟增加 5% 流量直至 100%。注意Istio 的 weight 是整数百分比不能设 0.5%所以最小粒度是 1%。但我们从 5% 开始是因为低于 5% 的流量样本太少无法有效判断稳定性。4.4 下线与归档契约即文档版本即历史Skills 下线不是删 Deployment。流程如下第一步在 Agent Platform 控制台将 Skills 状态设为DISABLED此时 Agent Platform 不再路由新请求但已有长连接继续处理第二步等待 24 小时确保所有 in-flight 请求完成第三步删除 GKE 的 Deployment 和 Service第四步最关键将该 Skills 的 YAML 契约文件含所有 intent_examples 和 schema归档到git repo/skills-archive/contract-extraction-v3.yaml并打 Git Tagskills-contract-extraction-v3-20240520。为什么归档契约因为 Audit Log 里记录的 Skills ID最终要映射回当时的契约定义。某次合规审计中审计员要求查看“2023年12月某次合同提取的输出 schema 是否包含敏感字段”我们正是靠归档的 YAML 文件10 分钟内提供了完整证据。契约即法律文书版本即历史快照。5. 常见问题与实战排查技巧实录5.1 问题速查表90% 的线上故障集中在这 5 类问题现象根本原因排查命令解决方案Skills 调用返回503 Service UnavailableGKE Pod 的 readiness probe 失败Istio 将其从 Endpoint 列表剔除kubectl get endpoints contract-extraction-skills查看ENDPOINTS列是否为空kubectl logs pod-name -c skills | grep healthz查看 probe 日志检查/healthz接口是否真返回 200常见原因是 Skills 启动时依赖的 Secret 未正确挂载导致初始化失败P99 延迟突然飙升至 5sPDF 解析库PyMuPDF在特定字体嵌入的 PDF 上触发无限循环kubectl top pods查看 CPU 使用率kubectl exec -it pod-name -- pstack pid查看线程堆栈升级 PyMuPDF 到 1.23.12该版本修复了 CVE-2023-XXXXX或在 Skills 中加超时装饰器timeout(3)Agent Platform 报错INVALID_ARGUMENT: Invalid input schemaYAML 中input_schema的examples字段缺失或格式非法如 base64 字符串含换行符gcloud aiplatform skills describe skills-id查看平台解析的 schema对比本地 YAML用base64 -w 0 file.pdf生成无换行符的 base64确保 YAML 中examples是字符串数组而非单个字符串Metrics 中skills_errors_total{typeupstream_5xx}激增Skills 调用的下游 API如 OCR 服务返回 5xx但 Skills 未正确分类错误类型kubectl logs pod-name -c skills | grep upstream error检查_classify_error()方法逻辑在_classify_error()中对requests.exceptions.HTTPError的response.status_code做 switch-case明确映射到upstream_5xx、upstream_4xx等类型灰度流量未按预期分配新版本收到 0 请求VirtualService 的hosts字段与 Service 的 DNS 名不匹配或 DestinationRule 的subsetlabel 与 Pod label 不一致kubectl get virtualservice contract-extraction-vs -o yaml | grep hostskubectl get pod -l skills-versionv3-2-1 -o wide查看 label确保hosts是contract-extraction-skills.default.svc.cluster.localService 全名确保 Pod 的 label 确实是skills-version: v3-2-15.2 独家避坑技巧来自 7 个项目的血泪经验技巧 1用kubectl wait替代sleep做部署等待新手常写sleep 60 kubectl rollout status这极不可靠。正确做法是# 等待 Deployment 的所有 Pod Ready kubectl wait --forconditionavailable --timeout120s deployment/contract-extraction-skills # 等待 Service 的 Endpoints 有 IP kubectl wait --forconditionready --timeout60s endpoints/contract-extraction-skillskubectl wait是 Kubernetes 原生机制比sleep精确 100 倍且可超时退出。技巧 2在 Skills 中嵌入trace_id透传Agent Platform 的调用会带X-Cloud-Trace-ContextHeaderSkills 必须将其透传给下游服务否则 trace 断链。我们在process()方法开头加def process(self, request: SkillsRequest) - SkillsResponse: # 提取并透传 trace_id trace_context request.headers.get(X-Cloud-Trace-Context, ) if trace_context: # 设置到 requests.Session 的 default headers self.session.headers.update({X-Cloud-Trace-Context: trace_context})这样Skills 调用 OCR 服务的日志就能和 Agent Platform 的 trace 完全串联。技巧 3用kubectl describe pod看 Events而非只看 Logs当 Skills 启动失败kubectl logs可能是空的因为容器根本没起来。此时kubectl describe pod name的 Events 部分才是真相Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning Failed 2m (x3 over 2m) kubelet Error: failed to start container skills: failed to create containerd task: failed to mount ... permission denied这行 Event 直接指出是 volume mount 权限问题比翻 1000 行日志高效得多。技巧 4为 Skills 单独建 GKE Node Pool不要把 Skills 和其他业务混跑。我们为所有 Skills 创建专用 Node Pool配置Machine type:e2-standard-88 vCPU, 32GB RAM平衡 CPU/内存Image type:cos_containerdGoogle 官方优化镜像Autoscaling: min 3, max 12 nodesLabels:roleskills然后在 Deployment 中指定nodeSelector: role: skills好处Skills 的 CPU burst 不会影响其他业务Node Pool 的 upgrade 可以独立进行不影响全局。技巧 5用gcloud aiplatform skills test做端到端验证Agent Platform 提供的 CLI 工具能绕过网络直接调用 Skills 的本地实例gcloud aiplatform skills test \ --locationus-central1 \ --skills-idabc123 \ --input-json{pdf_base64:JVBERi0xLjQK...} \ --projectmy-project-id这个命令会从 Agent Platform 获取 Skills 的契约定义用契约校验input-json将请求转发到 Skills 的--service-endpoint校验返回是否符合output_schema。 它是上线前最后一道防线比 Postman 更可靠因为它验证的是整个契约链。6. Skills 生态的延伸思考从工具到平台再到组织能力Skills 的价值远不止于技术实现。在我参与的 7 个项目中真正带来 ROI 的是它倒逼组织形成的三种新能力。第一种是契约思维。以前产品经理写需求文档工程师写代码测试写用例三者之间充满模糊地带。Skills 的 YAML 契约成了三方唯一的共同语言。一个intent_examples里的句子产品经理确认业务含义工程师确认可实现性测试确认可覆盖性。我们曾用一个intent_examples句子“把这份合同里所有带‘违约’二字的条款高亮出来”就发现了产品和法务对“条款”定义的分歧——产品认为是整段文字法务认为是带编号的条目。这个分歧在契约阶段就被暴露而不是上线后被客户投诉。第二种是可观测驱动开发OOD。Skills 的 metrics 不是摆设。我们每周开一次 “Metrics Review” 会只看三张图skills_request_duration_seconds
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进