Skip to content

Skills Development

OmniAgent supports two types of skills:

  1. Markdown Skills - SKILL.md files compatible with OpenClaw format
  2. Compiled Skills - Go packages that register callable tools with the agent

Overview

Markdown skills inject instructions into the system prompt, teaching the agent how to use external tools.

Compiled skills register actual Go functions as LLM tools, enabling direct function calling.

Skill Format

Skills are defined in SKILL.md files:

---
name: weather
description: Get weather forecasts
metadata:
  emoji: "🌤️"
  requires:
    bins: ["curl"]
  install:
    - name: curl
      brew: curl
      apt: curl
---

# Weather Skill

You can check the weather using the `curl` command:

## Get Current Weather

```bash
curl "wttr.in/London?format=3"

Get Detailed Forecast

curl "wttr.in/London"
## Skill Packs

Skill packs are pre-bundled collections of markdown skills embedded via `go:embed`. They provide a convenient way to distribute and share skills.

### Using a Skill Pack

```go
import (
    "github.com/plexusone/omniagent/agent"
    skills "github.com/plexusone/omniagent-skills"
)

// Load all skills from a skill pack
agent, err := agent.New(config,
    agent.WithSkillPack(skills.Default().FS()),
)

Filtering Skills

Load only specific skills using includes:

agent, err := agent.New(config,
    agent.WithSkillPack(skills.Default().FS()),
    agent.WithSkillIncludes("github", "weather", "tmux"),
)

Or exclude specific skills:

agent, err := agent.New(config,
    agent.WithSkillPack(skills.Default().FS()),
    agent.WithSkillExcludes("notion", "slack"),
)

Configuration File

Control skill loading via config:

skills:
  enabled: true
  packs:
    - omniagent-skills  # Informational only
  paths:
    - ~/.omniagent/skills
  includes:
    - github
    - weather
  excludes:
    - deprecated-skill
  max_injected: 20

Directory Override

Skills from directories take precedence over embedded pack skills with the same name. This allows customizing bundled skills:

~/.omniagent/skills/
└── github/
    └── SKILL.md  # Overrides the github skill from the pack

Available Skill Packs

Pack Description Skills
omniagent-skills Default skill pack 18 OpenClaw-compatible skills

Agent Options

Option Description
WithSkillPack(fs.FS) Register an embedded skill pack
WithSkillDirs(...string) Set skill directories
WithSkillIncludes(...string) Only load named skills
WithSkillExcludes(...string) Skip named skills
WithSkillManager(*Manager) Use a custom skill manager

Skill Discovery

Skills are discovered from:

  1. Embedded skill packs (via WithSkillPack)
  2. ~/.omniagent/skills/
  3. Custom paths via skills.paths config
skills:
  enabled: true
  paths:
    - ~/.omniagent/skills
    - /opt/shared-skills
  max_injected: 20

Managing Skills

List Skills

omniagent skills list

Output:

✓ 🎵 sonoscli - Control Sonos speakers via CLI
✓ 🐙 github - GitHub CLI operations
✗ ☀️ weather - Weather forecasts (missing: weather binary)

Show Skill Details

omniagent skills info sonoscli

Check Requirements

omniagent skills check

Requirements

Skills can declare requirements that must be met:

Binary Requirements

metadata:
  requires:
    bins: ["gh", "jq"]  # All required
    anyBins: ["curl", "wget"]  # At least one required

Environment Variables

metadata:
  requires:
    env: ["GITHUB_TOKEN", "OPENAI_API_KEY"]

Install Hints

metadata:
  install:
    - name: gh
      brew: gh
      apt: gh
    - name: jq
      brew: jq
      apt: jq

Creating a Skill

1. Create Directory

mkdir -p ~/.omniagent/skills/myskill

2. Create SKILL.md

---
name: myskill
description: My custom skill
metadata:
  emoji: "🔧"
---

# My Skill

Instructions for the AI agent on how to use this skill...

## Available Commands

- `mytool list` - List all items
- `mytool add <name>` - Add a new item

3. Verify

omniagent skills list
omniagent skills info myskill

Best Practices

Keep Instructions Clear

Write instructions as if explaining to a human who knows nothing about your tool.

Include Examples

Show concrete examples of commands and expected output.

Declare Requirements

Always declare binary and environment requirements so users know what's needed.

Use Emojis Sparingly

One emoji in the metadata helps identify skills visually.

ClawHub Compatibility

OmniAgent is compatible with skills from ClawHub. Install skills using:

# Coming soon
bunx clawhub install sonoscli

Or manually clone to your skills directory:

git clone https://github.com/user/skill ~/.omniagent/skills/skill

Compiled Skills

Compiled skills are Go packages that register functions as LLM tools. They provide better performance and type safety compared to markdown skills.

Creating a Compiled Skill

1. Implement the Skill Interface

package myskill

import (
    "context"
    "github.com/plexusone/omniagent/skills/compiled"
)

type MySkill struct {
    // skill state
}

func New() *MySkill {
    return &MySkill{}
}

func (s *MySkill) Name() string {
    return "myskill"
}

func (s *MySkill) Description() string {
    return "My custom skill description"
}

func (s *MySkill) Tools() []compiled.Tool {
    return []compiled.Tool{
        {
            Name:        "myskill_action",
            Description: "Performs an action",
            Parameters: map[string]compiled.Parameter{
                "input": {
                    Type:        "string",
                    Description: "The input value",
                    Required:    true,
                },
            },
            Handler: s.handleAction,
        },
    }
}

func (s *MySkill) Init(ctx context.Context) error {
    // Initialize resources
    return nil
}

func (s *MySkill) Close() error {
    // Cleanup resources
    return nil
}

func (s *MySkill) handleAction(ctx context.Context, params map[string]any) (any, error) {
    input := params["input"].(string)
    return map[string]any{"result": "Processed: " + input}, nil
}

2. Register with Agent

import "github.com/example/myskill"

skill := myskill.New()
agent, err := agent.New(config,
    agent.WithCompiledSkill(skill),
)

Storage-Aware Skills

Skills that need persistent storage implement StorageAware:

import "github.com/plexusone/omnistorage-core/kvs"

type MySkill struct {
    storage kvs.Store
}

func (s *MySkill) SetStorage(store kvs.Store) {
    s.storage = store
}

Storage is automatically injected when using WithSessionsFromStorage or WithStorage:

agent.New(config,
    agent.WithSessionsFromStorage(backend),  // Injects storage
    agent.WithCompiledSkill(mySkill),        // Receives storage
)

Parameter Types

Type JSON Schema Type Go Type
"string" string string
"integer" integer int, int64
"number" number float64
"boolean" boolean bool
"array" array []any
"object" object map[string]any

Built-in Compiled Skills

OmniAgent includes these compiled skills:

Skill Tools Description
sessions sessions_list, sessions_history, etc. Session management

Skill Lifecycle

agent.New()
    ├── WithCompiledSkill(skill)
    │       └── RegisterCompiledSkill()
    │               ├── SetStorage() if StorageAware
    │               └── Register tools with ToolRegistry
    ├── InitCompiledSkills()
    │       └── skill.Init(ctx) for each skill
    ... agent runs ...
    └── agent.Close()
            └── CloseCompiledSkills()
                    └── skill.Close() for each skill

Best Practices

  1. Return Structured Data - Return maps or structs, not plain strings
  2. Handle Errors Gracefully - Return user-friendly error messages
  3. Validate Parameters - Check required parameters before processing
  4. Use Descriptive Names - Tool names should be skillname_action format
  5. Document Parameters - Descriptions help the LLM use tools correctly

Remote Skills

Remote skills connect to external services and expose their capabilities as agent tools. OmniAgent supports two types of remote skills:

MCP Skills

MCP (Model Context Protocol) skills spawn external MCP servers and expose their tools to the agent.

import "github.com/plexusone/omniagent/agent"

agent, err := agent.New(config,
    agent.WithMCPSkill(mcp.Config{
        Name:    "github",
        Command: []string{"npx", "-y", "@modelcontextprotocol/server-github"},
        Env: map[string]string{
            "GITHUB_TOKEN": os.Getenv("GITHUB_TOKEN"),
        },
    }),
)

MCP Configuration

Field Description
Name Skill identifier (must be unique)
Description Human-readable description
Command Command to spawn the MCP server
Env Environment variables for the command
LazyConnect Defer connection until first tool call
ClientName Client identifier sent to server
ClientVersion Client version sent to server
Server Install Command
GitHub npx -y @modelcontextprotocol/server-github
Filesystem npx -y @modelcontextprotocol/server-filesystem
Brave Search npx -y @anthropic/brave-search-mcp

OpenAPI Skills

OpenAPI skills parse OpenAPI 3.x specifications and expose operations as tools.

import (
    "github.com/plexusone/omniagent/agent"
    openapi "github.com/plexusone/omniagent/skills/remote/openapi"
)

agent, err := agent.New(config,
    agent.WithOpenAPISkill(openapi.Config{
        Name:    "petstore",
        SpecURL: "https://petstore3.swagger.io/api/v3/openapi.json",
        Auth: openapi.AuthConfig{
            Type:   openapi.AuthAPIKey,
            APIKey: os.Getenv("PETSTORE_API_KEY"),
        },
    }),
)

OpenAPI Configuration

Field Description
Name Skill identifier (must be unique)
Description Human-readable description
SpecURL URL to fetch OpenAPI spec
SpecFile Path to local OpenAPI spec file
BaseURL Override the server URL from spec
Auth Authentication configuration
IncludeOperations Filter to specific operation IDs
ExcludeOperations Exclude specific operation IDs
IncludeTags Filter to operations with tags
LazyLoad Defer spec loading until first use
RequestTimeout Timeout for API requests (seconds)

Authentication Types

// API Key (header)
Auth: openapi.AuthConfig{
    Type:       openapi.AuthAPIKey,
    APIKey:     "your-api-key",
    APIKeyName: "X-API-Key",  // default
    APIKeyIn:   "header",     // or "query"
}

// Bearer Token
Auth: openapi.AuthConfig{
    Type:  openapi.AuthBearer,
    Token: "your-bearer-token",
}

// Basic Auth
Auth: openapi.AuthConfig{
    Type:     openapi.AuthBasic,
    Username: "user",
    Password: "pass",
}

Filtering Operations

Include only specific operations:

agent.WithOpenAPISkill(openapi.Config{
    Name:              "api",
    SpecURL:           "https://api.example.com/openapi.json",
    IncludeOperations: []string{"getUser", "listUsers"},
})

Filter by tags:

agent.WithOpenAPISkill(openapi.Config{
    Name:        "api",
    SpecURL:     "https://api.example.com/openapi.json",
    IncludeTags: []string{"users", "accounts"},
})

Exclude operations:

agent.WithOpenAPISkill(openapi.Config{
    Name:              "api",
    SpecURL:           "https://api.example.com/openapi.json",
    ExcludeOperations: []string{"deleteUser", "adminEndpoint"},
})

Remote Skill Lifecycle

agent.New()
    ├── WithMCPSkill() / WithOpenAPISkill()
    │       └── RegisterCompiledSkill()
    ├── InitCompiledSkills()
    │       ├── MCP: Spawn server, discover tools
    │       └── OpenAPI: Load spec, generate tools
    ... agent runs ...
    └── agent.Close()
            ├── MCP: Terminate server process
            └── OpenAPI: No cleanup needed