> ## Documentation Index
> Fetch the complete documentation index at: https://java.agentscope.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Skill

## Overview

Agent Skills are modular skill packages that extend agent capabilities. Each Skill contains instructions, metadata, and optional resources (such as scripts, reference documentation, examples, etc.), which agents will automatically use for relevant tasks.

**Reference**: [Claude Agent Skills Official Documentation](https://platform.claude.com/docs/zh-CN/agents-and-tools/agent-skills/overview)

## Core Features

### Progressive Disclosure Mechanism

Adopts **three-stage on-demand loading** to optimize context: Initially loads only metadata (\~100 tokens/Skill) → AI loads complete instructions when needed (\<5k tokens) → On-demand access to resource files. Tools are also progressively disclosed, activated only when the Skill is in use.

**Workflow:** User Query → AI Identifies Relevant Skill → Calls `load_skill_through_path` Tool to Load Content and Activate Bound Tools → On-Demand Resource Access → Task Completion

**Unified Loading Tool**: `load_skill_through_path(skillId, resourcePath)` provides a single entry point for loading skill resources

* `skillId` uses an enum field, ensuring selection only from registered Skills, guaranteeing accuracy
* `resourcePath` is the resource path relative to the Skill root directory (e.g., `references/api-doc.md`)
* Returns a list of all available resource paths when the path is incorrect, helping the LLM correct errors

### Adaptive Design

We have further abstracted skills so that their discovery and content loading are no longer dependent on the file system. Instead, the LLM discovers and loads skill content and resources through tools. At the same time, to maintain compatibility with the existing skill ecosystem and resources, skills are still organized according to file system structure for their content and resources.

**Organize your skill content and resources just like organizing a skill directory in a file system!**

Taking the [Skill Structure](#skill-structure) as an example, this directory-structured skill is represented in our system as:

```java theme={null}
AgentSkill skill = AgentSkill.builder()
    .name("data_analysis")
    .description("Use this skill when analyzing data, calculating statistics, or generating reports")
    .skillContent("# Data Analysis\n...")
    .addResource("references/api-doc.md", "# API Reference\n...")
    .addResource("references/best-practices.md", "# Best Practices\n...")
    .addResource("examples/example1.java", "public class Example1 {\n...\n}")
    .addResource("scripts/process.py", "def process(data): ...\n")
    .build();
```

### Skill Structure

```text theme={null}
skill-name/
├── SKILL.md          # Required: Entry file with YAML frontmatter and instructions
├── references/       # Optional: Detailed reference documentation
│   ├── api-doc.md
│   └── best-practices.md
├── examples/         # Optional: Working examples
│   └── example1.java
└── scripts/          # Optional: Executable scripts
    └── process.py
```

### SKILL.md Format Specification

```yaml theme={null}
---
name: skill-name                    # Required: Skill name (lowercase letters, numbers, underscores)
description: This skill should be used when...  # Required: Trigger description, explaining when to use
homepage: https://example.com/docs  # Optional: Additional metadata exposed to the agent prompt
metadata:
  clawdbot:
    requires:
      env:
        - API_KEY
---

# Skill Name

## Feature Overview
[Detailed description of the skill's functionality]

## Usage Instructions
[Usage steps and best practices]

## Available Resources
- references/api-doc.md: API reference documentation
- scripts/process.py: Data processing script
```

**Required Fields:**

* `name` - Skill name (lowercase letters, numbers, underscores)
* `description` - Skill functionality and usage scenarios, helps AI determine when to use

**Metadata Notes:**

* Any additional YAML frontmatter fields are preserved as skill metadata, not limited to predefined fields
* Nested maps and lists are supported and keep their structure and insertion order
* Frontmatter is parsed with SnakeYAML `SafeConstructor`; only top-level YAML objects of type `Map` are accepted
* Invalid frontmatter or frontmatter exceeding the parser limit is ignored and treated as empty metadata

## Quick Start

### 1. Create a Skill

#### Method 1: Using Builder

```java theme={null}
AgentSkill skill = AgentSkill.builder()
    .name("data_analysis")
    .description("Use when analyzing data...")
    .putMetadata("homepage", "https://example.com/docs")
    .skillContent("# Data Analysis\n...")
    .addResource("references/formulas.md", "# Common Formulas\n...")
    .source("custom")
    .build();
```

#### Method 2: Create from Markdown

```java theme={null}
// Prepare SKILL.md content
String skillMd = """
---
name: data_analysis
description: Use this skill when analyzing data, calculating statistics, or generating reports
---
# Skill Name
Content...
""";

// Prepare resource files (optional)
Map<String, String> resources = Map.of(
    "references/formulas.md", "# Common Formulas\n...",
    "examples/sample.csv", "name,value\nA,100\nB,200"
);

// Create Skill
AgentSkill skill = SkillUtil.createFrom(skillMd, resources);
```

#### Method 3: Direct Construction

```java theme={null}
AgentSkill skill = new AgentSkill(
    "data_analysis",                    // name
    "Use when analyzing data...",       // description
    "# Data Analysis\n...",             // skillContent
    resources                            // resources (can be null)
);
```

### 2. Integrate with ReActAgent

#### Using SkillBox

```java theme={null}
Toolkit toolkit = new Toolkit();

SkillBox skillBox = new SkillBox(toolkit);
skillBox.registerSkill(skill1);

ReActAgent agent = ReActAgent.builder()
        .name("DataAnalyst")
        .model(model)
        .toolkit(toolkit)
        .skillBox(skillBox)  // Automatically registers skill tools and hook
        .memory(new InMemoryMemory())
        .build();
```

### 3. Use Skills

## Simplified Integration

```java theme={null}
SkillBox skillBox = new SkillBox(new Toolkit());

skillBox.registerSkill(dataSkill);

ReActAgent agent = ReActAgent.builder()
    .name("Assistant")
    .model(model)
    .skillBox(skillBox)
    .build();
```

## Advanced Features

### Feature 1: Progressive Disclosure of Tools

Bind Tools to Skills for on-demand activation. Avoids context pollution from pre-registering all Tools, only passing relevant Tools to LLM when the Skill is actively used.

**Lifecycle of Progressively Disclosed Tools**: Tool lifecycle remains consistent with Skill lifecycle. Once a Skill is activated, Tools remain available throughout the entire session, avoiding the call failures caused by Tool deactivation after each conversation round in the old mechanism.

**Example Code**:

```java theme={null}
Toolkit toolkit = new Toolkit();
SkillBox skillBox = new SkillBox(toolkit);

AgentSkill dataSkill = AgentSkill.builder()
    .name("data_analysis")
    .description("Comprehensive data analysis capabilities")
    .skillContent("# Data Analysis\n...")
    .build();

AgentTool loadDataTool = new AgentTool(...);

skillBox.registration()
    .skill(dataSkill)
    .tool(loadDataTool)
    .apply();

ReActAgent agent = ReActAgent.builder()
    .name("Assistant")
    .model(model)
    .toolkit(toolkit)
    .skillBox(skillBox)
    .build();
```

### Feature 2: Code Execution Capabilities

Provides an isolated code execution environment for Skills, supporting Shell commands, file read/write operations, etc. Uses Builder pattern to compose tools and configuration on demand.

**Basic Usage**:

```java theme={null}
SkillBox skillBox = new SkillBox(toolkit);

// Enable all code execution tools (Shell, read file, write file)
skillBox.codeExecution()
    .withShell()
    .withRead()
    .withWrite()
    .enable();
```

**Configuration Reference**:

* **Tool Selection**: Combine `withShell()`, `withRead()`, `withWrite()` as needed — only explicitly enabled tools are registered
* **`workDir`**: Shared working directory for all tools. Created automatically when specified; if omitted, a temporary directory `agentscope-code-execution-*` is created lazily and cleaned up on JVM exit
* **`uploadDir`**: Upload location for Skill resource files; defaults to `workDir/skills`
* **File Filtering**: Controls which resource files are allowed to upload. Defaults to `scripts/`, `assets/` folders and `.py`, `.js`, `.sh` extensions. Adjust with `includeFolders()`/`includeExtensions()`, or fully customize with `fileFilter()` (the two approaches are mutually exclusive)
* **Custom Shell**: `withShell(customShellTool)` accepts a custom tool whose `baseDir` is automatically overridden with `workDir` while preserving its security policy

**Custom Configuration**:

```java theme={null}
// Specify directory + custom Shell + file filtering
ShellCommandTool customShell = new ShellCommandTool(
    null,  // baseDir will be automatically overridden with workDir
    Set.of("python3", "node", "npm"),
    command -> askUserApproval(command)
);

skillBox.codeExecution()
    .workDir("/data/agent-workspace")              // working directory
    .uploadDir("/data/agent-workspace/my-skills")  // optional, defaults to workDir/skills
    .includeFolders(Set.of("scripts/", "data/"))   // optional, customize upload folders
    .includeExtensions(Set.of(".py", ".json"))      // optional, customize upload extensions
    .withShell(customShell)
    .withRead()
    .withWrite()
    .enable();

// Or use a fully custom file filter (mutually exclusive with includeFolders/includeExtensions)
skillBox.codeExecution()
    .fileFilter(path -> path.endsWith(".py"))  // or SkillFileFilter.acceptAll()
    .withRead()
    .withWrite()
    .enable();
```

### Feature 3: Skill Persistence Storage

**Why is this feature needed?**

Skills need to remain available after application restart, or be shared across different environments. Persistence storage supports:

#### File System Storage

```java theme={null}
AgentSkillRepository repo = new FileSystemSkillRepository(Path.of("./skills"));
repo.save(List.of(skill), false);
AgentSkill loaded = repo.getSkill("data_analysis");
```

#### MySQL Database Storage

```java theme={null}
// Using simple constructor with default database/table names
DataSource dataSource = createDataSource();
MysqlSkillRepository repo = new MysqlSkillRepository(dataSource, true, true);

// Using Builder for custom configuration
MysqlSkillRepository repo = MysqlSkillRepository.builder(dataSource)
        .databaseName("my_database")
        .skillsTableName("my_skills")
        .resourcesTableName("my_resources")
        .createIfNotExist(true)
        .writeable(true)
        .build();

repo.save(List.of(skill), false);
AgentSkill loaded = repo.getSkill("data_analysis");
```

#### Git Repository (Read-Only)

Used to load Skills from a Git repository (read-only). Supports HTTPS and SSH.

**Update mechanism**

* By default, each read triggers a lightweight remote reference check; a pull runs only when the
  remote HEAD changes.
* You can disable auto-sync via the constructor and call `sync()` manually when you want to
  refresh.

```java theme={null}
AgentSkillRepository repo = new GitSkillRepository(
    "https://github.com/your-org/your-skills-repo.git");
AgentSkill skill = repo.getSkill("data-analysis");
List<AgentSkill> allSkills = repo.getAllSkills();

GitSkillRepository manualRepo = new GitSkillRepository(
    "https://github.com/your-org/your-skills-repo.git", false);
manualRepo.sync();
```

If the repository contains a `skills/` subdirectory, it will be used; otherwise the repo root
is used.

#### Classpath Repository (Read-Only)

Used to load pre-packaged Skills from classpath resources. Automatically compatible with standard JARs and Spring Boot Fat JARs.

```java theme={null}
try (ClasspathSkillRepository repository = new ClasspathSkillRepository("skills")) {
    AgentSkill skill = repository.getSkill("data-analysis");
    List<AgentSkill> allSkills = repository.getAllSkills();
} catch //...
```

Resource structure: Place multiple skill subdirectories under `src/main/resources/skills/`, each containing a `SKILL.md`.

> Note: `JarSkillRepositoryAdapter` is deprecated. Use `ClasspathSkillRepository` instead.

#### Nacos Repository (Read-Only)

Pulls or subscribes to Skills from Nacos via a pre-built `AiService` (or Nacos connection config). The Agent fetches Skills from Nacos at runtime in real time, with support for change subscription and automatic awareness. Suitable for online scenarios that need to stay in sync with Nacos.

```java theme={null}
// Create Nacos skill repository with a pre-built AiService
try (NacosSkillRepository repository = new NacosSkillRepository(aiService, "namespace")) {
    AgentSkill skill = repository.getSkill("data-analysis");
    boolean exists = repository.skillExists("data-analysis");
} catch //...
```

> Note: Add the `agentscope-extensions-nacos-skill` dependency.

### Feature 4: Custom Skill Prompts

When SkillBox injects a system prompt into the Agent, it generates one XML `<skill>` entry per registered Skill so the LLM can decide when to load which Skill. Metadata is rendered directly from `AgentSkill.getMetadata()`, and `<skill-id>` is always appended for tool loading.

* **`instruction`**: The prompt header, explaining how to use Skills (how to load them, path conventions, etc.). Defaults to a built-in `load_skill_through_path` usage guide
* **XML metadata rendering**: Scalar metadata becomes a child element, nested maps become nested XML, and lists become repeated `<item>` elements
* **Metadata exposure control**: `skillBox.setExposeAllSkillMetadata(false)` limits the prompt to `name`, `description`, and `skill-id`; the default is to expose all metadata fields

When code execution is enabled, the section appended after `</available_skills>` can also be customized via `.codeExecutionInstruction()`:

* **`codeExecutionInstruction`**: Template for the code execution section; every `%s` placeholder will be replaced with the `uploadDir` absolute path. Passing `null` or blank uses the built-in default.

Passing `null` or a blank string for `instruction` or `codeExecutionInstruction` uses the built-in default.

**Example**:

```java theme={null}
// Customize the instruction header
String customInstruction = """
    ## Available Skills
    When a task matches a skill, load it with load_skill_through_path.
    """;

SkillBox skillBox = new SkillBox(toolkit, customInstruction);

// Optionally expose only core metadata fields in the prompt
skillBox.setExposeAllSkillMetadata(false);

// Customize the code execution section (takes effect when code execution is enabled)
skillBox.codeExecution()
    .workDir("/data/workspace")
    .codeExecutionInstruction("""
        ## Script Execution
        Skills root directory: %s
        Always use absolute paths when running scripts.
        """)
    .withShell()
    .enable();
```

### Performance Optimization Recommendations

1. **Control SKILL.md Size**: Keep under 5k tokens, recommended 1.5-2k tokens
2. **Organize Resources Properly**: Place detailed documentation in references/ rather than SKILL.md
3. **Regularly Clean Versions**: Use `clearSkillOldVersions()` to clean up old versions no longer needed
4. **Avoid Duplicate Registration**: Leverage duplicate registration protection mechanism; same Skill object with multiple Tools won't create duplicate versions

## Related Documentation

* [Claude Agent Skills Official Documentation](https://platform.claude.com/docs/zh-CN/agents-and-tools/agent-skills/overview) - Complete concept and architecture introduction
* [Tool Usage Guide](/v1/en/docs/task/tool) - Tool system usage methods
* [Agent Configuration](/v1/en/docs/quickstart/agent) - Agent configuration and usage
