# En

> Skill (Agent Skills)

- Skill: `trpc-group/en` (Agent Skill, multi-file: 39 files)
- Install (CLI): `npx skillmds@latest add trpc-group/en`
- Raw SKILL.md: https://api.skillmd.com/api/skills/trpc-group/en/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: trpc-group (https://skillmd.com/u/trpc-group)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/trpc-group/en

---

# Skill (Agent Skills)

Agent Skills let you package reusable workflows into folders containing a `SKILL.md` specification file along with optional documentation and scripts. During a conversation, the agent first injects low-cost "overview" information, then loads the full body content and documentation only when truly needed, and safely runs scripts in an isolated workspace.

Background references:
- Engineering blog:
  https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills
- Open Skills repository (reference structure):
  https://github.com/anthropics/skills

## Overview

### 🎯 Features

- 🔎 Overview injection (name + description) to guide selection
- 📥 `skill_load` fetches `SKILL.md` body and selected documentation on demand, automatically loading tools defined in the skill
- 📋 `skill_list` lists all available skill names
- 🔧 `skill_list_tools` lists tool names defined in a specified skill's `SKILL.md`
- ⚙️ `skill_select_tools` dynamically selects skill tools (add/replace/clear modes) for token optimization
- 📚 `skill_select_docs` adds/replaces/clears documentation
- 🧾 `skill_list_docs` lists available documentation
- 🏃 `skill_run` executes commands and returns stdout/stderr and output files
- 🗂️ Collects output files with MIME type detection support
- 🧩 Pluggable local or container workspace executors (local by default)
- 🧱 Custom working directory where skill run input files, output files, and skill files can be placed
- 🎯 Dynamic tool loading that automatically provides relevant tools based on skill selection, saving LLM tokens

### Three-Layer Information Model

Agent Skills adopt a three-layer information model that enables on-demand loading while keeping prompts concise:

**1) Initial "Overview" Layer (extremely low cost)**
   - Only injects the `name` and `description` from `SKILL.md` into the system message
   - Lets the model know which skills are available without loading full content

**2) Full Body Layer (loaded on demand)**
   - When a task truly requires a skill, the model calls `skill_load`
   - The framework then injects the complete `SKILL.md` body content for that skill

**3) Documentation/Script Layer (selective + isolated execution) / Tool Invocation**
   - Documentation is included only when explicitly requested
   - Scripts are not inlined into the prompt but executed in an isolated workspace
   - Only execution results and output files are returned, without exposing script source code
   - Parses user-configured available tools

### File Layout

```
skills/
  demo-skill/
    SKILL.md        # YAML (name/description) + Markdown body
    USAGE.md        # optional docs (.md/.txt)
    scripts/build.sh
    reference/      # Reference documentation
    ...
```

Repository and parsing: [trpc_agent_sdk/skills/_repository.py](../../../trpc_agent_sdk/skills/_repository.py)

## Quick Start

### 1) Requirements

- Python3.12
- Model provider API key (OpenAI-compatible)
- Optional Docker (for container executor)

Common environment variables:

```bash
export TRPC_AGENT_API_KEY="your-api-key"
export TRPC_AGENT_BASE_URL="your-base-url"
export TRPC_AGENT_MODEL_NAME="your-model-name"
# Optional: specify the skills directory, supports local paths or URLs (see "URL-based Skills Root")
export SKILLS_ROOT=/path/to/skills
# Optional: override the cache directory for URL-based Skills Root
export SKILLS_CACHE_DIR=/path/to/cache
```

Alternatively, you can use a `.env` file (examples automatically load it via `python-dotenv`):

```bash
# .env file
TRPC_AGENT_API_KEY=your-api-key
TRPC_AGENT_BASE_URL=your-base-url
TRPC_AGENT_MODEL_NAME=your-model-name
SKILLS_ROOT=./skills
# Optional: SKILLS_ROOT can also be a URL, for example:
# SKILLS_ROOT=https://example.com/my-skills.tar.gz
# SKILLS_CACHE_DIR=/custom/cache/path
```

### 2) Enabling Skills in an Agent

Create a skill repository and a workspace executor. If no executor is specified, the local executor is used by default for development convenience.

```python
import os
from trpc_agent_sdk.agents import LlmAgent
from trpc_agent_sdk.models import OpenAIModel
from trpc_agent_sdk.skills import SkillToolSet
from trpc_agent_sdk.skills import create_default_skill_repository
from trpc_agent_sdk.skills.tools import LinkSkillStager
from trpc_agent_sdk.code_executors import create_local_workspace_runtime
from trpc_agent_sdk.code_executors import create_container_workspace_runtime
# Cube is an optional extra (`pip install 'trpc-agent-py[cube]'`); import lazily.
# from trpc_agent_sdk.code_executors.cube import CubeCodeExecutor, CubeCodeExecutorConfig
# from trpc_agent_sdk.code_executors.cube import create_cube_workspace_runtime

# Create workspace runtime (local, container, or cube)
workspace_runtime = create_local_workspace_runtime()
# Or use container: workspace_runtime = create_container_workspace_runtime()
# Or use a remote Cube/E2B sandbox:
#   executor = await CubeCodeExecutor.create(CubeCodeExecutorConfig())
#   workspace_runtime = create_cube_workspace_runtime(executor)

# Create skill repository
repository = create_default_skill_repository("./skills", workspace_runtime=workspace_runtime, use_cached_repository=True)

# Create skill tool set with optional artifact save options
skill_tool_set = SkillToolSet(
    repository=repository,
    skill_stager=LinkSkillStager(),
    # run_tool_kwargs is an optional tool parameter
    run_tool_kwargs={
        "save_as_artifacts": True,  # Whether to save as artifact files
        "omit_inline_content": False,
    }
)

# Create an agent with skills
agent = LlmAgent(
        name="skill_run_agent",
        description="A professional skill run assistant that can use Agent Skills.",
        model=_create_model(),
        instruction=INSTRUCTION,  # Prompt containing skill usage guidance
        tools=[skill_tool_set],
        skill_repository=repository,
    )
```

