GitHub user wenjin272 created a discussion: Agent Skills Integration Design
# Agent Skills Integration
### Introduction
Agent Skills are folders of instructions, scripts, and resources that agents
can discover and use to do things more accurately and efficiently.
```markdown
my-skill/
├── SKILL.md # Required: metadata + instructions
├── scripts/ # Optional: executable code
├── references/ # Optional: documentation
└── assets/ # Optional: templates, resources
```
Agent Skills can provide the following capabilities for agents:
* **For skill authors**: Build capabilities once and deploy them across
multiple agent products.
* **For compatible agents**: Support for skills lets end users give agents
new capabilities out of the box.
* **For teams and enterprises**: Capture organizational knowledge in
portable, version-controlled packages.
### How Agent Skill Works
Skills use progressive disclosure to manage context efficiently:
1. **Discovery**: At startup, agents load only the name and description of
each available skill, just enough to know when it might be relevant.
2. **Activation**: When a task matches a skill’s description, the agent reads
the full SKILL.md instructions into context.
3. **Execution**: The agent follows the instructions, optionally loading
referenced files or executing bundled code as needed.

This means that the Agent Framework needs to provide the following capabilities:
* Provide abstraction and management for Agent Skills, supporting the
loading, parsing, and utilization of skills by the Agent.
* Offer built-in tools to support the dynamic loading and execution of skills
by the Agent:
* `load_skill`: Supports the Agent in loading a complete SKILL.md file.
* `execute_shell_command`: Supports the Agent in executing scripts or
commands mentioned in SKILL.md.
* `load_skill_resource`: Supports the Agent in reading other resources
required by the skill.
### User Interface
#### How to provide agent skills
Users can provide agent skills for flink-agents jobs in various ways:
* Place the skills in a file system accessible to the job.
* File systems accessible to the job include:
* minicluster/standalone: The flink process runs locally. Skills can
be placed directly in a specific path on the local file system.
* k8s: The flink process runs within a pod. Users need to use custom
images, pod templates, or pv & pvc mechanisms to embed the skills into the
image or mount them into the pod.
* **Folder Format**
```markdown
opt/
└── skills/
└── skill-1/
└── SKILL.md
└── skill-2/
└── SKILL.md
```
At this point, the **absolute path** of this **directory** must be
specified in the flink-agents job.
```python
env.add_skills_from_paths(["/opt/skills"])
```
* **Zip Format**: Package the aforementioned skills folder into a zip
file; in this case, the **absolute path** to this **zip file** must be
configured.
```python
env.add_skills_from_paths(["/opt/skills.zip"])
```
* Package skills into the job's JAR file.
* Place agent skills in the job's resources directory.
```markdown
flink-agents-job/
└── src/
└── main/
└── java/
└── MyJob.java
└── resources/
└── skills/
└── skill-1/
└── SKILL.md
└── skill-2/
└── SKILL.md
```
Users can specify the **relative path** within the **resources**
**directory** in their assignments.
```python
env.add_skills_from_resources(["skills"])
```
* Similarly, skills can also be packaged as a zip file.
```python
env.add_skills_from_resources(["skills.zip"])
```
* Download skills via URL
* Currently, only supports packaging skills into a zip file and storing
them remotely, such as on oss, s3, etc.
```python
env.add_skills_from_urls(["https://<bucket>.oss-cn-hangzhou.aliyuncs.com/skills.zip"])
```
* Future support may include downloading skill folders from FTP links,
GitHub links, etc.
#### How to declare skills to be used
* **Job Level:** Any Agent and ChatModel are visible in the job
* **AgentExecutionEnvironment:** Users can declare the skills to be used
via the environment.
```python
class AgentsExecutionEnvironment(ABC):
...
def add_skills_from_paths(self, paths: List[str]) ->
"AgentsExecutionEnvironment":
"""Add skills from paths.
Args:
paths: List of paths on filesystem for loading skills.
"""
def add_skills_from_resources(
self, resources: List[str]
) -> "AgentsExecutionEnvironment":
"""Add skills from resources in jar.
Args:
resources: List of resources in the job jar for loading
skills.
"""
def add_skills_from_urls(self, urls: List[str]) ->
"AgentsExecutionEnvironment":
"""Add skills from urls.
Args:
urls: List of urls for loading skills, each url should
represent a zip file
contains one or many skills.
"""
```
```python
agents_env = AgentsExecutionEnvironment.get_execution_environment(
env=env, t_env=t_env
)
agents_env.add_skills_from_paths(["/opt/skills"])
```
* **Configuration**:Users can also configure via Config.
```python
class SkillOptions:
FROM_PATHS = ConfigOption(
key="skills.from.paths",
config_type=list,
default=None,
)
FROM_RESOURCES = ConfigOption(
key="skills.from.resources",
config_type=list,
default=None,
)
FROM_URLS = ConfigOption(
key="skills.from.urls",
config_type=list,
default=None,
)
```
```python
agents_env.get_config().set(SkillOptions.FROM_PATHS,["/opt/skills"])
```
* **Agent Level:** Any ChatModel within the Agent is visible.
* Users declare the skills available to the Agent using the
`@skills`decorator.
```python
class MyAgent(Agent):
@skills
@staticmethod
def my_skills() -> ResourceDescriptor:
# Users must configure at least one
# of the following options: paths, resources, or urls.
# Supports combined configuration
return ResourceDescriptor(
clazz=ResourceName.SKILLS_MANAGER,
paths=["/path/to/skills"],
resources=["skills"]
urls=["https://<bucket>.oss-cn-"
"hangzhou.aliyuncs.com/skills.zip"],
)
```
* **ChatModel Level:**
* Configure the skills available to this Chat Model via `skill_names`;
these must be a subset of the skills declared for the job or agent.
```python
class MyAgent(Agent):
@chat_model_setup
@staticmethod
def my_chat_model() -> ResourceDescriptor:
return ResourceDescriptor(
clazz=ResourceName.ChatModel.OLLAMA_SETUP,
connection="ollama_connection",
model=OLLAMA_CHAT_MODEL,
skill_names=["my_skill_1", "my_skill_2"]
)
```
### Framework Implementation
#### Skill Abstraction
`AgentSkill` is an abstraction of agent skills, containing the following
elements:
* **name**: The name of the skill.
* **description**: A brief description of the skill.
* **instructions**: The specific content or steps of the skill.
* **resources**: Other files used by the skill, such as scripts, templates,
and data files.
```python
class AgentSkill(BaseModel):
"""Representation for agent skill that can be loaded and used by agents.
Attributes
----------
name : str
The name of the skill.
description : str
A brief description of the skill.
instructions : str
Detailed instructions of the skill.
resources : Dict[str, str], optional
Additional resources required by the skill.
"""
name: str
description: str
instructions: str
resources: Dict[str, str] = None
```
#### Skill Manager
`AgentSkillManager` is responsible for loading, parsing, and validating Agent
Skills.
* **Loading**
* Supports loading Agent Skills from the following sources:
* file system
* jar packages
* remote urls
* **Parsing**
* Parses file content to construct AgentSkill objects.
* Supports parsing from zip files.
* **Validation**
* Verifies that the AgentSkill does not contain unsupported commands or
behaviors.
```python
class AgentSkillManager(Resource):
paths: List[str] = Field(default=None)
resources: List[str] = Filed(default=None)
urls: List[str] = Field(default=None)
skills: List[AgentSkill] = Field(default_factory=list)
def load_skills(self) -> None:
"""load and parse skills."""
# load skills from directory
# load skills from jar
# load skills from urls
def get_skills(self) -> List[AgentSkill]:
"""get the registered skills."""
return self.skills
def get_system_prompt(self, names: List[str] | None = None) -> Prompt
"""provide system prompt that instruct llm when and how to
use skills."""
def _load_skills_from_paths(self) -> None:
"""load and parse skills from the paths."""
def _load_skills_from_resources(self) -> None:
"""load and parse skills from jar according to resources."""
def _load_skills_from_urls(self) -> None:
"""fetch and parse skills from the specified URLs."""
def _check_skill(self, skill: AgentSkill) -> None:
"""Check if the skill is supported.
Currently, only shell commands or python scripts within the skill
are supported.
"""
```
#### Built-in Tools
Built-in tools are the utilities required by the Agent to execute skills during
runtime.
* load\_skill:load the entire skill.
```python
def load_skill(manager: AgentSkillManager, name: str) -> str:
"""load the entire skill content."""
```
* execute\_shell\_command:execute shell commands, including running python
scripts, etc.
```python
def execute_shell_command(
command: str,
timeout: int = 300,
**kwargs: Any,
) -> str:
"""Execute given command and return the return code, standard output and
error"""
```
* load\_skill\_resource:read the resource files required for the skill, such
as reference materials, templates, data, etc.
```python
def load_skill_resource(manager: AgentSkillManager, name: str, path: str)
-> str:
"""load the specific resource."""
```
### Future Works
* Support fetching agent skills from mcp server
* Currently, FastMCP offers Skills Provider capabilities:
[https://gofastmcp.com/servers/providers/skills](https://gofastmcp.com/servers/providers/skills).
However, Flink-Agents currently integrates the official SDK. Although FastMCP
(22.8k stars) has surpassed the official SDK (21.6k stars) to become the most
popular MCP framework in the community, it only provides a Python SDK.
* Retrieving agent skills via an MCP server can enable dynamic updates of
agent skills.
GitHub link: https://github.com/apache/flink-agents/discussions/565
----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]