Skip to content
AgentEnv Framework
AgentsSkills

Skills

Write a skill once, use on any agent

Skills follow the Agent Skills specification: a folder with a SKILL.md whose front matter gives the skill's name and description. Any skill can be added to any agent that implements the skill-config extension, and how the agent installs and uses it is up to the agent. This page gives ClaudiusRLMAgent one.

Write a skill

A skill is a directory named after the skill, with its SKILL.md at the top:

skills/email-etiquette/SKILL.md
---
name: email-etiquette
description: How replies from this inbox are written. Use before sending any email.
---

# Email etiquette

- Greet the recipient by first name.
- Say in one line which request you are answering.
- Sign off with "Best, the Finance team".

The name is lowercase letters, digits and hyphens. It names the skill everywhere: on the agent, on its card and in the store.

Accept skills in your agent

Installing a skill is up to the agent, because only the agent knows where its runtime reads skills from. A skill arrives in one of two forms: inline, as the text of its SKILL.md, or as a bundle, with a download grant for each of its files. ClaudiusRLMAgent writes either one to /app/skills and puts every installed skill in Claude's system prompt, on sub-calls too:

claudius/agent.py (additions)
from pathlib import Path

from agentenv_protocol.a2a_agent import (
    SKILL_CONFIG_V1,
    BundleSkillRequest,
    InlineSkillRequest,
    download,
    extension,
)

SKILLS = Path("/app/skills")


class ClaudiusRLMAgent(AgentEnvAgent):
    async def run(self, request: TaskRequest[ClaudiusRLMConfig]) -> TaskResult:
        skills = [(SKILLS / skill["name"] / "SKILL.md").read_text() for skill in request.skills]
        system = "\n\n".join([request.config.system_prompt, *skills])
        ...  # solve() sends system=system on every call to Claude

    @extension(SKILL_CONFIG_V1.add.inline)
    async def add_inline_skill(self, request: InlineSkillRequest):
        path = SKILLS / request.name / "SKILL.md"
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(request.skill_md)
        return {"name": request.name}

    @extension(SKILL_CONFIG_V1.add.bundle)
    async def add_bundle_skill(self, request: BundleSkillRequest):
        for file in request.skill_bundle.files:
            await download(file.object, SKILLS / request.name / file.path)
        return {"name": request.name}

Binding the two handlers turns on skill-config. The SDK does the rest: it refuses a second skill with the same name, lists installed skills at GET /ext/skill-config, adds each one to the agent card, and passes them to every later task as request.skills.

The change makes a new version of the agent. Register and deploy it the way Deploying your agent did:

Terminal
agent-env a2a-agent put --id claudius --dockerfile claudius/Dockerfile --skip-validation
agent-env a2a-agent deploy --id claudius
Output (trimmed)
Created artifact: id=a2a-agent-claudius version=2
Created A2A agent: id=claudius version=2 image=a2a-agent-claudius:2
...
Deployed!
Instance ID: claudius-j5rwex20
A2A URL: http://localhost:43011

Add a skill to a running agent

agent-env a2a-agent add-skill installs a skill on a deployed instance. With --skill-md-path, it sends the file inline:

Terminal
agent-env a2a-agent add-skill --instance-id claudius-j5rwex20 \
  --skill-md-path skills/email-etiquette/SKILL.md
Output
Deployed agent: claudius v2 @ http://localhost:43011
Registering inline skill from skills/email-etiquette/SKILL.md (name=email-etiquette)...
Registered: {'name': 'email-etiquette'}

The agent now lists it:

Terminal
curl -sS http://localhost:43011/ext/skill-config
Output
{"skills":{"email-etiquette":{"description":"How replies from this inbox are written. Use before sending any email."}}}

Its card lists it too, under skills, with the id skill-email-etiquette and the tag skill, so anything that reads the card sees what the agent can do.

Store a skill

A skill you reuse across tasks belongs in the store, as a versioned artifact like any other. Its id must match the name in its front matter:

Terminal
agent-env artifact skill put --id email-etiquette --skill-dir skills/email-etiquette
Output (start)
Uploading SkillArtifact bundle (1 file(s))...
Created SkillArtifact: id=email-etiquette version=1 spec_version=0.1 skill_files_id=email-etiquette__files skill_s3_url=file:///root/.local/state/agent-env/object_store/artifacts/skill/email-etiquette/1

The put checks the front matter, stores every file in the directory, and prints the skill it stored. agent-env a2a-agent add-skill --skill-artifact-id email-etiquette then installs the stored skill on an instance, as a bundle.

Skills in a task

In a task, a skill reaches the agent in one of two places. deploy_agent takes a skills list and installs each one right after the deploy, inline as skill_md:

A deploy_agent step with a skill
{"id": "agent", "type": "deploy_agent", "env_ids": ["email"], "a2a_agent_id": "claudius",
 "agent_name": "assistant",
 "skills": [{"name": "email-etiquette",
             "description": "How replies from this inbox are written. Use before sending any email.",
             "skill_md": "---\nname: email-etiquette\n..."}]}

An add_skills step installs skills on an agent that is already deployed, by agent_name. Each entry is a stored skill, by skill_artifact_id and an optional skill_artifact_version, or an inline one, by name, description and body, which the step turns into a SKILL.md:

An add_skills step
{"id": "etiquette", "type": "add_skills", "agent_name": "assistant",
 "skills": [{"skill_artifact_id": "email-etiquette", "skill_artifact_version": 1}]}

add_skills also writes skills of its own: for each CLI in cli_artifact_ids, a skill that says where the CLI is installed and how to discover its subcommands, and for each universe in file_artifact_universe_ids, one that says where its files were loaded.

Last updated on

Ask a question · Report an issue

On this page