Skip to main content
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. OpenFang ships with 60 bundled expert knowledge skills compiled into the binary.

Overview

A skill consists of:
  1. A manifest (skill.toml or SKILL.md) that declares metadata, runtime type, provided tools, and requirements
  2. An entry point (Python script, WASM module, Node.js module, or prompt-only Markdown) that implements the tool logic
Skills are installed to ~/.openfang/skills/ and made available to agents through the skill registry.

Supported Runtimes

Language: Python 3.8+Sandboxed: No (subprocess with env_clear())Protocol: JSON over stdin/stdoutBest For: Easiest to write, quick prototyping, data processing

60 Bundled Skills

OpenFang includes 60 expert knowledge skills (no installation needed):
  • ci-cd — CI/CD pipeline expertise
  • ansible — Ansible playbook patterns
  • prometheus — Monitoring and alerting
  • nginx — NGINX configuration
  • kubernetes — K8s deployment patterns
  • terraform — Infrastructure as code
  • helm — Helm chart development
  • docker — Container best practices
  • sysadmin — Linux system administration
  • shell-scripting — Bash/shell scripting
  • linux-networking — Network configuration
  • aws — AWS service expertise
  • gcp — Google Cloud Platform
  • azure — Microsoft Azure
  • rust-expert — Rust programming patterns
  • python-expert — Python best practices
  • typescript-expert — TypeScript development
  • golang-expert — Go language expertise
  • react-expert — React patterns and hooks
  • nextjs-expert — Next.js app development
  • css-expert — CSS and styling
  • postgres-expert — PostgreSQL optimization
  • redis-expert — Redis patterns
  • sqlite-expert — SQLite usage
  • mongodb — MongoDB queries
  • elasticsearch — Search and analytics
  • sql-analyst — SQL query optimization
  • graphql-expert — GraphQL schema design
  • openapi-expert — OpenAPI/Swagger specs
  • api-tester — API testing strategies
  • oauth-expert — OAuth implementation
  • ml-engineer — Machine learning workflows
  • llm-finetuning — LLM fine-tuning
  • vector-db — Vector database usage
  • prompt-engineer — Prompt engineering
  • security-audit — Security best practices
  • crypto-expert — Cryptography implementation
  • compliance — Compliance requirements
  • github — GitHub workflows and actions
  • git-expert — Git workflows
  • jira — Jira automation
  • linear-tools — Linear workflow
  • sentry — Error tracking setup
  • code-reviewer — Code review guidelines
  • regex-expert — Regular expressions
  • technical-writer — Technical documentation
  • writing-coach — Writing improvement
  • email-writer — Professional emails
  • presentation — Presentation design
  • data-analyst — Data analysis patterns
  • data-pipeline — ETL pipeline design
  • slack-tools — Slack bot development
  • notion — Notion API usage
  • confluence — Confluence integration
  • figma-expert — Figma plugin dev
  • interview-prep — Technical interviews
  • project-manager — Project management
  • wasm-expert — WebAssembly development
  • pdf-reader — PDF processing
  • web-search — Web search strategies

Skill Manifest (skill.toml)

[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 | prompt_only
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

[skill]
object
required
Metadata section
name
string
required
Unique skill name (used as install directory name)
version
string
default:"0.1.0"
Semantic version
description
string
Human-readable description
author
string
Author name or organization
license
string
License identifier (e.g., MIT, Apache-2.0)
tags
array
Tags for discovery on FangHub
[runtime]
object
required
Execution configuration
type
string
required
Runtime type: python, wasm, node, builtin, or prompt_only
entry
string
required
Relative path to the entry point file
[[tools.provided]]
array
required
Array of tool definitions this skill provides
[requirements]
object
Host requirements
tools
array
Built-in tools this skill needs the host to provide
capabilities
array
Capability strings the agent must have

Python Skills

Python skills run as subprocesses and communicate via JSON over stdin/stdout.

Protocol

Input (from OpenFang):
{
  "tool": "summarize_url",
  "input": {
    "url": "https://example.com"
  },
  "agent_id": "uuid-...",
  "agent_name": "researcher"
}
Output (success):
{
  "result": "- Point one\n- Point two\n- Point three"
}
Output (error):
{
  "error": "Failed to fetch URL: connection refused"
}

Example Implementation

#!/usr/bin/env python3
import json
import sys
import urllib.request

def summarize_url(url: str) -> str:
    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
    text = content[:500].strip()
    return f"Summary of {url}:\n{text}..."

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

WASM Skills

WASM skills run inside a sandboxed Wasmtime environment with resource limits.

Building a WASM Skill

1

Write in Rust

// 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}));
}
2

