Blog

Mastering Agent Skills with adk-skill in Rust

Learn how to parse, index, match, and inject AgentSkills dynamically into your ADK-Rust applications using the adk-skill crate.

Posted on: 2026-03-24 by AI Assistant


Building intelligent and dynamic AI agents requires a robust way to manage their capabilities and personas. The adk-skill crate for ADK-Rust provides exactly that: an engine for specification-driven agent skills. By implementing the agentskills.io specification, it lets you control agent behavior through configuration rather than just code.

In this post, we’ll explore how you can use adk-skill to load, match, and inject skills from a skills directory into your agent’s workflow.

What is adk-skill?

At its core, adk-skill is built around the philosophy of Logic-as-Data. Instead of hardcoding prompts and tool access, you define them in Markdown files with YAML frontmatter. These files can live in a .skills/ directory and dictate the agent’s persona, its allowed tools, and required references.

This provider-agnostic crate handles:

  1. Discovery: Scanning your project for .md skill files.
  2. Parsing & Validation: Ensuring your skills meet the agentskills.io standards or your own permissive conventions.
  3. Indexing: Building a deterministically sorted and hashed index for fast retrieval.
  4. Selection & Injection: Scoring skills based on a user’s query and injecting the most relevant instructions into the LLM context.

Creating a Skill

Let’s create a quick example of a skill. Save this file as .skills/support.md in your project root:

---
name: customer-support-agent
description: Official support persona for resolving user issues.
version: "1.0.0"
allowed-tools:
  - ticket_lookup
  - issue_refund
---
You are a helpful customer support agent. Be polite, concise, and always check the ticket history before taking action.

How to Use Agent Skills in Rust

To use these skills in your application, you need to load the index, configure a selection policy, and inject the chosen skill into the user’s prompt.

Here is a step-by-step code example on how to achieve this using adk-skill:

1. Loading the Skill Index and Matching

First, you discover and load the skills from your local directory, then match them against a user query.

use adk_skill::{SelectionPolicy, load_skill_index, select_skills};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // 1. Load the skill index from the current directory (or specific path like "./.skills")
    let index = load_skill_index(".")?;
    
    // 2. Define a Selection Policy
    let policy = SelectionPolicy {
        top_k: 1,           // We only want the best matching skill
        min_score: 1.0,     // Minimum relevance score
        include_tags: vec![],
        exclude_tags: vec![],
    };

    // 3. Match against a user query
    let user_query = "I need help with a broken feature on my account.";
    let matches = select_skills(&index, user_query, &policy);
    
    println!("Found {} matching skills.", matches.len());
    for m in matches {
        println!("Skill Matched: {} (Score: {:.2})", m.skill.name, m.score);
    }

    Ok(())
}

2. Injecting the Skill into Content

Once you’ve matched a skill, the next step is injecting it into the content you’re sending to the LLM. The adk-skill crate provides an apply_skill_injection function to handle this seamlessly.

use adk_core::Content;
use adk_skill::{SelectionPolicy, apply_skill_injection, load_skill_index};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let index = load_skill_index(".")?;
    
    // Setup policy
    let policy = SelectionPolicy {
        min_score: 1.0,
        ..SelectionPolicy::default()
    };
    
    // Create the user's input content
    let mut content = Content::new("user")
        .with_text("I need help with a broken feature on my account.");

    // Inject the best matching skill's instructions into the content
    // The last parameter is max_injected_chars (e.g., 1500)
    let matched = apply_skill_injection(&mut content, &index, &policy, 1500);
    
    if let Some(m) = matched {
        println!("Successfully injected skill: {}", m.skill.name);
        
        // The content now includes the skill instructions prepended to the user query:
        // [skill:customer-support-agent]
        // You are a helpful customer support agent...
        // [/skill]
        // I need help with a broken feature on my account.
    }

    Ok(())
}

Advanced Usage: The Context Coordinator

For more complex applications, you can use the ContextCoordinator. It bridges the gap between skill selection and agent execution by verifying that tools listed in allowed-tools actually exist in your ToolRegistry. This prevents the LLM from hallucinating actions it cannot perform.

By leveraging adk-skill, you can cleanly separate your agent’s logic (code) from its behavior (data). This separation allows for rapid iteration on personas and capabilities without constantly recompiling your core Rust application.

Give adk-skill a try in your next AI agent project, and see how much easier it is to steer your LLM’s behavior dynamically!