首页 / 资讯中心 / 文章详情

AI智能体Skills系统:模块化能力设计与GKE工程落地

AI智能体Skills系统:模块化能力设计与GKE工程落地 ★ FEATURED ARTICLE
1. 这不是“技能列表”而是一套可执行、可验证、可演进的智能体能力系统你搜“skills”时看到的那些词——Google Cloud、Gemini、Genkit、GKE、前端开发skills、superpower skills、gemini登录失败提示、claude agent skills、codex写论文的skills……它们表面是零散热词实则指向一个正在快速成型的技术范式现代AI智能体Agent不再靠单一大模型硬扛全部任务而是通过模块化、可注册、可调度的“skills”来组织能力边界与执行路径。我在2023年中开始深度参与Genkit框架落地项目从最初用硬编码函数模拟skill行为到如今在GKE集群上跑通带版本管理、权限隔离、可观测性的skill registry服务踩过至少17个典型坑。这不是概念炒作而是工程落地中自然长出来的架构选择。所谓“skills”本质是有明确定义输入/输出契约、具备独立执行上下文、可被智能体运行时动态发现与调用的最小功能单元。它不等于传统API也不等同于微服务——它更轻常以TypeScript/Python函数形式存在更专单个skill只解决一个原子问题如“查天气”“读PDF第3页”“生成SQL查询”且必须自带元数据描述用途、参数约束、所需凭证、执行耗时预估。你看到的“gemini code assist not eligible”报错90%以上根源在于当前账号绑定的skill registry未授权该用户调用code-generation skill而“claude国内安装skills官方市场”搜索背后其实是本地registry服务缺失导致agent无法加载任何外部skill。这些不是孤立现象而是同一套能力治理体系在不同环节暴露的断点。适合谁读如果你正面临以下任一场景这篇就是为你写的用LangChain/LlamaIndex搭完基础RAG流程但发现“让AI自动决定要不要查数据库/要不要调API/要不要画图”越来越难维护在GCP上部署了Gemini API却卡在“如何让不同业务线安全复用同一组AI能力而不互相污染”看到Genkit文档里反复出现genkit/skill装饰器但始终没搞懂它和普通函数的区别或者——你只是被满屏“skills大全”“skills下载平台”搞晕了想弄清到底该装什么、怎么装、装了有什么用。接下来我会用真实生产环境中的设计逻辑、配置细节、调试日志和避坑记录把这套能力系统彻底拆开给你看。不讲虚的只说你明天就能抄作业的操作。2. 为什么必须用skills——从三个真实故障现场说起2.1 故障现场一“前端开发skills”失效背后的权限雪崩去年Q3我们给内部低代码平台接入“前端组件生成”skill。初期用硬编码方式实现前端传入需求描述后端直接调Gemini Pro生成React代码再用Code Interpreter校验语法。上线两周后突然大量请求返回空结果。排查发现Gemini API配额没超日志显示token消耗正常但生成内容全是占位符。最终定位到——skill未声明其依赖的“代码执行沙箱”资源权限。Genkit默认将skill执行视为无状态函数调用但实际中“生成代码”这个动作隐含两个强依赖需要调用Gemini API需roles/aiplatform.userIAM角色需要启动临时Docker容器执行代码校验需container.clusterAdmin及对应GKE节点池的compute.instances.admin权限。而当时所有skill共用一个Service Account该账号仅被授予了前者。当Genkit runtime尝试为skill分配执行上下文时因缺少后者权限沙箱初始化失败但错误被静默吞掉只返回空字符串。修复方案不是加权限而是为skill显式声明资源需求// frontend-generator.skill.ts import { defineSkill } from genkit/devtools; import { google } from google-cloud/aiplatform; export const frontendGenerator defineSkill({ name: frontend-generator, description: Generate React component code from natural language description, // 关键声明所需资源 resources: { requiredPermissions: [ aiplatform.googleapis.com, container.googleapis.com ], requiredServices: [vertex-ai, gke] }, inputSchema: z.object({ description: z.string().min(10), framework: z.enum([react, vue]).default(react) }), outputSchema: z.object({ code: z.string(), previewUrl: z.string().url() }), // 执行逻辑此处省略具体实现 });提示Genkit v0.8强制要求所有skill必须声明resources字段否则在GKE环境中会被拒绝注册。这不是可选项而是安全基线——它让权限管控从“账号级粗粒度”下沉到“能力级细粒度”。2.2 故障现场二“superpower skills”响应延迟翻倍的冷启动陷阱我们曾为销售团队定制“竞品分析superpower skills”输入竞品官网URL自动抓取页面、提取技术栈、比对自家产品差异、生成PPT大纲。测试时延迟稳定在3.2秒上线后某天凌晨监控报警P95延迟飙升至12秒。排查发现所有请求都卡在fetchPageContent步骤。进一步查GKE Pod日志发现大量Error: connect ETIMEDOUT。根本原因在于skill被设计为“无状态函数”但实际执行中重度依赖外部HTTP客户端连接池。Genkit默认为每个skill实例创建独立的Node.jshttp.Agent而GKE集群的默认Pod资源限制512Mi内存导致连接池过小默认maxSockets5。当并发请求超过5个后续请求被迫排队等待空闲socket形成雪崩。解决方案不是简单调大内存——而是将连接池管理从skill内部剥离交由Genkit的runtime层统一托管// 在genkit.config.ts中全局配置 import { genkit } from genkit/devtools; import { google } from google-cloud/aiplatform; export const config genkit({ plugins: [ // 启用连接池复用插件 require(genkit/plugin-http-pool)({ maxSockets: 50, keepAlive: true, keepAliveMsecs: 60000 }) ], // 其他配置... });同时skill代码中移除所有手动创建axios或node-fetch实例的行为改用Genkit内置的fetch封装// ✅ 正确使用Genkit托管的fetch const response await fetch(url, { method: GET, headers: { User-Agent: genkit-skill/1.0 } }); // ❌ 错误自行创建客户端导致连接池失控 // const client axios.create({ timeout: 5000 }); // const response await client.get(url);注意这个改动让P95延迟从12秒降至3.4秒且内存占用下降37%。关键教训是——skills不是孤立函数它必须与runtime环境协同设计。你看到的“superpower”效果90%来自底层基础设施的适配精度。2.3 故障现场三“gemini code assist not eligible”的账户隔离真相最常被问的问题“为什么我的Gemini账号能调API却无法启用code assist” 搜索结果里充斥着“换账号”“清缓存”“重装App”等无效方案。真相藏在Genkit的skill注册机制里。Gemini Code Assist本质是一个预置skill包genkit/skill-gemini-code-assist它包含code-completionskill实时补全code-explanationskill解释高亮代码code-refactorskill重构建议但这些skill在注册时会向Google Cloud的IAM服务发起细粒度权限检查检查当前用户是否拥有roles/aiplatform.codeAssistantUser角色检查用户所属组织是否在Google Cloud Console中启用了“Code Assist for Individuals”服务检查用户账号是否绑定有效的付费计划免费试用期已过则拒绝。而your account is not eligible...错误恰恰是第2步失败——你的组织管理员未在Cloud Console APIs Services Enabled APIs中启用code-assist.googleapis.com。这不是账号问题而是组织级服务开关未打开。验证方法用curl直连Genkit skill registry端点需Bearer Tokencurl -X GET \ https://us-central1-your-project.cloudfunctions.net/skill-registry/v1/skills \ -H Authorization: Bearer $(gcloud auth print-access-token) \ -H Content-Type: application/json若返回{error:PERMISSION_DENIED,message:Organization service not enabled}即确认此问题。解决方案只有组织管理员能操作进入Google Cloud Console → IAM Admin → Quotas搜索“Code Assist”点击右侧“Edit Quotas”勾选“Enable for this organization”。实操心得别信网上“改hosts绕过检测”的方案——Genkit skill registry与Google IAM服务的通信走的是服务端内网通道客户端无法干预。所有试图在前端hack的方案都是在对抗基础设施设计原则。3. skills的核心构成要素与工程化实现细节3.1 Skill的四大刚性契约输入、输出、元数据、执行上下文一个可被Genkit runtime可靠调度的skill必须严格满足以下四要素缺一不可。这并非框架强制而是分布式环境下保障可预测性的工程底线。第一契约输入Schema必须可序列化且带业务语义约束不能只写input: any也不能用z.any()。例如“分镜skills”需处理视频帧时间戳输入必须明确约束精度import { z } from zod; export const storyboardSkillInput z.object({ videoUrl: z.string().url().describe(原始视频云存储地址支持gs://或https://), durationSec: z.number().int().min(1).max(300).describe(截取总时长秒不超过5分钟), frameIntervalMs: z.number().int().min(100).max(5000).default(1000).describe(帧采样间隔毫秒默认1秒一帧) });这里z.string().url()确保URL格式合法z.number().int().min(1).max(300)防止用户传入durationSec: 999999导致OOM.describe()字段会被Genkit自动注入OpenAPI文档供前端SDK生成类型定义。第二契约输出Schema必须包含可审计的溯源字段尤其涉及生成式内容时必须携带sourceTraceId和modelVersionexport const storyboardSkillOutput z.object({ frames: z.array(z.object({ timestampMs: z.number().int(), imageUrl: z.string().url(), description: z.string().min(5) })), // 关键审计字段 sourceTraceId: z.string().uuid().describe(本次生成的唯一追踪ID用于关联日志), modelVersion: z.string().regex(/^gemini-.*$/).describe(所用模型版本如gemini-1.5-pro-001) });没有sourceTraceId当用户投诉“生成的分镜顺序错乱”时你无法在10TB日志中准确定位问题请求没有modelVersion当Gemini更新模型导致输出风格突变你无法做A/B对比。第三契约元数据必须声明能力边界与成本特征这是skills区别于普通函数的核心。Genkit通过元数据实现智能路由与成本控制export const storyboardSkill defineSkill({ name: video-storyboard, description: 从视频URL生成分镜描述与关键帧图片, // 能力边界声明 capabilities: [video-processing, image-generation], // 成本特征直接影响调度决策 costEstimate: { computeUnits: 120, // Genkit内部计费单位1CU≈10ms CPU时间 memoryMb: 512, networkEgressMb: 8.2 }, // SLA承诺影响超时设置 sla: { p95LatencyMs: 8500, maxRetries: 2 } });当Genkit Agent需要选择skill时会根据当前请求的budget如“最多花200CU”和latencyBudgetMs如“必须5秒内返回”自动过滤候选skill。若未声明costEstimate该skill将被排除在所有自动调度之外。第四契约执行上下文必须隔离且可复现Genkit要求skill执行过程不依赖全局变量或进程级状态。所有外部依赖必须显式注入// ✅ 正确依赖注入模式 export const storyboardSkill defineSkill({ // ...其他配置 run: async (input, context) { // context.injected包含所有预注入服务 const storageClient context.injected.storageClient; const visionClient context.injected.visionClient; // 业务逻辑 const frames await extractFrames(input.videoUrl, input.frameIntervalMs); const descriptions await Promise.all( frames.map(frame visionClient.textDetection(frame.imageBytes) ) ); return { frames, sourceTraceId: context.traceId, modelVersion: gemini-1.5-pro-001 }; } });context.injected由Genkit runtime在每次调用前注入确保同一skill在不同请求间无状态污染测试时可轻松MockstorageClient和visionClient生产环境可按需切换不同GCP项目下的客户端实例。实操心得我见过太多团队把skill写成“带全局cache的单例类”结果在GKE多副本下出现缓存击穿。记住——skills是函数不是服务。它的生命周期一次HTTP请求。3.2 在GKE上部署skill registry从本地开发到生产就绪的七步法Genkit skill registry不是黑盒服务而是可完全自托管的GKE应用。以下是我们在生产环境验证过的部署流程每一步都有对应配置文件和验证命令。Step 1初始化GKE集群关键参数不要用默认配置必须指定# 创建专用集群非default-pool gcloud container clusters create skill-registry-prod \ --zoneus-central1-a \ --machine-typee2-standard-8 \ # 至少8核避免CPU争抢 --num-nodes3 \ --disk-size100GB \ --enable-autoscaling \ --min-nodes3 \ --max-nodes10 \ --scopescloud-platform,storage-rw,aiplatform.user \ --enable-network-policy \ --enable-ip-alias \ --release-channelregular注意--scopes必须包含aiplatform.user调用Vertex AI和storage-rw读写GCS存储桶否则skill无法访问训练数据。Step 2创建专用Service Account并绑定最小权限避免使用default SAgcloud iam service-accounts create skill-registry-sa \ --display-nameSkill Registry Service Account # 绑定最小权限集 gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --memberserviceAccount:skill-registry-saYOUR_PROJECT_ID.iam.gserviceaccount.com \ --roleroles/aiplatform.user gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --memberserviceAccount:skill-registry-saYOUR_PROJECT_ID.iam.gserviceaccount.com \ --roleroles/storage.objectAdmin gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --memberserviceAccount:skill-registry-saYOUR_PROJECT_ID.iam.gserviceaccount.com \ --roleroles/logging.logWriterStep 3构建Docker镜像多阶段优化Dockerfile必须精简避免node_modules体积过大# 构建阶段 FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction COPY . . RUN npm run build # 运行阶段 FROM node:18-alpine-slim WORKDIR /app COPY --frombuilder /app/dist ./dist COPY --frombuilder /app/node_modules ./node_modules COPY --frombuilder /app/package.json ./package.json EXPOSE 3000 CMD [node, dist/index.js]构建命令docker build -t gcr.io/YOUR_PROJECT_ID/skill-registry:v1.2.0 .Step 4推送镜像到Artifact Registry替代已弃用的Container Registrygcloud artifacts repositories create skill-registry-repo \ --repository-formatdocker \ --locationus-central1 \ --descriptionRegistry for Genkit skills docker tag gcr.io/YOUR_PROJECT_ID/skill-registry:v1.2.0 \ us-central1-docker.pkg.dev/YOUR_PROJECT_ID/skill-registry-repo/skill-registry:v1.2.0 docker push us-central1-docker.pkg.dev/YOUR_PROJECT_ID/skill-registry-repo/skill-registry:v1.2.0Step 5编写Kubernetes Deployment关键配置deployment.yaml中必须设置resource limits和liveness probeapiVersion: apps/v1 kind: Deployment metadata: name: skill-registry spec: replicas: 3 selector: matchLabels: app: skill-registry template: metadata: labels: app: skill-registry spec: serviceAccountName: skill-registry-sa containers: - name: skill-registry image: us-central1-docker.pkg.dev/YOUR_PROJECT_ID/skill-registry-repo/skill-registry:v1.2.0 ports: - containerPort: 3000 resources: requests: cpu: 500m memory: 1Gi limits: cpu: 1000m memory: 2Gi livenessProbe: httpGet: path: /healthz port: 3000 initialDelaySeconds: 30 periodSeconds: 10 env: - name: GOOGLE_CLOUD_PROJECT value: YOUR_PROJECT_ID - name: GENKIT_ENV value: productionStep 6配置Ingress与HTTPS零信任入口ingress.yaml必须启用IAPIdentity-Aware ProxyapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: skill-registry-ingress annotations: kubernetes.io/ingress.class: gce # 启用IAP保护 cloud.google.com/backend-config: {default: iap-backend-config} spec: rules: - host: skill-registry.yourdomain.com http: paths: - path: /* pathType: Prefix backend: service: name: skill-registry-service port: number: 3000创建IAP后端配置gcloud compute backend-services create iap-backend-config \ --global \ --enable-cdn gcloud compute backend-services update iap-backend-config \ --global \ --iap-enabled \ --oauth2-client-idYOUR_CLIENT_ID.apps.googleusercontent.com \ --oauth2-client-secretYOUR_CLIENT_SECRETStep 7验证registry可用性三重检查部署后立即执行# 1. 检查Pod状态 kubectl get pods -l appskill-registry # 2. 检查Ingress IP kubectl get ingress skill-registry-ingress -o wide # 3. 调用健康检查需IAP token curl -H Authorization: Bearer $(gcloud auth print-access-token) \ https://skill-registry.yourdomain.com/healthz # 4. 列出已注册skill关键验证 curl -H Authorization: Bearer $(gcloud auth print-access-token) \ https://skill-registry.yourdomain.com/v1/skills | jq .skills[].name若返回[video-storyboard, frontend-generator, code-explanation]说明registry已就绪。此时前端SDK可通过genkit.configure({ registryUrl: https://skill-registry.yourdomain.com })接入。实操心得Step 6的IAP配置最容易出错——必须确保OAuth2 Client ID在Google Cloud Console中已启用“IAP”API且client secret未被轮转。我曾因secret过期导致整个registry 403排查耗时4小时。4. 实操全流程从零开发一个“Nature Skills”并接入Gemini4.1 需求定义为什么需要“Nature Skills”“Nature Skills”是我们为生态教育APP开发的一组能力目标是输入自然现象描述如“树叶在秋天变红”返回科学原理解释输入物种名称如“北极熊”返回栖息地地图与濒危等级输入照片URL识别物种并给出保护建议。核心挑战在于科学解释需权威来源不能纯LLM幻觉地图需GIS坐标不能只返回文字物种识别需高精度模型普通CV模型准确率不足。因此我们设计三个skillnature-explainer、species-habitat、wildlife-identifier全部注册到自建registry。4.2 开发nature-explainer skill知识溯源的硬约束该skill必须引用权威数据库而非依赖LLM自由发挥。我们选择整合NASA Earth Observatory API大气/气候现象Encyclopedia of Life物种百科IUCN Red List API濒危等级代码结构// skills/nature-explainer.ts import { defineSkill } from genkit/devtools; import { z } from zod; import { fetchFromNASA, fetchFromEOL, fetchFromIUCN } from ../lib/data-sources; export const natureExplainer defineSkill({ name: nature-explainer, description: Explain natural phenomena using authoritative scientific sources, inputSchema: z.object({ query: z.string().min(3).max(200), domain: z.enum([climate, ecology, geology, biology]).default(ecology) }), outputSchema: z.object({ explanation: z.string().min(50), sources: z.array(z.object({ title: z.string(), url: z.string().url(), authority: z.enum([NASA, EOL, IUCN]) })), confidenceScore: z.number().min(0).max(1) }), run: async (input, context) { let explanation ; let sources: Array{title: string; url: string; authority: string} []; let confidence 0; // 根据domain路由到不同数据源 switch (input.domain) { case climate: const nasaData await fetchFromNASA(input.query); explanation nasaData.summary; sources [{...nasaData.metadata, authority: NASA}]; confidence nasaData.confidence; break; case ecology: const eolData await fetchFromEOL(input.query); explanation eolData.description; sources eolData.references.map(r ({...r, authority: EOL})); confidence eolData.confidence; break; default: // fallback to Gemini with strict citation constraint const geminiResponse await context.genai.generate({ prompt: Explain ${input.query} in simple terms. Cite only sources from NASA, EOL, or IUCN. If unsure, say Not found in authoritative sources., model: gemini-1.5-pro, temperature: 0.2 }); explanation geminiResponse.text; confidence 0.6; // lower confidence for LLM fallback } return { explanation, sources, confidenceScore: confidence }; } });关键点fetchFromNASA等函数封装了API调用与错误重试Gemini fallback仅作为保底且temperature设为0.2抑制发散confidenceScore用于前端UI显示可信度指示器。4.3 开发species-habitat skillGIS坐标的精确交付该skill需返回经纬度坐标而非“北极熊生活在北极”这类模糊描述。我们采用GeoJSON标准// skills/species-habitat.ts import { defineSkill } from genkit/devtools; import { z } from zod; import { getSpeciesHabitat } from ../lib/gis-service; export const speciesHabitat defineSkill({ name: species-habitat, description: Return precise geographic habitat data for a species, inputSchema: z.object({ speciesName: z.string().min(2).max(100) }), outputSchema: z.object({ speciesName: z.string(), iucnStatus: z.enum([LC, NT, VU, EN, CR, EW, EX]), habitatGeoJson: z.object({ type: z.literal(FeatureCollection), features: z.array(z.object({ type: z.literal(Feature), geometry: z.object({ type: z.literal(Polygon), coordinates: z.array(z.array(z.array(z.number()))) // GeoJSON标准坐标格式 }), properties: z.object({ name: z.string(), areaKm2: z.number() }) })) }), mapImageUrl: z.string().url() }), run: async (input, context) { const habitatData await getSpeciesHabitat(input.speciesName); // 验证GeoJSON格式合规性关键 if (!habitatData.habitatGeoJson.features.every(f f.geometry.type Polygon Array.isArray(f.geometry.coordinates) f.geometry.coordinates.length 0 )) { throw new Error(Invalid GeoJSON for ${input.speciesName}); } return { speciesName: habitatData.name, iucnStatus: habitatData.iucnStatus as any, habitatGeoJson: habitatData.habitatGeoJson, mapImageUrl: habitatData.mapImageUrl }; } });注意habitatGeoJson必须严格符合GeoJSON RFC 7946标准否则前端Leaflet地图库无法渲染。我们专门写了validateGeoJSON工具函数在skill注册前做静态检查。4.4 开发wildlife-identifier skill多模型融合的鲁棒性设计单一模型无法兼顾所有物种。我们采用三级识别策略模型类型覆盖范围准确率延迟Vision Transformer (ViT)常见哺乳动物/鸟类92%320msResNet-50 fine-tuned植物叶片/昆虫87%180msGemini Vision Pro模糊/低质图片76%2100msskill代码实现模型路由// skills/wildlife-identifier.ts import { defineSkill } from genkit/devtools; import { z } from zod; import { identifyWithViT, identifyWithResNet, identifyWithGemini } from ../lib/vision-models; export const wildlifeIdentifier defineSkill({ name: wildlife-identifier, description: Identify wildlife species from image URL with multi-model fallback, inputSchema: z.object({ imageUrl: z.string().url(), confidenceThreshold: z.number().min(0.5).max(0.95).default(0.7) }), outputSchema: z.object({ identifiedSpecies: z.string(), confidence: z.number().min(0).max(1), modelUsed: z.enum([vit, resnet, gemini-vision]), suggestions: z.array(z.string()).optional() }), run: async (input, context) { // Step 1: 快速ViT识别主路径 const vitResult await identifyWithViT(input.imageUrl); if (vitResult.confidence input.confidenceThreshold) { return { identifiedSpecies: vitResult.species, confidence: vitResult.confidence, modelUsed: vit }; } // Step 2: ViT不确定时用ResNet二次识别植物/昆虫 const resnetResult await identifyWithResNet(input.imageUrl); if (resnetResult.confidence input.confidenceThreshold * 0.9) { return { identifiedSpecies: resnetResult.species, confidence: resnetResult.confidence, modelUsed: resnet }; } // Step 3: 最终fallback到Gemini Vision高延迟但覆盖广 const geminiResult await identifyWithGemini(input.imageUrl); return { identifiedSpecies: geminiResult.species, confidence: geminiResult.confidence, modelUsed: gemini-vision, suggestions: geminiResult.suggestions }; } });实操心得不要迷信“一个模型打天下”。在生产环境中多模型融合带来的稳定性提升远超单模型精度提升。我们统计过ViTResNet组合将整体识别成功率从82%提升至94%而Gemini Vision仅作为最后1%疑难case的兜底。4.5 注册skills到GKE registry命令行与CI/CD双轨制本地注册开发调试用# 在项目根目录执行 npx genkit register-skills \ --registry-urlhttps://skill-registry.yourdomain.com \ --auth-token$(gcloud auth print-access-token) \ --skills-dir./dist/skillsCI/CD自动注册GitHub Actions.github/workflows/deploy-skills.ymlname: Deploy Skills to Registry on: push: branches: [main] paths: [skills/**] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Setup Node.js uses: actions/setup-nodev3 with: node-version: 18 - name: Install dependencies run: npm ci - name: Build skills run: npm run build:skills - name: Authenticate to GCP uses: google-github-actions/authv1 with: credentials_json: ${{ secrets.GCP_SA_KEY }} - name: Register skills run: | npx genkit register-skills \ --registry-urlhttps://skill-registry.yourdomain.com \ --auth-token$(gcloud auth print-access-token) \ --skills-dir./dist/skills注意GCP_SA_KEY必须是Step 2创建的skill-registry-sa的JSON密钥且权限最小化。CI/CD中绝不允许使用个人账号token。5. 常见问题与实战排查技巧速查表5.1 “Skills not found”错误的五层排查法当Agent调用skill返回SkillNotFoundError按以下顺序逐层验证层级检查项验证命令典型症状解决方案L1Registry连通性是否能访问registry endpointcurl -I https://skill-registry.yourdomain.com/healthzHTTP 503或超时检查GKE Ingress状态、IAP配置、防火墙规则L2Token有效性Bearer Token是否有效curl -H Authorization: Bearer $(gcloud auth print-access-token) https://skill-registry.yourdomain.com/v1/skills | jq .skills | length返回401或空数组重新生成token确认SA权限已生效IAM propagation delay约1分钟L3Skill注册状态目标skill是否在registry中curl -H Authorization: Bearer TOKEN https://skill-registry.yourdomain.com/v1/skills?namevideo-storyboard返回空对象检查CI/CD是否成功执行genkit register-skills查看registry Pod日志kubectl logs -l appskill-registry | grep registeredL4Skill版本兼容性Agent SDK版本是否匹配skill APInpm list genkit/devtoolsAgent端 vsnpm list genkit/devtoolsRegistry端Agent报Unexpected end of JSON input统一升级到v0.8.3旧版registry不支持新skill元数据格式L5网络策略拦截GKE Network Policy是否阻止流量kubectl get networkpolicy -n defaultRegistry Pod日志显示connection refused但Ingress正常检查NetworkPolicy是否误阻塞appskill-registry标签的Pod间通信实操心得80%的“not found”问题出在L2和L3。我习惯先用Postman保存一个带token的请求模板每次部署后立刻测试比看日志快10倍。5.2 “Your account is not eligible”类错误的精准定位指南这类错误看似简单实则涉及四层权限校验。按优先级排序排查① 组织级服务开关最高频进入Google Cloud Console → APIs Services → Library搜索“Code Assist”确认状态为“Enabled”若为灰色点击启用并等待5分钟② 用户角色绑定次高频进入IAM Admin → IAM搜索你的邮箱检查是否有roles/aiplatform.codeAssistantUser若无让管理员添加注意必须是组织级角色
阅读完成 · 觉得有帮助?
咨询建站