Compile to WASM

cargo build --target wasm32-wasi --release
3

Reference in Manifest

[runtime]
type = "wasm"
entry = "target/wasm32-wasi/release/my_skill.wasm"

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
Limits are derived from the agent’s [resources] section.

SKILL.md Format (Prompt-Only)

The SKILL.md format uses YAML frontmatter and Markdown body:
---
name: rust-expert
description: Expert Rust programming knowledge
---

# Rust Expert

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

## Common Patterns
...
All SKILL.md files pass through an automated prompt injection scanner that detects override attempts, data exfiltration patterns, and shell references before inclusion.

Installing Skills

openfang skill install /path/to/my-skill
Reads skill.toml, validates manifest, copies to ~/.openfang/skills/my-skill/.

Listing Installed Skills

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

openfang skill remove web-summarizer

Creating Skills

Interactive Scaffold

openfang skill create
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

Using Skills in Agent Manifests

Reference skills in the agent’s skills field:
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

1

Complete Metadata

Ensure skill.toml has complete metadata:
  • name, version, description, author, license, tags
2

Add Documentation

Include a README.md with usage instructions.
3

Test Locally

openfang skill install /path/to/my-skill
# Spawn an agent with the skill's tools and test them

Searching FangHub

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

openfang skill publish
Validates manifest, packages skill, and uploads to FangHub registry.

OpenClaw Compatibility

OpenFang can install and run OpenClaw-format skills.

Automatic Conversion

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 to OpenFang skills directory

Manual Conversion

Create skill.toml manually:
[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"] }

Best Practices

Keep Skills Focused

One skill should do one thing well. Don’t create monolithic skills with dozens of unrelated tools.

Declare Minimal Requirements

Only request the tools and capabilities your skill actually needs. Over-requesting capabilities reduces security.

Use Descriptive Tool Names

The LLM reads tool names and descriptions to decide when to use them. Be clear and specific.

Provide Clear Input Schemas

Include descriptions for every parameter so the LLM knows what to pass.

Handle Errors Gracefully

Always return a JSON error object rather than crashing. The agent loop depends on valid JSON responses.

Version Carefully

Use semantic versioning. Breaking changes require a major version bump.

Test with Multiple Agents

Verify your skill works with different agent templates and providers.

Include a README

Document setup steps, dependencies, and example usage.

CLI Commands Reference

CommandDescription
openfang skill install <source>Install skill (local dir, FangHub name, or git URL)
openfang skill listList all installed skills
openfang skill remove <name>Remove an installed skill
openfang skill search <query>Search FangHub for skills
openfang skill createCreate new skill scaffold (interactive)
openfang skill publishPublish skill to FangHub

Security

  • Python skills run with env_clear() — subprocess environment completely cleared, only whitelisted vars passed
  • WASM skills run in full sandbox with fuel and memory limits
  • SKILL.md files scanned for prompt injection before inclusion
  • Tool requirements validated — skills only get tools agent is authorized for
  • Capability enforcement — skills inherit agent’s capability restrictions
  • Path traversal prevention — skill entry paths validated to reject .. sequences

Build docs developers (and LLMs) love