*Note: Starting after version 1.1.10, skill loading and injection were optimized to support caching skill content and symlink-based staging in the local sandbox, avoiding full directory copies.*

**Prompt example**:

The `INSTRUCTION` should include complete skill usage workflow guidance:

```python
INSTRUCTION = """
You are an AI assistant with access to Agent Skills.

## Complete Skill Workflow

When handling user requests:

1. **Discover** → Call skill_list() to see available skills
2. **Inspect** → Call skill_list_tools(skill_name="...") to preview tools
3. **Load** → Call skill_load(skill_name="...") to load the skill
4. **Optimize** → Call skill_select_tools(...) to select only needed tools (saves tokens)
5. **Document** → Call skill_list_docs(...) and skill_select_docs(...) if more info needed
6. **Execute** → Call skill_run(...) to execute commands or use skill's tools directly

Example Complete Flow:
User: "What's the weather in Beijing?"
→ skill_list() → see "weather-tools"
→ skill_list_tools(skill_name="weather-tools") → see available tools
→ skill_load(skill_name="weather-tools") → load full content
→ skill_select_tools(skill_name="weather-tools", tools=["get_current_weather"]) → optimize
→ get_current_weather(city="Beijing") → execute

Always use environment variables in commands:
- $WORKSPACE_DIR, $SKILLS_DIR, $WORK_DIR, $OUTPUT_DIR, $RUN_DIR, $SKILL_NAME
"""
```

Key points:
- **Automatic tool registration**: The following tools are automatically registered via `SkillToolSet`, requiring no manual wiring:
  - `skill_list`: Lists all available skills
  - `skill_list_tools`: Lists tools of a skill
  - `skill_load`: Loads skill content
  - `skill_select_tools`: Selects specific tools (token optimization)
  - `skill_list_docs`: Lists available documentation
  - `skill_select_docs`: Selects specific documentation
  - `skill_run`: Executes skill commands
- **Intelligent prompt guidance**: Explicitly describe the workflow in the prompt to guide the LLM to call tools in the correct order
- **Token optimization**: Use `skill_select_tools` to load only the needed tools, significantly reducing context size
- **Code location**:
  - Package entry (aggregated exports): [trpc_agent_sdk/skills/tools/__init__.py](../../../trpc_agent_sdk/skills/tools/__init__.py)
  - `skill_run` implementation: [trpc_agent_sdk/skills/tools/_skill_run.py](../../../trpc_agent_sdk/skills/tools/_skill_run.py) (for other tools, see **Declaration location** in each section below)

### 3) Running the Example

Full interactive demo: [examples/skills/run_agent.py](../../../examples/skills/run_agent.py)

The example is organized in a modular structure:
- `agent/agent.py` - Agent creation
- `agent/tools.py` - Skill tool set creation
- `agent/config.py` - Model configuration from environment variables
- `agent/prompts.py` - Agent instruction prompts
- `run_agent.py` - Main entry file

```bash
cd examples/skills

# Set environment variables
export TRPC_AGENT_API_KEY="your-api-key"
export TRPC_AGENT_BASE_URL="your-base-url"
export TRPC_AGENT_MODEL_NAME="your-model-name"
export SKILLS_ROOT="./skills"  # Optional, defaults to ./skills

# Run the example
python3 run_agent.py
```

Or use a `.env` file:

```bash
# Create .env file
cat > .env << EOF
TRPC_AGENT_API_KEY=your-api-key
TRPC_AGENT_BASE_URL=your-base-url
TRPC_AGENT_MODEL_NAME=your-model-name
SKILLS_ROOT=./skills
EOF

# Run (automatically loads .env)
python3 run_agent.py
```

Example skill (excerpt):
[examples/skills/skills/python-math/SKILL.md](../../../examples/skills/skills/python-math/SKILL.md)

Tips:
- Describe the task you want to accomplish; the model will decide whether a skill is needed based on the overview.
- When needed, the model will call `skill_load` to fetch the body/documentation, then call `skill_run` to execute and return output files.

#### Example run output

Using user-file-ops as an example:
```txt
🆔 Session ID: be355f8f...
📝 User:
        I have a text file at /tmp/skillrun-notes.txt.
        Please use the user-file-ops skill to summarize it, you can use command `cp` to copy it to the workspace,
        then mapping it to `work/inputs/user-notes.txt` and writing the summary to `out/user-notes-summary.txt`

🤖 Assistant:
🔧 [Invoke Tool:: skill_load({'skill_name': 'user-file-ops'})]
📊 [Tool Result: {'result': "skill 'user-file-ops' loaded"}]

🔧 [Invoke Tool:: skill_list_docs({'skill_name': 'user-file-ops'})]
📊 [Tool Result: {}]

🔧 [Invoke Tool:: skill_run({'skill': 'user-file-ops', 'command': 'cp /tmp/skillrun-notes.txt work/inputs/user-notes.txt && bash scripts/summarize_file.sh work/inputs/user-notes.txt out/user-notes-summary.txt', 'output_files': ['out/user-notes-summary.txt']})]
📊 [Tool Result: {'stdout': '', 'stderr': '', 'exit_code': 0, 'timed_out': False, 'duration_ms': 0, 'output_files': [{'name': 'out/user-notes-summary.txt', 'content': 'File: work/inputs/user-notes.txt\nLines: 2\nWords: 7\nBytes: 41\n\nFirst 20 non-empty lines:\n     1\thello from skillrun\n     2\tthis is another line\n', 'mime_type': 'text/plain'}], 'artifact_files': []}]
The file `/tmp/skillrun-notes.txt` has been summarized successfully. Here are the details:

### Summary of `user-notes.txt`:
- **Lines**: 2
- **Words**: 7
- **Bytes**: 41

### Preview (First 20 non-empty lines):
```
1. hello from skillrun
2. this is another line
```

The summary has been saved to `out/user-notes-summary.txt`. Let me know if you'd like to perform any further actions!
```

#### Run Directory

Default working directory name: `/tmp/ws_<session_id>-<time>/`, files under the directory:
```txt
├── metadata.json
├── out
│   └── user-notes-summary.txt
├── runs
│   ├── run_20260116T201918.239930
│   ├── run_20260116T201918.322124
│   └── run_20260116T201918.402214
├── skills
│   └── user-file-ops
│       ├── inputs -> ../../work/inputs
│       ├── out -> ../../out
│       ├── scripts
│       │   └── summarize_file.sh
│       ├── SKILL.md
│       └── work -> ../../work
└── work
    └── inputs
        └── user-notes.txt
```
- out: Result output directory
- work: Temporary shared working directory
- runs: Current program run path
- skills: Storage directory for all skills

## Advanced Usage

### Custom Working Directory

By default, a workspace is created in a temporary directory (e.g., `/tmp/ws_<session_id>-<time>/`) when skills are executed. If you need to customize the output directory location, you can do so by setting environment variables.

#### Method 1: Specify in Code

```python
def create_skill_tool_set(workspace_runtime_type: str = "local") -> SkillToolSet:
    """Create a new skill tool set."""
    tool_kwargs = {
        "save_as_artifacts": True,
        "omit_inline_content": False,
    }
    if workspace_runtime_type == "local":
        workspace_runtime_args = {"work_root": "/tmp/ws_abc123"}
    else:
        workspace_runtime_args = {}
    # workspace_runtime = _create_workspace_runtime(workspace_runtime_type="container", **workspace_runtime_args)
    # Create workspace runtime based on the specified type (local/container)
    workspace_runtime = _create_workspace_runtime(workspace_runtime_type=workspace_runtime_type, **workspace_runtime_args)
    skill_paths = _get_skill_paths()
    repository = create_default_skill_repository(skill_paths, workspace_runtime=workspace_runtime)
    return SkillToolSet(repository=repository, run_tool_kwargs=tool_kwargs), repository
```

Specify in the workspace_runtime_args parameter.

The working directory then becomes: `/{custom_dir}/ws_{session_id}_{time}`, for example:

```txt
/tmp/ws_abc123/ws_env_var_demo_1768564372436142924/
├── metadata.json
├── out
│   ├── fibonacci_data.txt
│   └── fibonacci_summary.txt
├── runs
│   ├── run_20260116T195252.438049
│   ├── run_20260116T195252.518753
│   ├── run_20260116T195252.597016
│   ├── run_20260116T195257.562621
│   └── run_20260116T195304.315245
├── skills
│   └── python-math
│       ├── inputs -> ../../work/inputs
│       ├── out -> ../../out
│       ├── scripts
│       │   └── fib.py
│       ├── SKILL.md
│       └── work -> ../../work
└── work
    └── inputs
```

#### Method 2: Specify in the Prompt

```python
output_instruction = f"""

IMPORTANT: When calling skill_run, you MUST pass env={{'OUTPUT_DIR': '{custom_output_dir}'}} parameter
to use the custom output directory. Write all output files to $OUTPUT_DIR (which will be '{custom_output_dir}').
"""
```
You can also use this approach when you expect skill execution commands to pass other environment variables.

### Dynamic Tool Loading

Full example reference: [skills_with_dynamic_tools/run_agent.py](../../../examples/skills_with_dynamic_tools/run_agent.py)

### URL-based Skills Root

`SKILLS_ROOT` supports not only local directory paths but also URL formats. The framework automatically downloads remote archive packages, extracts and caches them locally. Subsequent calls hit the cache directly without re-downloading.

Related implementation: [trpc_agent_sdk/skills/_url_root.py](../../../trpc_agent_sdk/skills/_url_root.py)

#### Supported Input Formats

| Format | Example | Description |
|---|---|---|
| Local path | `/path/to/skills` or `./skills` | Directly uses a local directory (default behavior, no caching involved) |
| `file://` URL | `file:///path/to/skills` | Explicit file URL, only supports `localhost` or empty host |
| `http://` / `https://` URL | `https://example.com/skills.tar.gz` | Automatically downloads, extracts, and caches locally |

Supported archive formats for remote URLs:

| Extension | Format |
|---|---|
| `.zip` | ZIP archive |
| `.tar` | Uncompressed tar archive |
| `.tar.gz` / `.tgz` | gzip-compressed tar archive |
| `SKILL.md` (direct link) | Single bare skill file |

When the format cannot be determined from the extension, the framework reads magic bytes from the file header for automatic identification (ZIP: `PK\x03\x04`; gzip: `\x1f\x8b`).

#### Usage

**Configure via environment variables**:

```bash
# HTTPS + tar.gz archive
export SKILLS_ROOT="https://example.com/my-skills.tar.gz"

# HTTPS + ZIP archive
export SKILLS_ROOT="https://example.com/my-skills.zip"

# Point directly to a single SKILL.md file
export SKILLS_ROOT="https://example.com/SKILL.md"

# Explicit file URL (equivalent to a local path)
export SKILLS_ROOT="file:///home/user/my-skills"
```

**Use directly in code**:

```python
# Directly configure the skill path
skill_path = "https://example.com/skills.tar.gz"
repository = create_default_skill_repository(skill_path, workspace_runtime=workspace_runtime)
```

#### Download Caching Mechanism

When using a URL-based `SKILLS_ROOT` for the first time, the framework automatically performs the following steps:

```txt
1. Download the archive to a temporary directory
   {cache_dir}/tmp-skill-root-XXXXXX/download

2. Extract to a temporary extraction directory
   {cache_dir}/tmp-skill-root-XXXXXX/root/

3. Write a sentinel file (marks extraction as successful)
   {cache_dir}/tmp-skill-root-XXXXXX/root/.ready

4. Atomically rename to the final cache directory (named by SHA-256 hash of the URL)
   {cache_dir}/{sha256_of_url}/

5. Clean up temporary directories
```

On subsequent calls, if the `{cache_dir}/{sha256_of_url}/.ready` file exists, the cached directory is returned directly, skipping download and extraction. If the cache directory exists but the `.ready` file is missing (e.g., a previous download was interrupted), it is automatically cleaned up and re-downloaded.

In concurrent scenarios where multiple processes download the same URL simultaneously, the framework ensures through atomic `rename` operations that only the first process's result is written. Other processes detect the `.ready` file and return immediately.

**Default cache directory locations**:

| Platform | Default Path |
|---|---|
| Linux | `$XDG_CACHE_HOME/trpc-agent-py/skills/` or `~/.cache/trpc-agent-py/skills/` |
| macOS | `~/Library/Caches/trpc-agent-py/skills/` |
| Windows | `%LocalAppData%/trpc-agent-py/skills/` |

Override via environment variable:

```bash
export SKILLS_CACHE_DIR="/custom/cache/path"
```

#### Security Restrictions

To guard against malicious archives (e.g., zip bombs) and oversized downloads, the framework enforces the following hard limits:

| Restriction | Default Value | Description |
|---|---|---|
| Maximum download size per request | 64 MiB | Includes both `Content-Length` pre-check and streaming write verification |
| Maximum individual extracted file size | 64 MiB | ZIP uses dual verification of header declaration and actual read |
| Total size of all extracted files | 256 MiB | Cumulative byte count limit for all entries |

Exceeding any limit raises a `RuntimeError`, and downloaded temporary files are automatically cleaned up.

Additionally, archive path safety is strictly enforced:
- Rejects absolute paths (e.g., `/etc/passwd`)
- Rejects path traversal (e.g., `../../etc/passwd`)
- Rejects Windows drive letters (e.g., `C:foo`)
- Rejects symbolic links and hard link tar entries (prevents sandbox escape)

## SKILL.md File Structure

The `SKILL.md` file uses YAML front matter (metadata) + Markdown body format:

```markdown
---
name: python-math
description: Small Python utilities for math and text files.
---

Overview
Run short Python scripts inside the skill workspace...

Examples
1) Print the first N Fibonacci numbers
   Command: python3 scripts/fib.py 10 > out/fib.txt

Output Files
- out/fib.txt
```

Writing guidelines:
- **Keep it concise**: The `name` and `description` fields should be brief and clear, used for overview display
- **Provide details**: In the body, include when to use, steps/commands, output file paths, etc.
- **Organize scripts**: Place scripts in the `scripts/` directory and reference them in commands

For more examples, see:
https://github.com/anthropics/skills

## Skill Tools Explained

### `skill_list`

**Declaration location**: [trpc_agent_sdk/skills/tools/_skill_list.py](../../../trpc_agent_sdk/skills/tools/_skill_list.py)

**Input parameters**: None

**Return value**:
- An array of all available skill names

**Behavior**:
- Returns a list of all available skill names in the skill repository
- Used for discovering and browsing available skills

**Prompt guidance**:

This tool is automatically called by the LLM. The agent's prompt should include guidance similar to:

```python
INSTRUCTION = """
## Skill Discovery Workflow

When a user asks for a task that might require skills:

1. **First, always check available skills**:
   - Call skill_list() to see what skills are available
   - This shows you all skill names like ["file-tools", "python-math", "weather-tools"]

Example:
User: "Can you help me with weather information?"
Assistant: Let me check what skills are available.
→ Call skill_list()
→ See result: ["file-tools", "python-math", "weather-tools"]
→ Notice "weather-tools" is relevant
"""
```

**Use cases**:
- User asks "What skills are available?"
- When exploring available capabilities
- When unsure which skill to use, list all skills first

### `skill_list_tools`

**Declaration location**: [trpc_agent_sdk/skills/tools/_skill_list_tool.py](../../../trpc_agent_sdk/skills/tools/_skill_list_tool.py)

**Input parameters**:
- `skill_name` (required): Skill name

**Return value**:
- An array of tool names defined in the `Tools:` section of the skill's `SKILL.md`
- Returns an empty array if the skill defines no tools

**Behavior**:
- Returns the list of tools declared in the specified skill's `SKILL.md`
- Used to preview the tools provided by a skill before loading it
- **Note**: Only returns tools explicitly listed in `SKILL.md`, not all tools in the actual code

**Prompt guidance**:

This tool is called by the LLM before loading a skill. The prompt should include:

```python
INSTRUCTION = """
## Skill Inspection Workflow

Before loading ANY skill, you MUST inspect its tools:

2. **Preview skill tools before loading**:
   - Call skill_list_tools(skill_name="skill-name")
   - This shows what tools the skill provides
   - Verify the skill has the tools you need

Example:
Assistant: I found "weather-tools" skill. Let me check what it provides.
→ Call skill_list_tools(skill_name="weather-tools")
→ See result: ["get_current_weather", "get_weather_forecast", "search_city_by_name"]
→ Confirm it has "get_current_weather" which I need
→ Proceed to load the skill

**Why this step matters**:
- Avoids loading unnecessary skills
- Confirms the skill has required capabilities
- Saves tokens by loading only relevant skills
"""
```

**Use cases**:
- Verify a skill provides the required tools before calling `skill_load`
- User asks "What tools does this skill have?"
- When choosing the appropriate skill

**Definition in SKILL.md**:

Tools are declared in the `Tools:` section of the `SKILL.md` file:

```markdown
---
name: weather-tools
description: Weather information query tools
---

Tools:
- get_current_weather
- get_weather_forecast
- search_city_by_name
# comment: this tool is deprecated
# - old_weather_api

Overview
...
```

### `skill_select_tools`

**Declaration location**: [trpc_agent_sdk/skills/tools/_skill_select_tools.py](../../../trpc_agent_sdk/skills/tools/_skill_select_tools.py)

**Input parameters**:
- `skill_name` (required): Skill name
- `tools` (optional): Array of tool names
- `include_all_tools` (optional): Boolean, whether to include all tools
- `mode` (optional): String, operation mode
  - `add`: Add tools to the existing list
  - `replace`: Replace the existing tool list (default)
  - `clear`: Clear all tools

**Return value**:
- `SkillSelectToolsResult` object containing:
  - `selected_tools`: Array of selected tool names
  - `include_all_tools`: Whether all tools are included

**Behavior**:
- Optimizes LLM context: activates only the tools needed for the current conversation
- Updates the `temp:skill:tools:<name>` session key
- When used with `DynamicSkillToolSet`, only selected tools are loaded into the LLM context

**Prompt guidance**:

This tool is called by the LLM after loading a skill to optimize token usage. The prompt should include:

```python
INSTRUCTION = """
## Tool Selection for Token Optimization

After loading a skill, you SHOULD refine tool selection:

4. **Optimize tool selection** (RECOMMENDED):
   - After skill_load(), all tools from SKILL.md are auto-selected
   - If you only need specific tools, call skill_select_tools() to reduce tokens
   - This is especially important for skills with many tools

Example 1: Select specific tools
User: "What's the current weather in Beijing?"
Assistant:
→ skill_load(skill_name="weather-tools")  # Auto-selects all 3 tools
→ skill_select_tools(
    skill_name="weather-tools",
    tools=["get_current_weather"],  # Only need current weather
    mode="replace"
  )
→ Result: Only 1 tool active instead of 3 (saves ~60% tokens)

Example 2: Multi-tool task
User: "Get current weather and 3-day forecast for Shanghai"
Assistant:
→ skill_load(skill_name="weather-tools")
→ skill_select_tools(
    skill_name="weather-tools",
    tools=["get_current_weather", "get_weather_forecast"],
    mode="replace"
  )
→ Result: 2 out of 3 tools active (saves ~30% tokens)

Example 3: Add more tools later
Assistant:
→ skill_select_tools(
    skill_name="weather-tools",
    tools=["search_city_by_name"],  # Need to search city
    mode="add"  # Add to existing selection
  )

**Token Savings**:
- A skill with 10 tools → select 2 → saves ~80% tool definition tokens
- Especially valuable for skills with complex tools
"""
```

**Use cases**:
- Optimize tool selection after `skill_load` to reduce token consumption
- When a task only requires a subset of a skill's tools
- Dynamically adjust available tools during the conversation

**Relationship with `skill_load`**:
- `skill_load` automatically selects all tools defined in `SKILL.md`
- `skill_select_tools` is used for further refinement to achieve token optimization

### `skill_load`

**Declaration location**: [trpc_agent_sdk/skills/tools/_skill_load.py](../../../trpc_agent_sdk/skills/tools/_skill_load.py)

**Input parameters**:
- `skill_name` (required): Skill name
- `docs` (optional): Array of document file names to load
- `include_all_docs` (optional): Boolean, whether to include all documentation

**Return value**:
- A success message string, e.g.: `"skill 'python-math' loaded"`

**Behavior**:
- Writes temporary session keys (per turn):
  - `temp:skill:loaded:<name>` = "1" (marks the skill as loaded)
  - `temp:skill:docs:<name>` = "*" (all documentation) or JSON array (specified document list)
  - `temp:skill:tools:<name>` = JSON array (tool list automatically parsed from `SKILL.md`)
- The request processor injects the `SKILL.md` body content and selected documentation into the system message
- Automatically selects all tools defined in the `Tools:` section of `SKILL.md`

**Prompt guidance**:

This tool is called by the LLM after confirming a skill is needed. The prompt should include:

```python
INSTRUCTION = """
## Skill Loading Workflow

After confirming a skill is appropriate:

3. **Load the skill**:
   - Call skill_load(skill_name="skill-name")
   - This injects the full SKILL.md body content into context
   - Automatically selects all tools defined in the skill's SKILL.md
   - Optionally load specific docs or all docs

Example 1: Load skill without docs
Assistant:
→ skill_load(skill_name="python-math")
→ Result: Full SKILL.md content loaded, all tools auto-selected
→ Can now use the skill's tools or run commands

Example 2: Load skill with specific docs
Assistant:
→ skill_load(
    skill_name="weather-tools",
    docs=["API_REFERENCE.md"]  # Load specific documentation
  )

Example 3: Load skill with all docs
Assistant:
→ skill_load(
    skill_name="data-analysis",
    include_all_docs=True  # Load all available docs
  )

**What happens after loading**:
- SKILL.md body is injected into your context (Overview, Examples, etc.)
- All tools listed in SKILL.md Tools: section are automatically selected
- You can now see detailed usage instructions and examples
- You can call skill_run or use the skill's tools

**Multiple loads**:
- Safe to call multiple times on the same skill
- Subsequent calls can add/replace docs
- Tool selection persists until modified by skill_select_tools
"""
```

**Use cases**:
- Load a skill after confirming the requirement via `skill_list` and `skill_list_tools`
- Need to view detailed usage instructions and examples for a skill
- Preparing to use a skill's tools or execute commands

**Usage notes**:
- Can be safely called multiple times to add or replace documentation
- First load automatically selects all tools; use `skill_select_tools` for further optimization

### `skill_select_docs`

**Declaration location**: [trpc_agent_sdk/skills/tools/_skill_select_docs.py](../../../trpc_agent_sdk/skills/tools/_skill_select_docs.py)

**Input parameters**:
- `skill_name` (required): Skill name
- `docs` (optional): Array of document file names
- `include_all_docs` (optional): Boolean, whether to include all documentation
- `mode` (optional): String, operation mode
  - `add`: Add documents to the existing list
  - `replace`: Replace the existing document list (default)
  - `clear`: Clear all documents

**Return value**:
- `SkillSelectDocsResult` object containing:
  - `selected_docs`: Array of selected document names
  - `include_all_docs`: Whether all documents are included

**Behavior**:
- Updates the `temp:skill:docs:<name>` session key:
  - `*`: Indicates all documents are included
  - JSON array: Indicates an explicitly specified document list
- On the next LLM request, the selected document content is injected into the system message

**Prompt guidance**:

This tool is called by the LLM when additional documentation is needed. The prompt should include:

```python
INSTRUCTION = """
## Documentation Selection

If the SKILL.md body is not sufficient, you can load additional docs:

5. **Select additional documentation** (when needed):
   - Call skill_select_docs() to load reference documentation
   - Use this when you need API details, configuration info, etc.

Example 1: Load specific docs
Assistant: I need more details about the API.
→ skill_select_docs(
    skill_name="weather-tools",
    docs=["API_REFERENCE.md", "CONFIGURATION.md"],
    mode="replace"
  )

Example 2: Load all docs
Assistant: Let me load all available documentation.
→ skill_select_docs(
    skill_name="data-analysis",
    include_all_docs=True
  )

Example 3: Add more docs
Assistant: I need additional reference.
→ skill_select_docs(
    skill_name="weather-tools",
    docs=["TROUBLESHOOTING.md"],
    mode="add"  # Add to existing docs
  )

**When to use**:
- SKILL.md Overview is insufficient
- Need detailed API reference
- Need configuration examples
- Troubleshooting specific issues
"""
```

**Use cases**:
- The `SKILL.md` body content is insufficient to complete the task
- Need to view API reference documentation
- Need configuration examples or troubleshooting guides

### `skill_list_docs`

**Declaration location**: [trpc_agent_sdk/skills/tools/_skill_list_docs.py](../../../trpc_agent_sdk/skills/tools/_skill_list_docs.py)

**Input parameters**:
- `skill_name` (required): Skill name

**Return value**:
- An array of available document file names (e.g., `["API_REFERENCE.md", "CONFIGURATION.md", "TROUBLESHOOTING.md"]`)

**Behavior**:
- Lists all available document files for the specified skill
- Used to view available documentation before calling `skill_select_docs`

**Prompt guidance**:

This tool is called by the LLM when it needs to view available documentation. The prompt should include:

```python
INSTRUCTION = """
## Documentation Discovery

Before selecting docs, you can check what's available:

**Check available docs**:
→ skill_list_docs(skill_name="skill-name")
→ Returns: ["API_REFERENCE.md", "USAGE_EXAMPLES.md", ...]

Example workflow:
User: "I need help configuring the weather API"
Assistant: Let me check what documentation is available.
→ skill_list_docs(skill_name="weather-tools")
→ Result: ["API_REFERENCE.md", "CONFIGURATION.md", "FAQ.md"]
→ I see there's a CONFIGURATION.md, let me load it.
→ skill_select_docs(
    skill_name="weather-tools",
    docs=["CONFIGURATION.md"]
  )

**When to use**:
- Before calling skill_select_docs
- User asks "what documentation is available?"
- Need to find specific reference materials
"""
```

**Use cases**:
- View available documentation before calling `skill_select_docs`
- User asks "What documentation does this skill have?"

**Note**: These session keys are automatically managed by the framework; in the natural conversation flow, you typically do not need to manipulate them directly.

### `skill_run`

**Declaration location**: [trpc_agent_sdk/skills/tools/_skill_run.py](../../../trpc_agent_sdk/skills/tools/_skill_run.py)

**Input parameters**:
- `skill` (required): Skill name
- `command` (required): Shell command to execute
- `output_files` (optional): Array of glob patterns for output files (e.g., `["out/*.txt", "$OUTPUT_DIR/result.json"]`)
- `env` (optional): Dictionary of custom environment variables (e.g., `{"CUSTOM_VAR": "value"}`)
- `timeout` (optional): Timeout in seconds

**Return value**:
- `WorkspaceRunResult` object containing:
  - `stdout`: Standard output
  - `stderr`: Standard error
  - `exit_code`: Exit code
  - `timed_out`: Whether it timed out
  - `duration_ms`: Execution duration in milliseconds
  - `output_files`: Array of collected output files (each containing `name`, `content`, `mime_type`)
  - `artifact_files`: Artifact file information

**Behavior**:
- Executes shell commands in an isolated workspace
- Automatically injects standard environment variables (`$WORKSPACE_DIR`, `$SKILLS_DIR`, `$WORK_DIR`, `$OUTPUT_DIR`, `$RUN_DIR`, `$SKILL_NAME`)
- Collects specified output files and returns them
- Supports custom environment variable overrides

**Prompt guidance**:

This tool is called by the LLM when ready to execute actual commands. The prompt should include detailed usage guidelines:

```python
INSTRUCTION = """
## Skill Execution

After loading a skill, you can execute commands:

6. **Execute skill commands**:
   - Call skill_run(skill="skill-name", command="...", output_files=[...])
   - Commands run in the skill's directory
   - Use environment variables for portable paths

Example 1: Simple command execution
Assistant:
→ skill_run(
    skill="python-math",
    command="python3 scripts/fib.py 10 > $OUTPUT_DIR/fib.txt",
    output_files=["$OUTPUT_DIR/fib.txt"]
  )

Example 2: Multiple output files
Assistant:
→ skill_run(
    skill="data-analysis",
    command="python3 scripts/analyze.py $WORK_DIR/inputs/data.csv",
    output_files=[
        "$OUTPUT_DIR/*.txt",
        "$OUTPUT_DIR/charts/*.png"
    ]
  )

Example 3: Custom environment variables
Assistant:
→ skill_run(
    skill="weather-tools",
    command="python3 scripts/fetch.py",
    env={
        "API_KEY": "user-provided-key",
        "REGION": "asia"
    },
    output_files=["$OUTPUT_DIR/weather.json"]
  )

Example 4: Complex multi-step command
Assistant:
→ skill_run(
    skill="file-tools",
    command='''
        mkdir -p $OUTPUT_DIR/processed &&
        cp $WORK_DIR/inputs/*.txt $OUTPUT_DIR/processed/ &&
        ls -la $OUTPUT_DIR/processed
    ''',
    output_files=["$OUTPUT_DIR/processed/*"]
  )

**Environment Variables Available**:
- $WORKSPACE_DIR: Root workspace directory
- $SKILLS_DIR: Skills directory (contains skill folders)
- $WORK_DIR: Shared working directory
  - $WORK_DIR/inputs: User input files (read-only)
- $OUTPUT_DIR: Output directory (write final results here)
- $RUN_DIR: Current run's directory (unique per execution)
- $SKILL_NAME: Current skill name (e.g., "python-math")

**Best Practices**:
1. Always use environment variables (not hard-coded paths)
2. Write final outputs to $OUTPUT_DIR
3. Read user files from $WORK_DIR/inputs
4. Include output_files parameter to collect results
5. Use descriptive output file names

**Common Patterns**:

# Generate output file

command="python3 scripts/process.py > $OUTPUT_DIR/result.txt"

# Process input and generate output
command="bash scripts/transform.sh $WORK_DIR/inputs/data.csv $OUTPUT_DIR/output.csv"

# Multiple commands
command="mkdir -p $OUTPUT_DIR/reports && python3 scripts/generate.py && ls $OUTPUT_DIR"

# Use SKILL_NAME for context
command="echo 'Processed by $SKILL_NAME' > $OUTPUT_DIR/metadata.txt"

**Error Handling**:
- Check exit_code in the result (0 = success)
- Read stderr for error messages
- Adjust timeout if command takes too long
"""
```

