Skip to content

ADK 智能体技能

Supported in ADKPython v1.25.0TypeScript v0.6.1Go v1.2.0Experimental

智能体 技能 (Skill) 是一个自包含的功能单元,ADK 智能体可以使用它来执行特定任务。智能体技能封装了任务所需的必要指令、资源和工具,基于智能体技能规范 (Agent Skill specification)。技能的结构允许它增量加载,以最小化对智能体运行上下文窗口的影响。

实验性

技能功能是实验性的。欢迎你通过相应的 ADK GitHub 仓库提供反馈:ADK PythonADK TypeScriptADK Go

开始使用

使用 SkillToolset 类让你的智能体可以使用一个或多个技能。你可以在代码中定义技能或从文件系统加载技能

import pathlib

from google.adk import Agent
from google.adk.skills import load_skill_from_dir
from google.adk.tools import skill_toolset

weather_skill = load_skill_from_dir(
    pathlib.Path(__file__).parent / "skills" / "weather_skill"
)

my_skill_toolset = skill_toolset.SkillToolset(
    skills=[weather_skill],
    additional_tools=[get_weather_tool],
)

root_agent = Agent(
    model="gemini-flash-latest",
    name="skill_user_agent",
    description="An agent that can use specialized skills.",
    instruction=(
        "You are a helpful assistant that can leverage skills to perform tasks."
    ),
    tools=[
        my_skill_toolset,
    ],
)

有关带有技能的 ADK 智能体的完整代码示例,包括基于文件的和内联的技能定义,请参阅代码示例 skills_agent

import {Agent, FunctionTool, SkillToolset, loadSkillFromDir} from '@google/adk';
import * as path from 'node:path';
import {z} from 'zod';

const weatherSkill = await loadSkillFromDir(
  path.join(__dirname, 'skills/weather_skill')
);

const getWeatherTool = new FunctionTool({
  name: 'get_weather',
  description: 'Gets the weather for a given location.',
  parameters: z.object({
    location: z.string().describe('The city and state, e.g. San Francisco, CA'),
  }),
  execute: async ({location}) => {
    return {
      location,
      temperature: '72°F',
      condition: 'Sunny',
    };
  },
});

const mySkillToolset = new SkillToolset([weatherSkill], {
  additionalTools: [getWeatherTool],
});

const rootAgent = new Agent({
  model: 'gemini-flash-latest',
  name: 'skill_user_agent',
  description: 'An agent that can use specialized skills.',
  instruction:
    'You are a helpful assistant that can leverage skills to perform tasks.',
  tools: [mySkillToolset],
});

export default rootAgent;
import (
    "context"
    "os"

    "google.golang.org/adk/agent/llmagent"
    "google.golang.org/adk/tool/skilltoolset/skill"
    "google.golang.org/adk/tool/skilltoolset"
    "google.golang.org/adk/tool"
)

mySkillToolset, err := skilltoolset.New(ctx, skilltoolset.Config{
    Source: skill.NewFileSystemSource(os.DirFS("./skills")),
})
if err != nil {
    // handle error
}

rootAgent, err := llmagent.New(llmagent.Config{
    Name:        "skill_user_agent",
    Model:       model,
    Description: "An agent that can use specialized skills.",
    Instruction: "You are a helpful assistant that can leverage skills to perform tasks.",
    Toolsets:    []tool.Toolset{mySkillToolset},
})
if err != nil {
    // handle error
}

有关完整示例,请参阅 skills 中的代码示例。

理解技能

技能功能允许你创建技能指令和资源的模块化包,智能体可以根据需要加载。这种方法有助于你组织智能体的能力,并由于仅在需要时加载指令而优化上下文窗口。技能的结构分为三个级别:

  • L1 (元数据): 提供用于技能发现的元数据。此信息定义在 SKILL.md 文件的 Frontmatter 部分,包括技能名称和描述等属性。
  • L2 (指令): 包含技能的主要指令,当技能被智能体触发时加载。此信息定义在 SKILL.md 文件的正文中。
  • L3 (资源): 包括其他资源,如参考材料、资产和脚本,可以根据需要加载。这些资源组织在以下目录中:
    • references/:具有扩展指令、工作流或指南的其他 Markdown 文件。
    • assets/:资源材料,如数据库模式、API 文档、模板或示例。
    • scripts/:智能体运行环境支持的可执行脚本。

技能目录结构

以下目录结构展示了在你的 ADK 智能体项目中包含技能的推荐方式。下面显示的 example-skill/ 目录以及任何并行的技能目录,必须遵循智能体技能规范的文件结构。仅 SKILL.md 文件是必需的。

my_agent/
    agent.py (or agent.ts / main.go)
    .env
    skills/
        example-skill/        # Skill
            SKILL.md          # main instructions (required)
            references/
                REFERENCE.md  # 详细的 API 参考
                FORMS.md      # 表单填写指南
                *.md          # 领域特定信息
            assets/
                *.*           # 模板、图像、数据
            scripts/
                *.py          # 实用脚本 (Python)
                *.js          # 实用脚本 (JavaScript)
                *.ts          # 实用脚本 (TypeScript)

技能来源

你可以在代码中定义技能或从文件系统读取技能

在代码中定义技能

