Skills

qianmoQqianmoQ· 更新于 2026-10-08· 阅读 23 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

Overview

A Skill is a self-contained package of instructions, and optionally scripts and reference files, that teaches the agent how to perform a specialized task. A skill is just a directory containing a SKILL.md file. Flink Agents discovers the skills you declare, lets the agent decide which one is relevant to the current request, and loads its full instructions only when needed.

Skills follow a progressive disclosure model, so that providing the agent with many capabilities does not bloat every request:

  1. Discovery — at startup, only each skill’s name and description are injected into the system prompt (a few dozen tokens per skill), so the agent knows what is available.
  2. Activation — when the agent judges a skill relevant, it calls the built-in load_skill tool to read the full SKILL.md instructions into the context.
  3. Execution — the agent follows the loaded instructions, running any bundled scripts or shell commands through the built-in bash tool, and reading additional reference files only on demand.

Skills are a good fit when a capability is best described as a procedure (a runbook the agent follows) rather than a single function call. For a single, well-typed operation, prefer a tool instead.

Skill Format

A skill is a directory whose name matches the skill, containing a SKILL.md file with YAML frontmatter and a Markdown body:

---
name: math-calculator
description: Calculate mathematical expressions using shell commands. Use when the user asks to perform arithmetic like addition, subtraction, multiplication, division, or powers.
license: Apache-2.0
compatibility: Requires bash with bc (basic calculator)
---

# Math Calculator Skill

## When to Use
Use this skill whenever the user asks to evaluate a numeric expression.

## Method
Evaluate expressions with the `bc` calculator:

```bash
echo "(2 + 3) * 4" | bc
# Output: 20
```

Frontmatter fields:

FieldRequiredDescription
nameYesSkill identifier. 1–64 characters, lowercase letters, numbers and hyphens only (no leading/trailing hyphen). Must match the value referenced in the chat model’s skills list.
descriptionYes1–1024 characters. Loaded at discovery time — write it so the agent can decide when to use the skill. State both what it does and when to use it.
licenseNoLicense of the skill.
compatibilityNoFree-text note on runtime requirements (e.g. required commands), up to 500 characters.

The Markdown body is the full instruction set loaded on activation. It may reference bundled files using paths relative to the skill directory (for example python scripts/gen_joke.py); those scripts and reference files are loaded only when the agent actually needs them.

A skill source is a directory holding one or more such skill subdirectories (or a .zip of that layout):

skills/
├── math-calculator/
│   └── SKILL.md
└── joke-generator/
    ├── SKILL.md
    └── scripts/
        └── gen_joke.py

Declare Skills in an Agent

Declare where to load skills from with the @skills/@Skills decorator/annotation. The method returns a Skills resource built with one of its factory methods.

Python

from flink_agents.api.agents.agent import Agent
from flink_agents.api.decorators import skills
from flink_agents.api.skills import Skills

class MathAgent(Agent):

    @skills
    @staticmethod
    def my_skills() -> Skills:
        # Load all skill subdirectories under a local directory.
        return Skills.from_local_dir("/path/to/skills")

Java

import org.apache.flink.agents.api.agents.Agent;
// The @Skills annotation and the Skills resource share a simple name but live
// in different packages, so fully-qualify the annotation when importing the class.
import org.apache.flink.agents.api.skills.Skills;

public class MathAgent extends Agent {

    @org.apache.flink.agents.api.annotation.Skills
    public static Skills mySkills() {
        // Load all skill subdirectories from a classpath resource (packaged in the jar).
        return Skills.fromClasspath("skills");
    }
}

Key points:

  • Use the decorator/annotation to declare a skill source.

    • In Python, use @skills.
    • In Java, use @Skills.
  • Declare more than one @skills/@Skills method on the same agent to combine sources; the runtime merges them and de-duplicates identical entries.

  • Declaring a skill source only makes the skills available. A skill is exposed to a chat model only when that model lists it in its skills (see Enable Skills on a Chat Model).

Skill Sources

Each factory method creates a source with a different scheme:

