Skills for Agents:Agent 技能扩展
Table of Contents
Skills for Agents:Agent 技能扩展
如果说 Tools 是 Agent 的"手脚"——让它能够执行具体的操作(查询数据库、调用 API、发送邮件),那么 Skills 就是 Agent 的"专业知识库"——让它在特定领域内具备系统化的思维框架、最佳实践和领域语言。Skill 机制是 ADK Go 中实现 Agent 专业化、模块化和可复用性的核心架构组件。
从 Tool 到 Skill:能力抽象的升级
理解 Skill 与 Tool 的区别对于正确使用 ADK Go 至关重要:
| 维度 | Tool | Skill |
|---|---|---|
| 抽象层级 | 原子操作(单个函数调用) | 能力模块(包含思维链、多步骤流程) |
| 状态管理 | 通常无状态 | 可维护内部状态和上下文 |
| 复杂度 | 简单、单一职责 | 复杂、领域专用 |
| 复用方式 | 作为函数被调用 | 作为模块被挂载 |
| 示例 | query_database、send_email | 数据分析、代码审查、合同审核 |
一个 Skill 本质上是一个预编排的 Agent 行为模板。它可能包含:
- 领域特定的系统指令(System Instruction)
- 推荐的 Tool 组合
- 预设的思维链(Chain-of-Thought)模板
- 输出格式规范
- 错误处理和回退策略
例如,“数据分析 Skill"不仅包含调用 Python 解释器的 Tool,还包含"如何理解数据分布→选择合适图表→生成洞察"的完整思维框架。
ADK Go 内置 Skills 深度解析
ADK Go 提供了若干开箱即用的内置 Skills,每个都针对特定场景进行了深度优化。
Code Interpreter Skill
这是最常用的内置 Skill 之一,它赋予 Agent 执行代码的能力。但不同于简单地暴露一个 exec_python Tool,Code Interpreter Skill 封装了完整的代码执行沙箱、错误处理和结果格式化逻辑。
package main
import (
"context"
"fmt"
"log"
"os"
"google.golang.org/adk/agent"
"google.golang.org/adk/llm"
"google.golang.org/adk/skill"
)
func main() {
ctx := context.Background()
model, err := llm.NewGeminiModel(ctx, llm.GeminiConfig{
APIKey: os.Getenv("GOOGLE_API_KEY"),
Model: "gemini-2.0-pro",
})
if err != nil {
log.Fatalf("模型初始化失败: %v", err)
}
// 配置 Code Interpreter Skill
codeSkill := skill.CodeInterpreter(
skill.WithTimeout(30*time.Second), // 代码执行超时
skill.WithMaxMemory(512*1024*1024), // 内存限制 512MB
skill.WithAllowedImports([]string{ // 允许导入的包白名单
"numpy", "pandas", "matplotlib", "json", "math",
}),
skill.WithForbiddenPatterns([]string{ // 禁止的危险操作
`os\.system`, `subprocess\.call`, `eval\(`, `exec\(`,
}),
)
agent, err := agent.New(agent.Config{
Name: "data-analyst",
Model: model,
Instruction: `你是一个数据分析师。当用户上传数据或询问数据相关问题时:
1. 先理解数据的结构和类型
2. 使用 Code Interpreter 进行探索性数据分析(EDA)
3. 生成可视化图表辅助说明
4. 提供数据驱动的洞察和建议
5. 所有分析必须基于实际代码执行结果,不得编造数据`,
Skills: []skill.Skill{codeSkill},
})
if err != nil {
log.Fatalf("Agent 创建失败: %v", err)
}
resp, err := agent.Run(ctx, "分析这份销售数据的趋势:\n月份,销售额\n1月,15000\n2月,18000\n3月,22000\n4月,19000\n5月,25000")
if err != nil {
log.Fatalf("执行失败: %v", err)
}
fmt.Println(resp.Text)
}
生产环境注意事项:
沙箱隔离:Code Interpreter 必须在完全隔离的环境中运行。我们推荐使用 gVisor、Firejail 或容器技术实现额外的安全层。
资源限制:未加限制的代码执行可能导致 CPU 耗尽或内存溢出。始终设置
MaxMemory和Timeout。网络隔离:默认情况下,代码执行环境应禁止网络访问,防止数据外泄或恶意下载。
状态持久化:如果需要在多次调用间保持变量状态,使用 Skill 提供的 Session 存储机制,而非全局变量。
Web Search Skill
Web Search Skill 封装了搜索引擎调用、结果筛选、内容提取和可信度评估的完整流程。它与 Grounding 的区别在于:Grounding 是隐式的、自动的搜索增强,而 Web Search Skill 是显式的、由 Agent 主动调用的研究能力。
webSearchSkill := skill.WebSearch(
skill.WithSearchProvider(skill.GoogleSearchProvider{
APIKey: os.Getenv("GOOGLE_SEARCH_API_KEY"),
CX: os.Getenv("GOOGLE_SEARCH_CX"),
}),
skill.WithResultLimit(10),
skill.WithContentExtractor(skill.ReadabilityExtractor{}), // 使用 Readability 算法提取正文
skill.WithCredibilityScorer(skill.DomainCredibilityScorer{
// 可信域名加分
TrustedDomains: []string{"arxiv.org", "github.com", "wikipedia.org"},
// 低质量域名降分
BlockedDomains: []string{"spam-site.com"},
}),
)
Data Analysis Skill
Data Analysis Skill 是 Code Interpreter Skill 的上层封装,专门针对结构化数据分析场景优化。它内置了:
- 数据清洗和预处理模板
- 常用统计检验方法
- 自动图表类型推荐(基于数据特征选择最合适的可视化方式)
- 异常值检测和处理策略
dataSkill := skill.DataAnalysis(
skill.WithVisualizationBackend(skill.MatplotlibBackend{
OutputFormat: "png",
DPI: 150,
}),
skill.WithStatisticalTests([]string{"t-test", "chi-square", "anova"}),
)
自定义 Skill:构建领域专家 Agent
内置 Skills 覆盖了通用场景,但企业级应用往往需要针对特定业务领域构建自定义 Skill。以下是一个为"智能合同审核"场景设计的自定义 Skill 完整实现:
package contract
import (
"context"
"fmt"
"regexp"
"strings"
"google.golang.org/adk/skill"
"google.golang.org/adk/tool"
)
// ContractReviewSkill 封装了合同审核的专业能力
type ContractReviewSkill struct {
riskRules []RiskRule
templateLibrary TemplateLibrary
complianceDB ComplianceDatabase
}
// RiskRule 定义一条风险识别规则
type RiskRule struct {
Name string
Severity string // critical, high, medium, low
Pattern *regexp.Regexp
Description string
Suggestion string
}
// NewContractReviewSkill 创建合同审核 Skill
func NewContractReviewSkill(db ComplianceDatabase) *ContractReviewSkill {
return &ContractReviewSkill{
riskRules: []RiskRule{
{
Name: "无限责任条款",
Severity: "critical",
Pattern: regexp.MustCompile(`(?i)无限责任|unlimited liability`),
Description: "合同包含无限责任条款,可能导致不可控的法律风险",
Suggestion: "建议修改为'有限责任',并明确赔偿上限",
},
{
Name: "自动续约条款",
Severity: "high",
Pattern: regexp.MustCompile(`(?i)自动续约|automatic.*renewal|tacit.*renewal`),
Description: "存在自动续约机制,可能导致合同在不知情的情况下延续",
Suggestion: "建议增加明确的续约通知期(如提前 30 天书面通知)",
},
{
Name: "单方变更权",
Severity: "high",
Pattern: regexp.MustCompile(`(?i)单方变更|单方修改|unilateral.*modification`),
Description: "一方拥有单方面修改合同条款的权利",
Suggestion: "建议改为'双方协商一致后方可变更'",
},
},
complianceDB: db,
}
}
func (s *ContractReviewSkill) Name() string {
return "contract-review"
}
func (s *ContractReviewSkill) Description() string {
return "专业的合同风险审核能力,能够识别合同中的法律风险、条款漏洞和合规问题"
}
func (s *ContractReviewSkill) Instructions() string {
return `你是一个专业的合同审核律师助手。当用户提交合同文本时,你需要:
1. **结构分析**:识别合同的类型(采购、服务、劳动、租赁等)和主要条款
2. **风险扫描**:使用内置规则库扫描高风险条款
3. **合规检查**:对照最新法律法规检查合规性
4. **条款建议**:对模糊、不公平或缺失的条款提出修改建议
5. **生成报告**:输出结构化的审核报告,包含风险等级、问题描述和修改建议
审核原则:
- 优先保护委托方利益
- 关注可执行性(条款是否能在实际纠纷中被法院支持)
- 注意时效性(法律有效期、通知期限等)
- 保持客观中立,不夸大风险也不遗漏问题`
}
func (s *ContractReviewSkill) Tools() []tool.Tool {
return []tool.Tool{
&ClauseExtractorTool{},
&ComplianceCheckTool{DB: s.complianceDB},
&RiskCalculatorTool{},
}
}
func (s *ContractReviewSkill) BeforeRun(ctx context.Context, input string) (string, error) {
// 预处理:标准化合同文本
normalized := strings.ReplaceAll(input, "\r\n", "\n")
normalized = regexp.MustCompile(`\n{3,}`).ReplaceAllString(normalized, "\n\n")
return normalized, nil
}
func (s *ContractReviewSkill) AfterRun(ctx context.Context, output string) (string, error) {
// 后处理:确保报告格式统一
if !strings.Contains(output, "## 审核结论") {
output += "\n\n## 审核结论\n\n本合同经审核发现上述风险点,建议委托方在签署前与法务部门确认。"
}
return output, nil
}
// 注册 Skill
func init() {
skill.Register("contract-review", func(config map[string]interface{}) (skill.Skill, error) {
db, ok := config["compliance_db"].(ComplianceDatabase)
if !ok {
return nil, fmt.Errorf("contract-review skill 需要 compliance_db 配置")
}
return NewContractReviewSkill(db), nil
})
}
使用自定义 Skill
import "your-module/contract"
func main() {
db := initComplianceDB()
contractSkill := contract.NewContractReviewSkill(db)
agent, err := agent.New(agent.Config{
Name: "legal-assistant",
Model: model,
Skills: []skill.Skill{contractSkill},
})
// ...
}
Skill 的组合与编排
复杂的业务场景往往需要多个 Skill 协同工作。ADK Go 支持 Skill 的组合模式,允许构建"Skill 管道"或"Skill 路由器”。
Skill 管道模式
数据依次流经多个 Skill,每个 Skill 对数据进行特定处理:
pipeline := skill.NewPipeline(
skill.DataExtractionSkill{}, // 第一步:从非结构化文本提取数据
skill.DataValidationSkill{}, // 第二步:验证数据完整性和准确性
skill.DataAnalysisSkill{}, // 第三步:分析数据模式和趋势
skill.ReportGenerationSkill{}, // 第四步:生成分析报告
)
agent, err := agent.New(agent.Config{
Name: "data-pipeline-agent",
Skills: []skill.Skill{pipeline},
})
Skill 路由模式
根据输入类型动态选择最合适的 Skill:
router := skill.NewRouter()
router.Register("code", skill.CodeInterpreter())
router.Register("data", skill.DataAnalysis())
router.Register("image", skill.ImageAnalysis())
router.SetDefault(skill.GeneralConversation())
agent, err := agent.New(agent.Config{
Name: "multi-skill-agent",
Skills: []skill.Skill{router},
})
生产环境中的 Skill 管理
Skill 版本控制
Skills 作为 Agent 的核心能力组件,其变更需要严格的版本管理:
type VersionedSkill struct {
skill.Skill
Version string
Changelog string
Deprecated bool
ReplacedBy string // 如果已弃用,指向替代版本
}
func (v *VersionedSkill) ValidateCompatibility(other skill.Skill) error {
// 检查 Skill 版本兼容性
// 例如:v2 的 Skill 是否兼容 v1 的 Agent 配置
}
Skill 热加载
生产环境中不希望因为更新 Skill 而重启整个 Agent 服务。可以实现 Skill 的热加载机制:
type HotReloadableSkill struct {
current atomic.Value // 存储 *skill.Skill
watcher *fsnotify.Watcher
}
func (h *HotReloadableSkill) Load(path string) error {
// 监听 Skill 定义文件的变化
h.watcher.Add(path)
go func() {
for event := range h.watcher.Events {
if event.Op&fsnotify.Write == fsnotify.Write {
newSkill, err := loadSkillFromFile(path)
if err != nil {
log.Printf("Skill 热加载失败: %v", err)
continue
}
h.current.Store(newSkill)
log.Printf("Skill 已热更新: %s", newSkill.Name())
}
}
}()
return nil
}
func (h *HotReloadableSkill) Current() skill.Skill {
return h.current.Load().(skill.Skill)
}
Skill 性能监控
每个 Skill 的调用延迟、成功率和资源消耗都应该被监控:
func (s *MonitoredSkill) Execute(ctx context.Context, input string) (string, error) {
start := time.Now()
result, err := s.inner.Execute(ctx, input)
duration := time.Since(start)
metrics.RecordHistogram("skill_latency", float64(duration.Milliseconds()),
metrics.Tag{"skill", s.Name()})
if err != nil {
metrics.IncrementCounter("skill_errors",
metrics.Tag{"skill", s.Name()})
}
return result, err
}
常见陷阱与最佳实践
陷阱 1:Skill 过度耦合
将太多逻辑塞进一个 Skill 会导致维护困难和复用性降低。遵循"单一职责原则",一个 Skill 只负责一个明确的专业领域。
陷阱 2:Skill 与 Tool 边界模糊
如果一个"Skill"只是简单封装了一个 Tool 调用,没有额外的领域逻辑或思维框架,那它应该是一个 Tool,而不是 Skill。
陷阱 3:忽略 Skill 的上下文窗口消耗
复杂的 Skill Instructions 会占用大量上下文窗口。监控每个 Skill 的指令长度,必要时将长指令拆分为核心指令 + 可加载的参考文档。
陷阱 4:Skill 间的状态冲突
当多个 Skill 同时被激活时,它们可能产生冲突的指令或争夺 Tool 调用权。使用明确的优先级机制和冲突解决策略。
下一步
Skills 赋予 Agent 专业化的领域能力,使其从通用助手升级为行业专家。接下来我们将探讨 Callbacks 与 Plugins——ADK Go 最强大的扩展机制,让你能够在 Agent 生命周期的每一个关键节点插入自定义逻辑,实现真正的深度定制。
← Artifacts | Callbacks 与 Plugins →
想跟着学更多 Go ADK 实战?关注「全栈之巅-梦兽编程」公众号,每周更新 Go / AI 编程实战干货。
