
从云原生开发者视角解析Chrome Skills功能,探讨Agent应用的云原生落地路径
2026年4月,谷歌在Chrome浏览器中正式上线Skills功能,将OpenClaw为代表的Agent自动化能力深度集成到浏览器生态。
本文将从云原生架构、技术选型、实现细节和最佳实践等角度,深度解析Chrome Skills如何与云原生技术栈结合,为开发者提供完整的实现指南。
Chrome Skills的云原生架构包含以下核心组件:
┌────────────────────────────────────────┐
│ 浏览器端 │
│ (Chrome Extension + Skills UI) │
├────────────────────────────────────────┤
│ 边缘层 │
│ (负载均衡 + API网关 + 消息队列) │
├────────────────────────────────────────┤
│ 服务层 │
│ (Gemini服务 + Agent调度 + 技能管理) │
├────────────────────────────────────────┤
│ 数据层 │
│ (Redis + MongoDB + 对象存储) │
├────────────────────────────────────────┤
│ 基础设施 │
│ (腾讯云COS + 云数据库 + 监控告警) │
└────────────────────────────────────────┘| 服务 | 腾讯云 | 阿里云 | AWS | Azure | 推荐方案 | |------|---------|-------|-----|----------| | 对象存储 | COS | OSS | S3 | COS(成本最优) | | 数据库 | MongoDB | MySQL | PostgreSQL | MongoDB(文档型) | | 缓存 | Redis | Memcached | ElastiCache | Redis | | 消息队列 | Ckafka | RabbitMQ | SQS | Tencent MQ | | 函数计算 | SCF | Ckafka | 无 | Ckafka(需时可选) | | 监控 | 腾讯监控 | 云监控 | CloudWatch | Tencent监控 |
架构决策:
// 云服务配置
const geminiConfig = {
region: "ap-guangzhou",
endpoint: "https://generativelanguage.googleapis.com",
model: "gemini-2.0-pro",
maxTokens: 2048,
timeout: 30000
};
// 腾讯云API密钥管理
const tencentCloudConfig = {
secretId: process.env.GEMINI_SECRET_ID,
secretKey: process.env.GEMINI_SECRET_KEY,
region: process.env.TENCENT_CLOUD_REGION || "ap-guangzhou"
};
class GeminiCloudService {
constructor() {
this.apiKey = null;
this.keyCache = new Map();
this.requestQueue = new Map();
}
async initialize() {
// 1. 从腾讯云获取API密钥
const { secretId, secretKey } = tencentCloudConfig;
try {
// 调用腾讯云API获取密钥
const response = await fetch(
`https://cam.ap-guangzhou.tencentcloudapi.com/v2/index.php?Action=GetSecret`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `TC3-HMAC-SHA256 ${this._generateSignature(secretId, secretKey)}`
},
body: JSON.stringify({
secretId: secretId,
secretName: "gemini-api-key"
})
}
);
if (!response.ok) {
throw new Error('Failed to fetch API key');
}
const data = await response.json();
// 验证密钥格式
if (data.secretType !== 'Gemini API Key') {
throw new Error('Invalid secret type');
}
this.apiKey = data.secretKey;
// 缓存密钥
const cacheKey = `gemini_key_${Date.now()}`;
this.keyCache.set(cacheKey, {
key: this.apiKey,
timestamp: Date.now(),
ttl: 3600000 // 1小时
});
return this.apiKey;
} catch (error) {
console.error('Failed to initialize Gemini service:', error);
throw error;
}
}
_generateSignature(secretId, secretKey) {
// 生成HMAC-SHA256签名
const crypto = require('crypto');
const now = Date.now().toString();
const signatureStr = `date=${now}&secretId=${secretId}`;
return crypto
.createHmac('sha256', secretKey)
.update(signatureStr)
.digest('base64');
}
async generateContent(prompt, options = {}) {
// 2. 使用缓存的API密钥调用Gemini
const apiKey = await this.getOrRefreshKey();
try {
const response = await fetch(
`${geminiConfig.endpoint}?key=${apiKey}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
contents: [{
parts: [{
text: prompt
}]
}],
generationConfig: {
temperature: options.temperature || 0.7,
topP: options.topP || 1.0,
topK: options.topK || 40,
maxOutputTokens: options.maxTokens || 2048
}
})
}
);
if (!response.ok) {
throw new Error('Gemini API request failed');
}
const data = await response.json();
return {
success: true,
content: data.candidates[0].content.parts[0].text,
usage: {
promptTokens: data.usageMetadata.promptTokenCount,
completionTokens: data.usageMetadata.candidatesTokenCount,
totalTokens: data.usageMetadata.totalTokenCount
}
};
} catch (error) {
return {
success: false,
error: error.message
};
}
async getOrRefreshKey() {
// 检查缓存中的API密钥
const now = Date.now();
const cacheKeys = Array.from(this.keyCache.keys());
for (const cacheKey of cacheKeys) {
const cached = this.keyCache.get(cacheKey);
// 检查缓存是否过期(1小时TTL)
if (cached && (now - cached.timestamp) < 3600000) {
return cached.key;
}
// 删除过期缓存
this.keyCache.delete(cacheKey);
}
// 如果没有有效缓存,重新获取
return await this.initialize();
}
}
// 使用示例
const geminiService = new GeminiCloudService();
await geminiService.initialize();
// 调用Gemini服务
const result = await geminiService.generateContent('分析这个网页内容...', {
temperature: 0.8,
maxTokens: 1024
});
console.log('Gemini result:', result);class CloudTaskScheduler {
constructor(redisClient, mongoClient) {
this.redis = redisClient;
this.mongo = mongoClient;
this.taskQueues = new Map();
this.workerPool = new WorkerPool();
}
async submitTask(task) {
// 1. 任务入队
const taskId = this.generateTaskId();
const queueKey = `task_queue_${task.type}`;
await this.redis.lpush(queueKey, JSON.stringify({
taskId,
task: task.data,
priority: task.priority,
status: 'pending',
createdAt: Date.now(),
attempts: 0
}));
// 2. 触发任务处理
this.processQueue(queueKey);
return taskId;
}
async processQueue(queueKey) {
while (true) {
// 使用Redis的BLPOP获取任务
const taskData = await this.redis.brpop(queueKey);
if (!taskData) {
// 队列为空,等待一段时间
await new Promise(resolve => setTimeout(resolve, 1000));
continue;
}
const task = JSON.parse(taskData);
// 3. 检查任务状态
const currentStatus = await this.mongo.collection('tasks').findOne(
{ taskId: task.taskId }
);
if (currentStatus && currentStatus.status !== 'pending') {
console.log(`Task ${task.taskId} already in progress`);
continue;
}
// 4. 分配Worker
const worker = await this.workerPool.acquire(task.type);
try {
// 5. 执行任务
const result = await worker.execute(task);
// 6. 更新任务状态为已完成
await this.mongo.collection('tasks').updateOne(
{ taskId: task.taskId },
{
$set: {
status: 'completed',
completedAt: new Date(),
result: result,
attempts: currentStatus ? currentStatus.attempts + 1 : 1
}
}
);
// 7. 记录执行日志
await this.logExecution(task, result, true);
} catch (error) {
// 8. 错误处理
await this.mongo.collection('tasks').updateOne(
{ taskId: task.taskId },
{
$set: {
status: 'failed',
failedAt: new Date(),
error: error.message,
attempts: currentStatus ? currentStatus.attempts + 1 : 1
}
}
);
await this.logExecution(task, result, false);
} finally {
// 9. 释放Worker
this.workerPool.release(worker);
}
}
generateTaskId() {
return `task_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
}
async logExecution(task, result, success) {
// 记录执行日志到MongoDB
await this.mongo.collection('execution_logs').insertOne({
taskId: task.taskId,
result: result,
success: success,
timestamp: new Date(),
executionTime: result.executionTime || 0
});
}
}
// Worker池实现
class WorkerPool {
constructor(maxWorkers = 4) {
this.maxWorkers = maxWorkers;
this.workers = [];
this.availableWorkers = [];
}
async acquire(taskType) {
// 获取可用Worker
const worker = this.availableWorkers.find(w => w.type === taskType);
if (worker) {
this.availableWorkers = this.availableWorkers.filter(w => w !== worker);
worker.busy = true;
return worker;
}
// 如果没有可用Worker,等待
return new Promise(resolve => {
const checkInterval = setInterval(() => {
const worker = this.availableWorkers.find(w => w.type === taskType && !w.busy);
if (worker) {
clearInterval(checkInterval);
resolve(worker);
}
}, 100);
});
}
release(worker) {
worker.busy = false;
this.availableWorkers.push(worker);
}
}
// 使用示例
const redisClient = require('redis').createClient();
const mongoClient = require('mongodb').MongoClient(process.env.MONGODB_URI);
const scheduler = new CloudTaskScheduler(redisClient, mongoClient);
// 提交Agent任务
const taskId = await scheduler.submitTask({
type: 'web_analysis',
priority: 1,
data: {
url: 'https://example.com',
options: { timeout: 30000 }
}
});
console.log('Task submitted:', taskId);// MongoDB数据模型
const mongoose = require('mongoose');
const SkillSchema = new mongoose.Schema({
skillId: { type: String, required: true, unique: true, index: true },
name: { type: String, required: true },
description: { type: String, required: true },
version: { type: String, default: '1.0.0' },
promptTemplate: { type: String, required: true },
variables: [{
name: { type: String, required: true },
type: { type: String, required: true, enum: ['text', 'number', 'select', 'boolean'] },
defaultValue: mongoose.Schema.Types.Mixed,
required: { type: Boolean, default: false }
}],
executionConfig: {
type: { type: String, required: true, enum: ['simple', 'agent', 'multi_step'] },
timeout: { type: Number, default: 30000 },
maxTokens: { type: Number, default: 2048 },
temperature: { type: Number, default: 0.7 },
retryPolicy: { type: String, enum: ['none', 'fixed', 'exponential'], default: 'none' }
},
permissions: [{
type: { type: String, required: true },
scope: [String],
required: { type: Boolean, default: true }
}],
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now },
isActive: { type: Boolean, default: true },
authorId: { type: String, required: true },
isPublic: { type: Boolean, default: false },
downloadCount: { type: Number, default: 0 },
rating: { type: Number, default: 0 },
tags: [{ type: String }]
});
// MongoDB模型定义
const SkillExecutionSchema = new mongoose.Schema({
skillId: { type: String, required: true, index: true },
userId: { type: String, required: true, index: true },
executionContext: mongoose.Schema.Types.Mixed },
prompt: { type: String, required: true },
result: mongoose.Schema.Types.Mixed, required: true },
executionTime: { type: Number, required: true },
success: { type: Boolean, required: true },
error: mongoose.Schema.Types.String },
apiUsage: {
promptTokens: { type: Number },
completionTokens: { type: Number },
totalTokens: { type: Number }
},
createdAt: { type: Date, default: Date.now }
});
// 数据访问层
const SkillModel = mongoose.model('Skill', SkillSchema);
const SkillExecutionModel = mongoose.model('SkillExecution', SkillExecutionSchema);
// 数据服务类
class SkillDataService {
constructor() {
SkillModel;
SkillExecutionModel;
}
async initialize() {
await this.SkillModel;
await this.SkillExecutionModel;
}
async createSkill(skillData) {
const skill = new this.SkillModel(skillData);
return await skill.save();
}
async getSkill(skillId) {
return await this.SkillModel.findOne({ skillId, isActive: true });
}
async updateSkill(skillId, updateData) {
return await this.SkillModel.updateOne(
{ skillId },
updateData
);
}
async deleteSkill(skillId) {
return await this.SkillModel.updateOne(
{ skillId },
{ isActive: false }
);
}
async recordExecution(executionData) {
const execution = new this.SkillExecutionModel(executionData);
return await execution.save();
}
async getExecutions(skillId, limit = 50) {
return await this.SkillExecutionModel
.find({ skillId })
.sort({ createdAt: -1 })
.limit(limit);
}
async getSkillStatistics(skillId) {
const executions = await this.getExecutions(skillId);
const total = executions.length;
const successful = executions.filter(e => e.success).length;
const failed = executions.filter(e => !e.success).length;
const avgTime = executions.reduce((sum, e) => sum + e.executionTime, 0) / total;
return {
total,
successful,
failed,
successRate: total > 0 ? successful / total : 0,
avgExecutionTime: avgTime
};
}
}
// 使用示例
const dataService = new SkillDataService();
await dataService.initialize();
// 创建技能
const newSkill = await dataService.createSkill({
skillId: 'web_summary_v1',
name: '网页内容总结',
description: '智能总结当前网页的长文章',
version: '1.0.0',
promptTemplate: '你是一个专业的网页内容分析助手...',
variables: [{
name: 'page_content',
type: 'text',
required: true
}],
executionConfig: {
type: 'simple',
timeout: 30000,
maxTokens: 1024
},
permissions: [{
type: 'read_active_tab',
scope: ['<all_urls>']
}],
isPublic: true
});
console.log('Skill created:', newSkill);// 性能监控类
class PerformanceMonitor {
constructor() {
this.metrics = {
totalRequests: 0,
totalExecutionTime: 0,
cacheHitRate: 0,
errorRate: 0,
memoryUsage: 0,
networkLatency: 0
};
}
recordRequest(apiType, latency) {
this.metrics.totalRequests++;
this.metrics.networkLatency += latency;
this._updateMetrics();
}
recordExecution(executionTime, cached) {
this.metrics.totalExecutionTime += executionTime;
if (cached) {
this.metrics.cacheHitRate = (this.metrics.cacheHitRate * 0.99) + 0.01;
}
this._updateMetrics();
}
recordMemoryUsage(usage) {
this.metrics.memoryUsage = usage;
this._updateMetrics();
}
_updateMetrics() {
// 计算平均值和比率
const cacheHitRate = (this.metrics.cacheHitRate * 100).toFixed(2) + '%';
const errorRate = (this.metrics.errorRate * 100).toFixed(2) + '%';
// 上报到监控服务
this._uploadToMonitoring({
cacheHitRate: parseFloat(cacheHitRate),
errorRate: parseFloat(errorRate),
avgExecutionTime: (this.metrics.totalExecutionTime / this.metrics.totalRequests).toFixed(2)
});
}
_uploadToMonitoring(metrics) {
// 上报到腾讯云监控
fetch('https://monitor.tencentcloudapi.com/api/metrics', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.getAuthToken()}`
},
body: JSON.stringify({
service: 'chrome-skills',
metrics,
timestamp: Date.now()
})
});
}
getAuthToken() {
return process.env.TENCENT_CLOUD_AUTH_TOKEN;
}
}
// 使用示例
const monitor = new PerformanceMonitor();
// 记录API请求
monitor.recordRequest('gemini', 156);
// 记录技能执行
monitor.recordExecution(2450, true);
monitor.recordExecution(1230, false);
// 记录内存使用
monitor.recordMemoryUsage(512 * 1024 * 1024); // 512MB
console.log('Performance Metrics:', monitor.metrics);// 腾讯云安全配置
const tencentCloudSecurityConfig = {
// CAM角色配置
camRole: {
secretId: process.env.TENCENT_CLOUD_CAM_ROLE_SECRET_ID,
secretKey: process.env.TENCENT_CLOUD_CAM_ROLE_SECRET_KEY,
region: process.env.TENCENT_CLOUD_REGION || "ap-guangzhou",
policy: 'QcloudReadOnly' // 只读权限
},
// 安全组配置
securityGroups: {
fullAccess: {
description: '完全访问权限',
permissions: ['read_active_tab', 'scripting', 'storage']
},
limitedAccess: {
description: '受限访问权限',
permissions: ['read_active_tab', 'storage']
},
readOnly: {
description: '只读权限',
permissions: ['read_active_tab']
}
},
// 数据加密配置
encryption: {
algorithm: 'AES-256-GCM',
keySize: 32, // 256位
mode: 'CBC',
padding: 'PKCS7'
}
};
// 权限管理类
class TencentCloudPermissionManager {
constructor(camClient) {
this.camClient = camClient;
this.cachedPolicies = new Map();
}
async checkPermission(userId, resource, action) {
// 1. 检查缓存策略
const cacheKey = `policy_${userId}_${resource}_${action}`;
const cached = this.cachedPolicies.get(cacheKey);
if (cached && !this.isPolicyExpired(cached)) {
return cached.allowed;
}
// 2. 查询CAM策略
const policy = await this.camClient.getPolicy(userId);
// 3. 缓存策略
this.cachedPolicies.set(cacheKey, {
policy,
allowed: policy.allow,
timestamp: Date.now(),
ttl: 3600000 // 1小时
});
return policy.allow;
}
isPolicyExpired(cachedPolicy) {
const now = Date.now();
return (now - cachedPolicy.timestamp) > cachedPolicy.ttl;
}
async grantPermission(userId, resource, action, reason) {
// 记录权限授予
await this.camClient.grantPolicy(userId, resource, action, reason);
// 清除相关缓存
const cacheKeys = Array.from(this.cachedPolicies.keys()).filter(
key => key.startsWith(`policy_${userId}_${resource}`)
);
for (const cacheKey of cacheKeys) {
this.cachedPolicies.delete(cacheKey);
}
}
}
// 使用示例
const permissionManager = new TencentCloudPermissionManager(camClient);
// 检查用户权限
const hasPermission = await permissionManager.checkPermission(
'user123',
'skills',
'execute',
'执行技能'
);
console.log('Has permission:', hasPermission);// 部署流程
const deploymentPipeline = {
// 1. 环境准备
prepareEnvironment: async () => {
console.log('准备部署环境...');
// 配置腾讯云服务
await configureTencentCloudServices();
// 初始化数据库
await initializeDatabase();
// 配置负载均衡
await setupLoadBalancer();
console.log('环境准备完成');
},
// 2. 应用部署
deployApplication: async () => {
console.log('部署应用...');
// 上传代码到对象存储
await uploadToCOS();
// 配置云函数
await deployCloudFunctions();
// 配置API网关
await setupAPIGateway();
// 配置CDN
await setupCDN();
console.log('应用部署完成');
},
// 3. 服务启动
startServices: async () => {
console.log('启动云服务...');
// 启动Gemini服务
await startGeminiServices();
// 启动Agent调度服务
await startTaskScheduler();
// 启动监控服务
await startMonitoringServices();
console.log('所有服务启动完成');
},
// 4. 验证部署
validateDeployment: async () => {
console.log('验证部署...');
// 健康检查
await healthCheck();
// 性能测试
await performanceTest();
// 功能测试
await functionTest();
console.log('部署验证完成');
}
};
// 执行部署流程
async function main() {
try {
await deploymentPipeline.prepareEnvironment();
await deploymentPipeline.deployApplication();
await deploymentPipeline.startServices();
await deploymentPipeline.validateDeployment();
console.log('部署成功!');
} catch (error) {
console.error('部署失败:', error);
process.exit(1);
}
}
main();// 成本控制策略
const costControlStrategies = {
// API调用成本控制
geminiAPI: {
dailyQuota: 1000000, // 100万token/天
currentUsage: 0,
costPerMillionTokens: 2.00, // $2/100万token
budget: 200.00 // 日预算$200
},
// 对象存储成本控制
cosStorage: {
monthlyQuota: 1000, // 1TB
currentUsage: 0,
costPerGB: 0.118, // ¥0.118/GB
budget: 118.00, // 月预算¥118
},
// 数据库成本控制
mongodb: {
connectionPool: {
maxSize: 100,
minSize: 10
},
readWriteUnits: {
monthlyQuota: 10000000, // 1000万次操作
currentUsage: 0,
costPerMillion: 1.00, // ¥1/100万次操作
budget: 100.00, // 月预算¥100
}
};
// 成本监控类
class CostMonitor {
constructor() {
this.costs = {
gemini: costControlStrategies.geminiAPI,
cos: costControlStrategies.cosStorage,
mongodb: costControlStrategies.mongodb
};
}
async checkGeminiQuota() {
const usage = await getGeminiUsage();
if (usage.currentUsage >= this.costs.gemini.dailyQuota) {
console.warn('Gemini API quota exceeded');
return {
exceeded: true,
remaining: 0
};
}
return {
exceeded: false,
remaining: this.costs.gemini.dailyQuota - usage.currentUsage,
cost: (this.costs.gemini.dailyQuota - usage.currentUsage) *
(this.costs.gemini.costPerMillionTokens / 1000000)
};
}
async getMonthlyCost() {
const geminiCost = await this.getCurrentGeminiCost();
const cosCost = await this.getCurrentCOSCost();
const mongoCost = await this.getCurrentMongoDBCost();
const totalCost = geminiCost + cosCost + mongoCost;
return {
gemini: geminiCost,
cos: cosCost,
mongodb: mongoCost,
total: totalCost
};
}
}
// 使用示例
const costMonitor = new CostMonitor();
// 检查Gemini配额
const quotaStatus = await costMonitor.checkGeminiQuota();
console.log('Quota status:', quotaStatus);
// 获取月度成本
const monthlyCost = await costMonitor.getMonthlyCost();
console.log('Monthly cost:', monthlyCost);近期目标(6-12个月)
中长期目标(1-2年)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。