Factory method (Python / Java)SchemeDescription
Skills.from_local_dir(*paths) / Skills.fromLocalDir(String...)localOne or more local directories, or .zip files, holding skill subdirectories. The path must be resolvable on the Flink TaskManager that runs the agent.
Skills.from_url(*urls) / Skills.fromUrl(String...)urlOne or more http(s) URLs, each pointing to a .zip whose top level holds the skill subdirectories.
Skills.from_package(*pairs)packagePython only. One or more (package, resource) tuples locating skills inside an installed Python package.
Skills.fromClasspath(String...)classpathJava only. One or more classpath resource paths (e.g. under src/main/resources/skills). When packaged into a jar, the resource is materialized to a temp directory at runtime.

The package scheme is Python-only and the classpath scheme is Java-only. A plan written in one language using the other language’s scheme deserializes fine, but fails fast at load time. Use local or url for cross-language skill sources.

Enable Skills on a Chat Model

A declared skill becomes usable only when a chat model opts in by listing it in skills. When skills is set, the framework automatically:

  • injects the discovery prompt (the names and descriptions of the listed skills) into the system messages, and
  • adds the two built-in tools the agent needs — load_skill (to read a skill’s full instructions) and bash (to run its commands and scripts).

Python

@chat_model_setup
@staticmethod
def math_model() -> ResourceDescriptor:
    return ResourceDescriptor(
        clazz=ResourceName.ChatModel.OLLAMA_SETUP,
        connection="ollama_server",
        model="qwen3.5:9b",
        prompt="system_prompt",
        # Expose declared skills to this model by name.
        skills=["math-calculator"],
        # Whitelist the shell commands the bash tool is allowed to run.
        allowed_commands=["echo", "bc"],
    )

Java

@ChatModelSetup
public static ResourceDescriptor mathModel() {
    return ResourceDescriptor.Builder.newBuilder(ResourceName.ChatModel.OLLAMA_SETUP)
            .addInitialArgument("connection", "ollamaChatModelConnection")
            .addInitialArgument("model", "qwen3.5:9b")
            .addInitialArgument("prompt", "systemPrompt")
            // Expose declared skills to this model by name.
            .addInitialArgument("skills", List.of("math-calculator"))
            // Whitelist the shell commands the bash tool is allowed to run.
            .addInitialArgument("allowed_commands", List.of("echo", "bc"))
            .build();
}

Key points:

  • skills lists the skill names (matching the name field in each SKILL.md) the agent may use.
  • allowed_commands is a whitelist of shell command names the built-in bash tool may execute. Any command not on the list is rejected, so keep it as narrow as the skills require (for example echo and bc for arithmetic).
  • The bash tool rejects redirects to files by default. File-descriptor duplication and closure, such as 2>&1 and 2>&-, remain available.
  • Assignments to environment variables that can change command resolution or executable loading, including PATH, BASH_ENV, ENV, SHELLOPTS, CDPATH, LD_*, and DYLD_*, are rejected. The command allowlist is a validation boundary, not a general-purpose operating-system sandbox; do not allow shells, privilege wrappers, or other commands that can launch arbitrary executables.
  • The load_skill and bash tools are added automatically — you do not declare them in tools. They are added alongside any tools you do declare.
  • Make sure the system prompt instructs the agent to load the relevant skill before acting, for example: “You must load the skill first and strictly follow its instructions.” Without this nudge, smaller models may answer directly instead of consulting the skill.

Skills work with both the Workflow Agent (configure the chat model via @chat_model_setup/@ChatModelSetup as above) and the ReAct Agent (set skills and allowed_commands on the ReActAgent’s chat model descriptor, and register the Skills resource on the execution environment with add_resource(..., ResourceType.SKILLS, ...)).

How Skills Work

Once enabled, a request flows through the three progressive-disclosure stages:

  1. Discovery. The discovery prompt lists each available skill’s name and description and explains how to load one. This is the only skill content the agent sees by default:

    ## Available Skills
    <available_skills>
    <skill>
    <name>math-calculator</name>
    <description>Calculate mathematical expressions using shell commands. Use when ...</description>
    </skill>
    </available_skills>
  2. Activation. When the agent decides a skill applies, it calls load_skill(name="math-calculator"). The framework returns the full SKILL.md body, including the skill’s base directory and the absolute paths of its bundled resources.

  3. Execution. Following the loaded instructions, the agent invokes bash to run commands (e.g. echo "(2 + 3) * 4" | bc) or bundled scripts (e.g. python scripts/gen_joke.py), and loads additional reference files only when an instruction points to them.

This keeps each request lean — a skill the agent never activates costs only its one-line description.

评论

登录后参与评论

正在加载评论…