Skills for ADK agents¶
An agent Skill is a self-contained unit of functionality that an ADK agent can use to perform a specific task. An agent Skill encapsulates the necessary instructions, resources, and tools required for a task, based on the Agent Skill specification. The structure of a Skill allows it to be loaded incrementally to minimize the impact on the operating context window of the agent.
Experimental
The Skills feature is experimental. We welcome your feedback via the respective ADK GitHub repositories: ADK Python, ADK TypeScript, ADK Go.
Get started¶
Use the SkillToolset class to make one or more Skills available to your agent.
You can define skills in code or load
skills from a filesystem.
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,
],
)
For a complete code example of an ADK agent with a Skill, including both file-based and in-line Skill definitions, see the code sample skills_agent.
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
}
For a complete example, see the code sample in skills.
Understand Skills¶
The Skills feature allows you to create modular packages of Skill instructions and resources that agents can load on demand. This approach helps you organize your agent's capabilities and optimize the context window by only loading instructions when they are needed. The structure of Skills is organized into three levels:
- L1 (Metadata): Provides metadata for skill discovery. This information
is defined in the frontmatter section of the
SKILL.mdfile and includes properties such as the Skill name and description. - L2 (Instructions): Contains the primary instructions for the Skill,
loaded when the Skill is triggered by the agent. This information is defined
in the body of the
SKILL.mdfile. - L3 (Resources): Includes additional resources such as reference
materials, assets, and scripts that can be loaded as needed. These resources
are organized into the following directories:
references/: Additional Markdown files with extended instructions, workflows, or guidance.assets/: Resource materials such as database schemas, API documentation, templates, or examples.scripts/: Executable scripts supported by the agent runtime.
Skills directory structure¶
The following directory structure shows the recommended way to include Skills in
your ADK agent project. The example-skill/ directory shown below, and any
parallel Skill directories, must follow the
Agent Skill specification file
structure. Only the SKILL.md file is required.
my_agent/
agent.py (or agent.ts / main.go)
.env
skills/
example-skill/ # Skill
SKILL.md # main instructions (required)
references/
REFERENCE.md # detailed API reference
FORMS.md # form-filling guide
*.md # domain-specific information
assets/
*.* # templates, images, data
scripts/
*.py # utility scripts (Python)
*.js # utility scripts (JavaScript)
*.ts # utility scripts (TypeScript)
Skill sources¶
You can define skills within the code or read skills from a filesystem.
Define Skills in code¶
You can define Skills within the code of your agent, as shown below.
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.",
},
),
)
Note
ADK Go does not currently provide a standard Source for inline skills,
though this may be added in the future.
To define skills directly in code, you must implement the skill.Source
interface yourself, as shown below.
import (
"context"
"io"
"slices"
"strings"
"google.golang.org/adk/tool/skilltoolset/skill"
)
// Example implementation of a static in-memory 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
The Source interface can be backed by any data store (such as a database)
to support dynamic use cases like live updates and personalization.
Read Skills from filesystem¶
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"))
// This example doesn't use any optional wrappers, but you can use them if
// needed, e.g.:
// source, _, err = skill.WithFrontmatterPreloadSource(ctx, source)
// source, _, err = skill.WithCompletePreloadSource(ctx, source)
// For more information about these and other wrappers, see
// 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
}
Next steps¶
Check out these resources for building agents with Skills: