> [!NOTE]
> **Note:** This guide builds on the [Roads Management Insights AI agent](https://developers.google.com/maps/architecture/rmi-adk-agent.md.txt) reference architecture and its [sample source code on GitHub](https://github.com/googlemaps-samples/insights-samples/blob/main/roads_management_insights/rmi_adk_agent/README.md). It draws on lessons from that agent, but these techniques apply to any [Agent Development Kit (ADK)](https://adk.dev) agent that must reason over a specialized domain.

## Overview

Large language models have broad general knowledge, but they don't know your
domain's specific metrics, database schemas, or calculation formulas. Without
this context, the model guesses, which leads to incorrect SQL and flawed
analysis.

The RMI ADK Agent addresses this limitation through **skills** . Consider a user who
asks *"how congested was Storrow Drive yesterday?"* . To answer, the agent must
know that RMI expresses congestion as the **Travel Time Index (TTI)** , the ratio
of live `duration_in_seconds` to free-flow `static_duration_in_seconds` in the
`historical_travel_time` table. An agent without skills might instead invent an
`average_speed` column (RMI reports only categorical speed, never km/h) or apply
the wrong formula, producing a confident but wrong answer.

While the agent needs this domain knowledge, putting every metric definition,
table schema, and SQL caveat into a single system prompt is inefficient.

### Limitations of large system prompts

Putting all domain rules and schemas into a single system prompt causes several
problems:

- **Higher costs and slower responses**: Sending a huge prompt on every turn wastes tokens and increases latency, even for questions that don't need those rules.
- **Worse instruction following**: As a prompt grows longer with edge cases, the model becomes more likely to ignore or forget specific rules.
- **Harder maintenance**: Combining everything into one prompt makes it hard to update or test individual rules without breaking others.

## Skills

Agent **Skills** organize domain knowledge into modular folders that the agent
loads only when needed. Each skill is a directory containing a `SKILL.md` file
with Markdown instructions and a YAML header.

Instead of loading everything upfront, the agent only keeps each skill's short
`description` in its base prompt. When a user asks a question relevant to a
skill, the agent loads the full instructions for that turn. This keeps prompts
small and saves context space for actual conversation history.

Skills also provide a clean separation of concerns: you can write, test, and
update individual capabilities in isolation without risking unintended side
effects across unrelated domains. A production agent typically uses multiple
focused skills rather than one giant prompt.

## Anatomy of a skill

A `SKILL.md` file has two parts: a YAML header for routing and a Markdown body
for instructions.

### 1. YAML header

```yaml
---
name: rmi-traffic-metrics-grounding
description: >
  Standard traffic performance metrics computable from RMI BigQuery
  tables. Covers congestion severity (TTI), delay, travel time
  reliability (LOTTR, BTI, PTI, CoV), congestion frequency, speed
  breakdowns, and network-wide congestion rates. Use when the user asks
  about traffic conditions, congestion, reliability, delay, or network
  health.
---
```

The model uses the `description` to decide whether to load the skill. Because
the model only sees this description before deciding to load the skill, make sure
it clearly lists the topics covered, typical user phrasing, and when to trigger
it.

### 2. Markdown body

The body provides the domain-specific guidance the model follows once loaded.
The RMI metrics skill body includes the exact TTI formula
(`duration_in_seconds / static_duration_in_seconds`), a verified BigQuery SQL
template for each metric, and trigger phrases that map user intent to the right
metric. Providing structured, verified instructions keeps the model grounded and
prevents it from guessing schema or formula details.

## Register skills with ADK

Group skills into a `SkillToolset` and add them to the agent's tool list:

```python
from google.adk import skills
from google.adk.tools import skill_toolset

rmi_skill_toolset = skill_toolset.SkillToolset(
    skills=[
        # TRAFFIC_METRICS_SKILL_DIR points to the skill's SKILL.md folder.
        skills.load_skill_from_dir(TRAFFIC_METRICS_SKILL_DIR),
    ],
)

# root_agent = llm_agent.Agent(..., tools=[*bq_tools, rmi_skill_toolset])
```

Here, `TRAFFIC_METRICS_SKILL_DIR` points to the directory containing the
traffic metrics grounding skill.

## Bundle tools with skills

Because skills are text-based instructions, relying solely on the model to
interpret and execute complex logic can lead to inconsistencies. Attaching
executable tools to a skill provides determinism: code handles strict
calculations, validations, and API interactions, while the skill instructs the
model on when and how to use them.

Bundling tools also avoids global context bloat. Instead of exposing every
specialized tool upfront, tools are scoped to load only when their
corresponding domain skill is active.

You can attach specific tools directly to a skill in its YAML header:

```yaml
metadata:
  adk_additional_tools:
    - calculate_custom_metric
```

This ensures the model receives both the tool schema and its usage
instructions together just in time, keeping the base toolset lean.

## Example: Grounding a congestion query

1. The user asks *"How congested is Storrow Drive during evening rush?"*
2. The base system prompt advertises only each skill's name and description, so the agent sees that `rmi-traffic-metrics-grounding` covers "congestion" and calls `load_skill` to pull in its full instructions for this query.
3. With the skill loaded, the agent applies the TTI definition and the verified SQL template it provides, computing the ratio against `historical_travel_time` instead of guessing a formula.

Because a skill's body is only fetched when a query needs it, skills the agent
never uses never enter context, keeping the base system prompt small.

## Key takeaways

- **Ground with domain guidance**: Supply explicit instructions, constraints, and business logic rather than relying on general model assumptions.
- **Use modular skills**: Split knowledge into focused skills instead of one giant system prompt to save tokens, reduce latency, and improve accuracy.
- **Write clear descriptions**: Include specific trigger phrases and keywords in each skill's description so the agent loads it reliably.
- **Include concrete examples**: Add verified examples and reference workflows to skill bodies to keep outputs consistent and accurate.
- **Bundle tools for determinism**: Attach executable tools to skills to handle strict validation and execution while keeping the base toolset lean.

### Next steps

- **Explore advanced skill patterns** : Read the [Developer's Guide to Building ADK Agents with Skills](https://developers.googleblog.com/developers-guide-to-building-adk-agents-with-skills/) to learn about ADK skills.

## Contributors

[Nathaniel Thomas](https://www.linkedin.com/in/nathaniel-thomas-profile) \|
Software Engineering Intern, Google Maps Platform