你可以在智能体代码中定义技能,如下所示。

from google.adk.skills import models

greeting_skill = models.Skill(
    frontmatter=models.Frontmatter(
        name="greeting-skill",
        description=(
            "A friendly greeting skill that can say hello to a specific person."
        ),
    ),
    instructions=(
        "Step 1: Read the 'references/hello_world.txt' file to understand how"
        " to greet the user. Step 2: Return a greeting based on the reference."
    ),
    resources=models.Resources(
        references={
            "hello_world.txt": "Hello! So glad to have you here!",
            "example.md": "This is an example reference.",
        },
    ),
)
import {Agent, Skill, SkillToolset} from '@google/adk';

const greetingSkill: Skill = {
  frontmatter: {
    name: 'greeting-skill',
    description: 'A friendly greeting skill that can say hello to a specific person.',
  },
  instructions:
    "Step 1: Read the 'references/hello_world.txt' file to understand how to greet the user. Step 2: Return a greeting based on the reference.",
  resources: {
    references: {
      'hello_world.txt': 'Hello! So glad to have you here!',
      'example.md': 'This is an example reference.',
    },
  },
};

const mySkillToolset = new SkillToolset([greetingSkill]);

const rootAgent = new Agent({
  model: 'gemini-flash-latest',
  name: 'greeting_agent',
  description: 'An agent that uses an inline greeting skill.',
  instruction: 'You are a helpful assistant that uses skills to greet people.',
  tools: [mySkillToolset],
});

export default rootAgent;

Note

ADK Go 目前不提供内联技能的标准 Source,尽管将来可能会添加。 要直接在代码中定义技能,你必须自己实现 skill.Source 接口,如下所示。

import (
    "context"
    "io"
    "slices"
    "strings"

    "google.golang.org/adk/tool/skilltoolset/skill"
)

// 静态内存中 skill.Source 的示例实现:
type StaticSource struct{}

func (s *StaticSource) ListFrontmatters(ctx context.Context) ([]*skill.Frontmatter, error) {
    return []*skill.Frontmatter{
        {Name: "greeting-skill", Description: "A friendly greeting skill that can say hello to a specific person."},
    }, nil
}

func (s *StaticSource) LoadFrontmatter(ctx context.Context, name string) (*skill.Frontmatter, error) {
    if name != "greeting-skill" {
        return nil, skill.ErrSkillNotFound
    }
    return &skill.Frontmatter{Name: "greeting-skill", Description: "A friendly greeting skill that can say hello to a specific person."}, nil
}

func (s *StaticSource) LoadInstructions(ctx context.Context, name string) (string, error) {
    if name != "greeting-skill" {
        return "", skill.ErrSkillNotFound
    }
    return "Step 1: Read the 'references/hello_world.txt' file to understand how to greet the user. Step 2: Return a greeting based on the reference.", nil
}

func (s *StaticSource) ListResources(ctx context.Context, name, subpath string) ([]string, error) {
    if name != "greeting-skill" {
        return nil, skill.ErrSkillNotFound
    }
    if !slices.Contains([]string{"", ".", "references", "references/"}, subpath) {
        return nil, skill.ErrResourceNotFound
    }
    return []string{"references/hello_world.txt", "references/example.md"}, nil
}

func (s *StaticSource) LoadResource(ctx context.Context, name, resourcePath string) (io.ReadCloser, error) {
    if name != "greeting-skill" {
        return nil, skill.ErrSkillNotFound
    }
    switch resourcePath {
    case "references/hello_world.txt":
        return io.NopCloser(strings.NewReader("Hello! So glad to have you here!")), nil
    case "references/example.md":
        return io.NopCloser(strings.NewReader("This is an example reference.")), nil
    default:
        return nil, skill.ErrResourceNotFound
    }
}

Note

Source 接口可以由任何数据存储(例如数据库)支持,以支持动态用例,如实时更新和个性化。

从文件系统读取技能

import pathlib

from google.adk.skills import load_skill_from_dir
from google.adk.tools import skill_toolset

greeting_skill = load_skill_from_dir(
    pathlib.Path(__file__).parent / "skills" / "greeting-skill"
)
weather_skill = load_skill_from_dir(
    pathlib.Path(__file__).parent / "skills" / "weather-skill"
)

my_skill_toolset = skill_toolset.SkillToolset(
    skills=[weather_skill, greeting_skill],
)
import (
    "os"

    "google.golang.org/adk/tool/skilltoolset/skill"
    "google.golang.org/adk/tool/skilltoolset"
)

// ...

source := skill.NewFileSystemSource(os.DirFS("./skills"))

// 此示例未使用任何可选包装器,但你可以根据需要
// 使用它们,例如:
//   source, _, err = skill.WithFrontmatterPreloadSource(ctx, source)
//   source, _, err = skill.WithCompletePreloadSource(ctx, source)
// 有关这些及其他包装器的更多信息,请参阅
// https://pkg.go.dev/google.golang.org/adk/tool/skilltoolset/skill#Source。

skillToolset, err := skilltoolset.New(ctx, skilltoolset.Config{
    Source: source,
})
if err != nil {
    // handle error
}

下一步

查看这些用于构建带有技能的智能体的资源: