Skip to content

Custom Skills

Create your own skills to extend agent capabilities.

Overview

Custom skills allow you to add new functionality to your agents. Skills are script-based modules that agents can invoke to perform specific tasks.

Skill Structure

A skill consists of two files:

skills/
└── my_skill/
    ├── manifest.toml    # Skill metadata and configuration
    └── run.sh           # Entry point script

manifest.toml

toml
name = "my_skill"
description = "What this skill does"
version = "1.0.0"
run_command = "sh"
entrypoint = "run.sh"
needs_network = false
needs_fs_read = true
needs_fs_write = false
needs_env = false
FieldDescription
nameSkill identifier (lowercase, underscores)
descriptionWhat the skill does (shown to agent)
versionSemantic version
run_commandCommand to run (sh, bash, python)
entrypointScript file to execute
needs_networkRequires network access
needs_fs_readRequires filesystem read
needs_fs_writeRequires filesystem write
needs_envRequires environment variables

run.sh

bash
#!/bin/bash
# Arguments are passed as JSON array via stdin

# Read arguments
read -r args

# Parse first argument
arg1=$(echo "$args" | jq -r '.[0]')

# Do something
result="Processed: $arg1"

# Output is returned to the agent
echo "$result"

Creating a Skill

Method 1: Manual Creation

  1. Create skill directory:

    bash
    mkdir -p ~/.moxxy/agents/default/skills/my_skill
  2. Create manifest:

    bash
    cat > ~/.moxxy/agents/default/skills/my_skill/manifest.toml << 'EOF'
    name = "my_skill"
    description = "My custom skill"
    version = "1.0.0"
    run_command = "bash"
    entrypoint = "run.sh"
    needs_network = false
    needs_fs_read = true
    needs_fs_write = false
    needs_env = false
    EOF
  3. Create script:

    bash
    cat > ~/.moxxy/agents/default/skills/my_skill/run.sh << 'EOF'
    #!/bin/bash
    read -r args
    arg=$(echo "$args" | jq -r '.[0]')
    echo "Hello, $arg!"
    EOF
    
    chmod +x ~/.moxxy/agents/default/skills/my_skill/run.sh
  4. Restart agent:

    bash
    moxxy agent restart default

Method 2: Via Agent

Ask your agent to create the skill:

Create a skill called "file_counter" that counts files in a directory

The agent will use the create_skill skill to generate the code.

Method 3: Install from Repository

Install the skill from https://github.com/user/moxxy-skills/tree/main/weather

Skill Types

Shell Scripts (Bash)

bash
#!/bin/bash
read -r args

# Parse arguments
file=$(echo "$args" | jq -r '.[0]')

# Process
if [ -f "$file" ]; then
    wc -l < "$file"
else
    echo "Error: File not found"
fi

Python Scripts

toml
# manifest.toml
run_command = "python"
entrypoint = "run.py"
python
# run.py
import sys
import json

# Read arguments from stdin
args = json.loads(sys.stdin.read())

# Process
result = f"Received: {args[0]}"

# Output
print(result)

Complex Skills

For complex skills, you can include multiple files:

skills/
└── api_client/
    ├── manifest.toml
    ├── run.sh
    ├── lib.py          # Helper library
    └── config.json     # Configuration

Input/Output

Input

Arguments are passed as a JSON array via stdin:

json
["arg1", "arg2", "arg3"]

For MCP skills, an object is passed:

json
{"param1": "value1", "param2": "value2"}

Output

Whatever the script prints to stdout is returned to the agent:

bash
# Simple output
echo "Task completed successfully"

# JSON output (for structured data)
echo '{"status": "success", "count": 42}'

Error Handling

Print errors to stderr for proper handling:

bash
if [ error_condition ]; then
    echo "Error: Something went wrong" >&2
    exit 1
fi

Examples

File Processor Skill

toml
# manifest.toml
name = "file_processor"
description = "Process a file and extract information"
version = "1.0.0"
run_command = "bash"
entrypoint = "run.sh"
needs_fs_read = true
needs_fs_write = false
bash
#!/bin/bash
# run.sh

