> ## 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.

# Skills

> Extend agent capabilities with pluggable tool bundles

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

## Overview

A skill consists of:

<CardGroup cols={2}>
  <Card title="Manifest" icon="file-code">
    `skill.toml` or `SKILL.md` that declares metadata, runtime, tools, and requirements
  </Card>

  <Card title="Entry Point" icon="play">
    Python script, WASM module, Node.js module, or prompt-only Markdown
  </Card>
</CardGroup>

Skills are installed to `~/.openfang/skills/` and made available to agents through the skill registry. OpenFang ships with **60 bundled skills** compiled into the binary and available immediately.

## Supported Runtimes

| Runtime       | Language              | Sandboxed                          | Notes                                                            |
| ------------- | --------------------- | ---------------------------------- | ---------------------------------------------------------------- |
| `python`      | Python 3.8+           | No (subprocess with `env_clear()`) | Easiest to write. Uses stdin/stdout JSON protocol.               |
| `wasm`        | Rust, C, Go, etc.     | Yes (Wasmtime dual metering)       | Fully sandboxed. Best for security-sensitive tools.              |
| `node`        | JavaScript/TypeScript | No (subprocess)                    | OpenClaw compatibility.                                          |
| `prompt_only` | Markdown              | N/A                                | Expert knowledge injected into system prompt. No code execution. |
| `builtin`     | Rust                  | N/A                                | Compiled into the binary. For core tools only.                   |

## 60 Bundled Skills

OpenFang includes 60 expert knowledge skills compiled into the binary:

<CardGroup cols={4}>
  <Card title="DevOps & Infra" icon="server">
    ci-cd, ansible, prometheus, nginx, kubernetes, terraform, helm, docker, sysadmin, shell-scripting, linux-networking
  </Card>

  <Card title="Cloud" icon="cloud">
    aws, gcp, azure
  </Card>

  <Card title="Languages" icon="code">
    rust-expert, python-expert, typescript-expert, golang-expert
  </Card>

  <Card title="Frontend" icon="browser">
    react-expert, nextjs-expert, css-expert
  </Card>

  <Card title="Databases" icon="database">
    postgres-expert, redis-expert, sqlite-expert, mongodb, elasticsearch, sql-analyst
  </Card>

  <Card title="APIs & Web" icon="globe">
    graphql-expert, openapi-expert, api-tester, oauth-expert
  </Card>

  <Card title="AI/ML" icon="brain">
    ml-engineer, llm-finetuning, vector-db, prompt-engineer
  </Card>

  <Card title="Security" icon="shield">
    security-audit, crypto-expert, compliance
  </Card>

  <Card title="Dev Tools" icon="wrench">
    github, git-expert, jira, linear-tools, sentry, code-reviewer, regex-expert
  </Card>

  <Card title="Writing" icon="pen">
    technical-writer, writing-coach, email-writer, presentation
  </Card>

  <Card title="Data" icon="chart-line">
    data-analyst, data-pipeline
  </Card>

  <Card title="Collaboration" icon="users">
    slack-tools, notion, confluence, figma-expert
  </Card>

  <Card title="Career" icon="briefcase">
    interview-prep, project-manager
  </Card>

  <Card title="Advanced" icon="gears">
    wasm-expert, pdf-reader, web-search
  </Card>
</CardGroup>

These are `prompt_only` skills using the SKILL.md format — expert knowledge that gets injected into the agent's system prompt.

## SKILL.md Format

The SKILL.md format (also used by OpenClaw) uses YAML frontmatter and a Markdown body:

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

# Rust Expert

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

## Common Patterns
...
```

<Note>
  SKILL.md files are automatically parsed and converted to `prompt_only` skills. All SKILL.md files pass through an automated **prompt injection scanner** that detects override attempts, data exfiltration patterns, and shell references before inclusion.
</Note>

## Skill Format

### Directory Structure

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

### Manifest (skill.toml)

```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"
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(*)"]
```

### Manifest Sections

<Accordion title="[skill] — Metadata">
  | Field         | Type   | Required | Description                                        |
  | ------------- | ------ | -------- | -------------------------------------------------- |
  | `name`        | string | Yes      | Unique skill name (used as install directory name) |
  | `version`     | string | No       | Semantic version (default: `"0.1.0"`)              |
  | `description` | string | No       | Human-readable description                         |
  | `author`      | string | No       | Author name or organization                        |
  | `license`     | string | No       | License identifier (e.g., `"MIT"`, `"Apache-2.0"`) |
  | `tags`        | array  | No       | Tags for discovery on FangHub                      |
</Accordion>

<Accordion title="[runtime] — Execution Configuration">
  | Field   | Type   | Required | Description                                    |
  | ------- | ------ | -------- | ---------------------------------------------- |
  | `type`  | string | Yes      | `"python"`, `"wasm"`, `"node"`, or `"builtin"` |
  | `entry` | string | Yes      | Relative path to the entry point file          |
</Accordion>

<Accordion title="[[tools.provided]] — Tool Definitions">
  Each entry defines one tool that the skill provides:

  | Field          | Type   | Required | Description                                      |
  | -------------- | ------ | -------- | ------------------------------------------------ |
  | `name`         | string | Yes      | Tool name (must be unique across all tools)      |
  | `description`  | string | Yes      | Description shown to the LLM                     |
  | `input_schema` | object | Yes      | JSON Schema defining the tool's input parameters |
</Accordion>

<Accordion title="[requirements] — Host Requirements">
  | Field          | Type  | Description                                         |
  | -------------- | ----- | --------------------------------------------------- |
  | `tools`        | array | Built-in tools this skill needs the host to provide |
  | `capabilities` | array | Capability strings the agent must have              |
</Accordion>

## Python Skills

Python skills are the simplest to write. They run as subprocesses and 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 to stdout">
    Success:

    ```json theme={null}
    {
      "result": "- Point one\n- Point two\n- Point three"
    }
    ```

    Error:

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

### Example: Web Summarizer

```python 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 more advanced skills, 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()
```

## WASM Skills

WASM skills run inside a sandboxed Wasmtime environment. They are ideal for security-sensitive operations.

### Building a WASM Skill

<Steps>
  <Step title="Write your skill in Rust">
    ```rust theme={null}
    // src/lib.rs
    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 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 the capabilities granted to the agent apply

These are derived from the agent's `[resources]` section in its manifest.

## Installing Skills

### From a 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 a Git Repository

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

### Listing 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 into bullet points
data-analyzer        0.2.1      3        Statistical analysis tools
code-formatter       1.0.0      1        Format code in 20+ languages
```

### Removing Skills

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

## Using Skills in Agents

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

```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, merging them with the agent's base capabilities.

## Publishing to FangHub

FangHub is the community skill marketplace for OpenFang.

### Preparing Your Skill

<Steps>
  <Step title="Complete metadata">
    Ensure your `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 with the skill's tools and test them
    ```
  </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 will be available via:

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

This validates the manifest, packages the skill, and uploads it to the FangHub registry.

## CLI Commands

### Full Skill Command Reference

```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
```

This interactive command prompts for:

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

It generates:

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

The generated entry point includes a working template.

## OpenClaw Compatibility

OpenFang can install and run OpenClaw-format skills. The skill installer auto-detects OpenClaw skills (by looking for `package.json` + `index.ts`/`index.js`) and converts them.

### Automatic Conversion

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

If the directory contains an OpenClaw-style skill, OpenFang:

<Steps>
  <Step title="Detect format">
    Identifies OpenClaw format by presence of Node.js package files
  </Step>

  <Step title="Generate manifest">
    Creates `skill.toml` from `package.json`
  </Step>

  <Step title="Map tool names">
    Converts tool names to OpenFang conventions
  </Step>

  <Step title="Install">
    Copies skill to OpenFang skills directory
  </Step>
</Steps>

### Manual Conversion

If automatic conversion does not work, create a `skill.toml` manually:

```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"] }
```

Place alongside the existing `index.js`/`index.ts` and install:

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

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

## Best Practices

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

  <Card title="Declare Minimal Requirements" icon="list-check">
    Only request tools and capabilities you actually need
  </Card>

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

  <Card title="Clear Input Schemas" icon="diagram-project">
    Include descriptions for every parameter
  </Card>

  <Card title="Handle Errors Gracefully" icon="circle-exclamation">
    Return JSON error objects rather than crashing
  </Card>

  <Card title="Version Carefully" icon="code-branch">
    Use semantic versioning; breaking changes require major bump
  </Card>

  <Card title="Test with Multiple Agents" icon="users-gear">
    Verify compatibility with different agent templates and providers
  </Card>

  <Card title="Include Documentation" icon="book">
    Document setup steps, dependencies, and examples
  </Card>
</CardGroup>
