> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/RightNow-AI/openfang/llms.txt
> Use this file to discover all available pages before exploring further.

# Skill Development

> Extend agent capabilities by creating custom tools with Python, WASM, or Node.js

Skills are pluggable tool bundles that extend agent capabilities. A skill packages one or more tools with their implementation, letting agents do things that built-in tools don't cover.

## Overview

A skill consists of:

1. **Manifest** (`skill.toml` or `SKILL.md`) - Declares metadata, runtime, tools, and requirements
2. **Entry Point** - Python script, WASM module, Node.js module, or prompt-only Markdown

<Note>
  OpenFang ships with **60 bundled skills** compiled into the binary and available immediately.
</Note>

## Supported Runtimes

<CardGroup cols={2}>
  <Card title="Python" icon="python">
    **Easiest to write**

    * Uses stdin/stdout JSON protocol
    * Not sandboxed (subprocess with `env_clear()`)
    * Supports Python 3.8+
  </Card>

  <Card title="WASM" icon="shield">
    **Most secure**

    * Fully sandboxed (Wasmtime dual metering)
    * Resource limits enforced
    * Compile from Rust, C, Go, etc.
  </Card>

  <Card title="Node.js" icon="node-js">
    **OpenClaw compatible**

    * JavaScript/TypeScript support
    * Not sandboxed (subprocess)
    * Auto-converts OpenClaw skills
  </Card>

  <Card title="Prompt Only" icon="message">
    **Expert knowledge**

    * Markdown-based
    * Injected into system prompt
    * No code execution
    * 60 bundled skills included
  </Card>
</CardGroup>

## Bundled Skills

OpenFang includes 60 expert knowledge skills compiled into the binary:

| Category           | Skills                                                                                                                                    |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| **DevOps & Infra** | `ci-cd`, `ansible`, `prometheus`, `nginx`, `kubernetes`, `terraform`, `helm`, `docker`, `sysadmin`, `shell-scripting`, `linux-networking` |
| **Cloud**          | `aws`, `gcp`, `azure`                                                                                                                     |
| **Languages**      | `rust-expert`, `python-expert`, `typescript-expert`, `golang-expert`                                                                      |
| **Frontend**       | `react-expert`, `nextjs-expert`, `css-expert`                                                                                             |
| **Databases**      | `postgres-expert`, `redis-expert`, `sqlite-expert`, `mongodb`, `elasticsearch`, `sql-analyst`                                             |
| **APIs & Web**     | `graphql-expert`, `openapi-expert`, `api-tester`, `oauth-expert`                                                                          |
| **AI/ML**          | `ml-engineer`, `llm-finetuning`, `vector-db`, `prompt-engineer`                                                                           |
| **Security**       | `security-audit`, `crypto-expert`, `compliance`                                                                                           |
| **Dev Tools**      | `github`, `git-expert`, `jira`, `linear-tools`, `sentry`, `code-reviewer`, `regex-expert`                                                 |
| **Writing**        | `technical-writer`, `writing-coach`, `email-writer`, `presentation`                                                                       |
| **Data**           | `data-analyst`, `data-pipeline`                                                                                                           |
| **Collaboration**  | `slack-tools`, `notion`, `confluence`, `figma-expert`                                                                                     |
| **Career**         | `interview-prep`, `project-manager`                                                                                                       |
| **Advanced**       | `wasm-expert`, `pdf-reader`, `web-search`                                                                                                 |

## Skill Manifest Format

### Directory Structure

```
my-skill/
  skill.toml          # Manifest (required)
  src/
    main.py           # Entry point
  README.md           # Optional documentation
```

### skill.toml

```toml skill.toml theme={null}
[skill]
name = "web-summarizer"
version = "0.1.0"
description = "Summarizes any web page into bullet points"
author = "openfang-community"
license = "MIT"
tags = ["web", "summarizer", "research"]

[runtime]
type = "python"           # python | wasm | node | builtin
entry = "src/main.py"

[[tools.provided]]
name = "summarize_url"
description = "Fetch a URL and return a concise bullet-point summary"
input_schema = { 
  type = "object", 
  properties = { 
    url = { type = "string", description = "The URL to summarize" } 
  }, 
  required = ["url"] 
}

[[tools.provided]]
name = "extract_links"
description = "Extract all links from a web page"
input_schema = { 
  type = "object", 
  properties = { 
    url = { type = "string" } 
  }, 
  required = ["url"] 
}

[requirements]
tools = ["web_fetch"]
capabilities = ["NetConnect(*)"]
```

## Creating a Python Skill

Python skills communicate via JSON over stdin/stdout.

### Protocol

<Steps>
  <Step title="OpenFang sends JSON to stdin">
    ```json theme={null}
    {
      "tool": "summarize_url",
      "input": {
        "url": "https://example.com"
      },
      "agent_id": "uuid-...",
      "agent_name": "researcher"
    }
    ```
  </Step>

  <Step title="Script processes and writes result to stdout">
    ```json theme={null}
    {
      "result": "- Point one\n- Point two\n- Point three"
    }
    ```

    Or on error:

    ```json theme={null}
    {
      "error": "Failed to fetch URL: connection refused"
    }
    ```
  </Step>
</Steps>

### Example: Web Summarizer

```python src/main.py theme={null}
#!/usr/bin/env python3
"""OpenFang skill: web-summarizer"""
import json
import sys
import urllib.request


def summarize_url(url: str) -> str:
    """Fetch a URL and return a basic summary."""
    req = urllib.request.Request(url, headers={"User-Agent": "OpenFang-Skill/1.0"})
    with urllib.request.urlopen(req, timeout=30) as resp:
        content = resp.read().decode("utf-8", errors="replace")

    # Simple extraction: first 500 chars as summary
    text = content[:500].strip()
    return f"Summary of {url}:\n{text}..."


def extract_links(url: str) -> str:
    """Extract all links from a web page."""
    import re

    req = urllib.request.Request(url, headers={"User-Agent": "OpenFang-Skill/1.0"})
    with urllib.request.urlopen(req, timeout=30) as resp:
        content = resp.read().decode("utf-8", errors="replace")

    links = re.findall(r'href="(https?://[^"]+)"', content)
    unique_links = list(dict.fromkeys(links))
    return "\n".join(unique_links[:50])


def main():
    payload = json.loads(sys.stdin.read())
    tool_name = payload["tool"]
    input_data = payload["input"]

    try:
        if tool_name == "summarize_url":
            result = summarize_url(input_data["url"])
        elif tool_name == "extract_links":
            result = extract_links(input_data["url"])
        else:
            print(json.dumps({"error": f"Unknown tool: {tool_name}"}))
            return

        print(json.dumps({"result": result}))
    except Exception as e:
        print(json.dumps({"error": str(e)}))


if __name__ == "__main__":
    main()
```

### Using the OpenFang Python SDK

For cleaner code, use the Python SDK:

```python theme={null}
#!/usr/bin/env python3
from openfang_sdk import SkillHandler

handler = SkillHandler()

@handler.tool("summarize_url")
def summarize_url(url: str) -> str:
    # Your implementation here
    return "Summary..."

@handler.tool("extract_links")
def extract_links(url: str) -> str:
    # Your implementation here
    return "link1\nlink2"

if __name__ == "__main__":
    handler.run()
```

## Creating a WASM Skill

WASM skills run in a sandboxed Wasmtime environment with enforced resource limits.

### Building a WASM Skill

<Steps>
  <Step title="Write your skill in Rust">
    ```rust src/lib.rs theme={null}
    use std::io::{self, Read};

    #[no_mangle]
    pub extern "C" fn _start() {
        let mut input = String::new();
        io::stdin().read_to_string(&mut input).unwrap();

        let payload: serde_json::Value = serde_json::from_str(&input).unwrap();
        let tool = payload["tool"].as_str().unwrap_or("");
        let input_data = &payload["input"];

        let result = match tool {
            "my_tool" => {
                let param = input_data["param"].as_str().unwrap_or("");
                format!("Processed: {param}")
            }
            _ => format!("Unknown tool: {tool}"),
        };

        println!("{}", serde_json::json!({"result": result}));
    }
    ```
  </Step>

  <Step title="Compile to WASM">
    ```bash theme={null}
    cargo build --target wasm32-wasi --release
    ```
  </Step>

  <Step title="Reference in manifest">
    ```toml skill.toml theme={null}
    [runtime]
    type = "wasm"
    entry = "target/wasm32-wasi/release/my_skill.wasm"
    ```
  </Step>
</Steps>

### Sandbox Limits

The WASM sandbox enforces:

* **Fuel limit** - Maximum computation steps (prevents infinite loops)
* **Memory limit** - Maximum memory allocation
* **Capabilities** - Only capabilities granted to the agent apply

<Note>
  Limits are derived from the agent's `[resources]` section in its manifest.
</Note>

## SKILL.md Format

The SKILL.md format uses YAML frontmatter and Markdown body:

```markdown SKILL.md theme={null}
---
name: rust-expert
description: Expert Rust programming knowledge
---

# Rust Expert

## Key Principles
- Ownership and borrowing rules...
- Lifetime annotations...

## Common Patterns
...
```

<Warning>
  All SKILL.md files pass through an automated **prompt injection scanner** that detects override attempts, data exfiltration patterns, and shell references before inclusion.
</Warning>

## Installing Skills

### From Local Directory

```bash theme={null}
openfang skill install /path/to/my-skill
```

Reads the `skill.toml`, validates the manifest, and copies to `~/.openfang/skills/my-skill/`.

### From FangHub

```bash theme={null}
openfang skill install web-summarizer
```

Downloads from the FangHub marketplace registry.

### From Git Repository

```bash theme={null}
openfang skill install https://github.com/user/openfang-skill-example.git
```

### List Installed Skills

```bash theme={null}
openfang skill list
```

Output:

```
3 skill(s) installed:

NAME                 VERSION    TOOLS    DESCRIPTION
----------------------------------------------------------------------
web-summarizer       0.1.0      2        Summarizes any web page
data-analyzer        0.2.1      3        Statistical analysis tools
code-formatter       1.0.0      1        Format code in 20+ languages
```

### Remove Skills

```bash theme={null}
openfang skill remove web-summarizer
```

## Using Skills in Agents

Reference skills in the agent manifest's `skills` field:

```toml agent.toml theme={null}
name = "my-assistant"
version = "0.1.0"
description = "An assistant with extra skills"
author = "openfang"
module = "builtin:chat"
skills = ["web-summarizer", "data-analyzer"]

[model]
provider = "groq"
model = "llama-3.3-70b-versatile"

[capabilities]
tools = ["file_read", "web_fetch", "summarize_url"]
memory_read = ["*"]
memory_write = ["self.*"]
```

The kernel loads skill tools and prompts at agent spawn time.

## Publishing to FangHub

FangHub is the community skill marketplace for OpenFang.

### Preparing Your Skill

<Steps>
  <Step title="Complete metadata">
    Ensure `skill.toml` has: `name`, `version`, `description`, `author`, `license`, `tags`
  </Step>

  <Step title="Add documentation">
    Include a `README.md` with usage instructions
  </Step>

  <Step title="Test locally">
    ```bash theme={null}
    openfang skill install /path/to/my-skill
    # Spawn an agent and test the skill's tools
    ```
  </Step>
</Steps>

### Searching FangHub

```bash theme={null}
openfang skill search "web scraping"
```

Output:

```
Skills matching "web scraping":

  web-summarizer (42 stars)
    Summarizes any web page into bullet points
    https://fanghub.dev/skills/web-summarizer

  page-scraper (28 stars)
    Extract structured data from web pages
    https://fanghub.dev/skills/page-scraper
```

### Publishing

Publishing to FangHub (coming soon):

```bash theme={null}
openfang skill publish
```

Validates manifest, packages the skill, and uploads to the registry.

## OpenClaw Compatibility

OpenFang can install and run OpenClaw-format skills.

### Automatic Conversion

```bash theme={null}
openfang skill install /path/to/openclaw-skill
```

If the directory contains an OpenClaw-style skill (Node.js package), OpenFang:

1. Detects the OpenClaw format
2. Generates a `skill.toml` from `package.json`
3. Maps tool names to OpenFang conventions
4. Copies the skill to the OpenFang skills directory

### Manual Conversion

If automatic conversion doesn't work, create a `skill.toml` manually:

```toml skill.toml theme={null}
[skill]
name = "my-openclaw-skill"
version = "1.0.0"
description = "Converted from OpenClaw"

[runtime]
type = "node"
entry = "index.js"

[[tools.provided]]
name = "my_tool"
description = "Tool description"
input_schema = { 
  type = "object", 
  properties = { 
    input = { type = "string" } 
  }, 
  required = ["input"] 
}
```

<Note>
  Skills imported via `openfang migrate --from openclaw` are scanned and reported in the migration report with reinstallation instructions.
</Note>

## Best Practices

<CardGroup cols={2}>
  <Card icon="bullseye" title="Keep it Focused">
    One skill should do one thing well
  </Card>

  <Card icon="shield-halved" title="Minimal Requirements">
    Only request the tools and capabilities you actually need
  </Card>

  <Card icon="tag" title="Descriptive Names">
    The LLM reads tool names and descriptions to decide when to use them
  </Card>

  <Card icon="code" title="Clear Schemas">
    Include descriptions for every parameter so the LLM knows what to pass
  </Card>

  <Card icon="bug" title="Handle Errors">
    Always return JSON error objects rather than crashing
  </Card>

  <Card icon="arrow-up" title="Version Carefully">
    Use semantic versioning; breaking changes require major version bumps
  </Card>

  <Card icon="check" title="Test Thoroughly">
    Verify your skill works with different agent templates and providers
  </Card>

  <Card icon="book" title="Document Well">
    Include setup steps, dependencies, and example usage
  </Card>
</CardGroup>

## CLI Commands

```bash theme={null}
# Install a skill (local directory, FangHub name, or git URL)
openfang skill install <source>

# List all installed skills
openfang skill list

# Remove an installed skill
openfang skill remove <name>

# Search FangHub for skills
openfang skill search <query>

# Create a new skill scaffold (interactive)
openfang skill create
```

### Creating a Skill Scaffold

```bash theme={null}
openfang skill create
```

Interactive prompts for:

* Skill name
* Description
* Runtime type (python/node/wasm)

Generates:

```
~/.openfang/skills/my-skill/
  skill.toml        # Pre-filled manifest
  src/
    main.py         # Starter entry point
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Creating Agents" icon="robot" href="/guides/creating-agents">
    Build custom agents that use your skills
  </Card>

  <Card title="API Reference" icon="code" href="/integrations/skills">
    Skill API endpoint documentation
  </Card>
</CardGroup>