**Use cases**:
- Execute scripts or commands within a skill
- Process files and generate output
- Run data analysis, transformation, and other tasks

**Execution flow**

```txt
LLM calls skill_run(skill="python-math", command="python3 scripts/fib.py 10")
    ↓
1. Create an isolated workspace
   /tmp/ws_<session_id>/
   ├── skills/python-math/     (skill root directory, read-only)
   │   ├── SKILL.md
   │   ├── scripts/
   │   │   └── fib.py
   │   ├── out/    → ../../out  (symbolic link)
   │   └── work/   → ../../work (symbolic link)
   ├── out/                     (output directory)
   ├── work/                    (working directory)
   └── run/                     (run directory)
    ↓
2. Inject environment variables
   WORKSPACE_DIR=/tmp/ws_<session_id>
   SKILLS_DIR=/tmp/ws_<session_id>/skills
   WORK_DIR=/tmp/ws_<session_id>/work
   OUTPUT_DIR=/tmp/ws_<session_id>/out
   RUN_DIR=/tmp/ws_<session_id>/run
   SKILL_NAME=python-math
    ↓
3. Execute command (in skill root directory)
   cd /tmp/ws_<session_id>/skills/python-math
   bash -lc "python3 scripts/fib.py 10"
    ↓
4. Collect output files
   Collect files based on the output_files parameter
   e.g.: out/*.txt → /tmp/ws_<session_id>/out/*.txt
    ↓
5. Return results
   {
     "stdout": "...",
     "stderr": "...",
     "exit_code": 0,
     "output_files": [...]
   }
```

## Runtime Environment

**Interface definition**: [trpc_agent_sdk/code_executors/_base_workspace_runtime.py](../../../trpc_agent_sdk/code_executors/_base_workspace_runtime.py)

**Implementations**:
- **Local executor**: [trpc_agent_sdk/code_executors/local/_local_ws_runtime.py](../../../trpc_agent_sdk/code_executors/local/_local_ws_runtime.py)
  - Executes commands directly on the local system, suitable for development and testing
- **Container executor** (Docker): [trpc_agent_sdk/code_executors/container/_container_ws_runtime.py](../../../trpc_agent_sdk/code_executors/container/_container_ws_runtime.py)
  - Executes in Docker containers, providing better isolation
- **Cube executor** (remote E2B sandbox): [trpc_agent_sdk/code_executors/cube/_runtime.py](../../../trpc_agent_sdk/code_executors/cube/_runtime.py)
  - Executes inside a remote Cube/E2B sandbox; suitable for environments without local Docker, or when strong remote isolation is required
  - Construct via `create_cube_workspace_runtime(executor, workspace_cfg=...)`; see [code_executor.md](code_executor.md#cubeworkspaceruntime) for details
  - Requires the optional `[cube]` extra (`pip install 'trpc-agent-py[cube]'`) and the `E2B_API_URL` / `E2B_API_KEY` / `CUBE_TEMPLATE_ID` environment variables (or equivalent cfg fields)

**Container executor notes**:
- The run base directory is writable; when `$SKILLS_ROOT` is set, it is mounted in read-only mode
- Network access is disabled by default for reproducibility and security

**Cube executor notes**:
- File and directory transfers use a tar-based protocol so directory upload/download stays a single round-trip and preserves symlinks/permissions
- The remote workspace root defaults to `/workspace/cube_agent`; per-execution subtrees follow the `ws_<exec_id>_<suffix>` naming convention and are recreated lazily on every `create_workspace` call (so external sandbox cleanup heals transparently)
- The same Cube sandbox can back both the bare `CubeCodeExecutor` and the workspace runtime; commands share `execute_timeout` from `CubeCodeExecutorConfig`

**Security and resource limits**:
- **W

…(truncated)