read -r args
file=$(echo "$args" | jq -r '.[0]')
operation=$(echo "$args" | jq -r '.[1] // "info"')

case "$operation" in
    "info")
        echo "File: $file"
        echo "Size: $(stat -f%z "$file" 2>/dev/null || stat -c%s "$file") bytes"
        echo "Lines: $(wc -l < "$file")"
        ;;
    "head")
        head -n 10 "$file"
        ;;
    "tail")
        tail -n 10 "$file"
        ;;
    *)
        echo "Unknown operation: $operation" >&2
        exit 1
        ;;
esac

API Client Skill

toml
# manifest.toml
name = "api_client"
description = "Make HTTP requests to external APIs"
version = "1.0.0"
run_command = "bash"
entrypoint = "run.sh"
needs_network = true
bash
#!/bin/bash
# run.sh

read -r args
method=$(echo "$args" | jq -r '.[0]')
url=$(echo "$args" | jq -r '.[1]')
data=$(echo "$args" | jq -r '.[2] // empty')

case "$method" in
    "GET")
        curl -s "$url"
        ;;
    "POST")
        curl -s -X POST -H "Content-Type: application/json" -d "$data" "$url"
        ;;
    *)
        echo "Unsupported method: $method" >&2
        exit 1
        ;;
esac

Database Query Skill

toml
# manifest.toml
name = "db_query"
description = "Execute SQL queries against a database"
version = "1.0.0"
run_command = "bash"
entrypoint = "run.sh"
needs_fs_read = true
bash
#!/bin/bash
# run.sh

read -r args
query=$(echo "$args" | jq -r '.[0]')
db_path=$(echo "$args" | jq -r '.[1] // "$HOME/.moxxy/data.db"')

sqlite3 -json "$db_path" "$query"

Best Practices

Naming

  • Use lowercase with underscores: file_processor
  • Be descriptive: csv_analyzer, not process
  • Use verbs: send_email, fetch_data

Documentation

Include usage examples in the skill:

bash
#!/bin/bash
# Skill: file_processor
# Description: Process files with various operations
#
# Usage:
#   <invoke name="file_processor">["path/to/file", "operation"]</invoke>
#
# Operations:
#   - info: Show file information
#   - head: Show first 10 lines
#   - tail: Show last 10 lines

Error Handling

bash
#!/bin/bash
set -e

read -r args

# Validate input
if [ -z "$args" ]; then
    echo "Error: No arguments provided" >&2
    exit 1
fi

# Parse safely
file=$(echo "$args" | jq -r '.[0] // empty')

if [ -z "$file" ]; then
    echo "Error: File path required" >&2
    exit 1
fi

# Check file exists
if [ ! -f "$file" ]; then
    echo "Error: File not found: $file" >&2
    exit 1
fi

# Process...

Security

  1. Validate inputs - Never trust user input
  2. Sanitize paths - Prevent directory traversal
  3. Limit permissions - Request minimal capabilities
  4. Use WASM - For untrusted operations

Testing Skills

Manual Testing

bash
# Test the skill directly
echo '["test_input"]' | ~/.moxxy/agents/default/skills/my_skill/run.sh

Via Agent

Test the my_skill skill with the argument "hello"

Via API

bash
curl -X POST http://localhost:17890/api/agents/default/skills/my_skill/invoke \
  -H "Content-Type: application/json" \
  -d '{"args": ["test_input"]}'

Distributing Skills

GitHub Repository

Structure a repository for sharing:

moxxy-skills/
├── skills/
│   ├── weather/
│   │   ├── manifest.toml
│   │   └── run.sh
│   ├── translate/
│   │   ├── manifest.toml
│   │   └── run.py
│   └── ...
└── README.md

Users can install with:

Install the skill from https://github.com/user/moxxy-skills/tree/main/skills/weather

Skill Registry (Future)

A centralized skill registry is planned for easier discovery and installation.

Open source · Self-hosted · Data sovereign