How to Extend or Add New Skills to OpenMAIC: A Complete Developer Guide

To add a new skill to OpenMAIC, create a self-contained directory containing a SKILL.md file with YAML front-matter (defining name, description, and title) and an optional outline-constraints.json file, then place it in the skills/ directory or upload it via the POST /api/agent/skills API endpoint.

OpenMAIC treats skills as modular, file-based components that the system discovers automatically without requiring code changes. Whether you are contributing to the core repository or extending an instance with user-specific capabilities, the skill system leverages the Pi-native read tool to load instructional content on demand.

Understanding the OpenMAIC Skill Architecture

OpenMAIC skills are self-contained directories that the runtime discovers through two primary mechanisms: builtin skills (loaded from the skills/ folder at startup) and user-uploaded skills (stored in a virtual file system). According to the source code in lib/server/agent-runtime/skills.ts, the system initializes by calling loadSkills() to populate a builtinCache, then merges user skills from the virtual root /__openmaic_user_skills__ when sessions are created【skills.ts】.

When the Pi agent invokes a skill, it uses the native read tool to access the SKILL.md file. The lib/workbench/skill-load.ts module detects these read operations and renders a "load skill" card in the workbench interface, providing visual feedback that the skill context has been injected into the conversation【skill-load.ts】.

Adding a Built-in Skill to the Repository

Built-in skills reside in the skills/ directory and are automatically discovered when the server starts or hot-reloads. Follow these steps to create a new built-in skill:

1. Create the Skill Directory

Create a new directory under skills/agent-runtime/ (or any sub-path within skills/). The directory name becomes the skill's stable id used for invocation.

mkdir skills/agent-runtime/my-awesome-skill

No registration or import statements are required—the listBuiltinSkills() function recursively scans the skills/ tree to discover new directories automatically【skills.ts】.

2. Write the SKILL.md File

Each skill must contain a SKILL.md file with a YAML front-matter block followed by instructional content. The front-matter must include name, description, and optionally title and metadata.title for proper discovery by the readSkillTitle helper【skills.ts】.

---
name: "my-awesome-skill"
title: "My Awesome Skill"
description: "A demo skill that generates a simple two-scene outline."
---

# My Awesome Skill

You are a helpful assistant that should produce a two-scene outline:
1. An *introductory* scene.
2. A *conclusion* scene.

Use the format `Scene <n>: <title>` for each scene.

The body content after the front-matter provides the actual instructions the language model receives when the skill is loaded.

3. (Optional) Define Outline Constraints

For skills that generate structured outlines, you can add an outline-constraints.json file to enforce machine-checkable rules such as scene counts or allowed widget types. The JSON schema follows the OutlineConstraints TypeScript interface defined in lib/server/agent-runtime/skills.ts【skills.ts-L52】.

{
  "sceneCount": { "min": 2, "max": 2 },
  "allowedTypes": ["introductory", "conclusion"]
}

This file is optional but recommended for skills that require strict structural validation of generated content.

4. Invoke the Skill

Once committed and deployed, invoke the skill from the UI by typing /my-awesome-skill (using the directory name as the id) at the start of a chat message. This triggers the Pi read tool with the following arguments:

{
  "toolCall": {
    "name": "read",
    "arguments": { "path": "/skills/agent-runtime/my-awesome-skill/SKILL.md" }
  }
}

The createNativeSkillReadTool function locates the file, parses the skill metadata, and returns the instructional content to the model【skills.ts-L59】. The workbench then displays a "Skill loaded" card via the skillLoadId handler in skill-load.ts【skill-load.ts-L26】.

Uploading User Skills via the API

For runtime-extensible deployments, OpenMAIC supports uploading skills without modifying the repository. Send a POST request to /api/agent/skills with the SKILL.md file (or a ZIP archive containing it):

curl -X POST https://your-openmaic-instance/api/agent/skills \
  -F "file=@SKILL.md" \
  -H "Authorization: Bearer <your-access-token>"

The server validates the front-matter, stores the skill under /__openmaic_user_skills__/<uuid>/, and makes it available in the UI skill picker【route.ts】. User skills are discovered alongside built-in skills in the availableSkillsPromptBlock function, which generates the system prompt component listing all accessible capabilities【skills.ts-L76】.

Key Source Files for Skill Development

Understanding these implementation files helps troubleshoot and extend skill functionality:

  • lib/server/agent-runtime/skills.ts — Core loader implementing loadSkills(), listBuiltinSkills(), and createNativeSkillReadTool; handles caching in builtinCache and virtual file resolution for user skills【skills.ts-L97】.
  • lib/workbench/skill-load.ts — Client-side detector that recognizes read operations targeting SKILL.md files and renders the skill-load timeline card【skill-load.ts-L26】.
  • app/api/agent/skills/route.ts — HTTP handler for the POST /api/agent/skills endpoint that manages user skill uploads and validation【route.ts】.
  • lib/server/agent-runtime/user-skills.ts — Contains listUserSkills() for retrieving uploaded skills from the virtual file system【user-skills.ts】.

Summary

  • Skill structure requires a directory containing SKILL.md with YAML front-matter (name, description, title) and optional outline-constraints.json.
  • Built-in skills are automatically discovered when placed in the skills/ tree and scanned by listBuiltinSkills() without code changes.
  • User skills can be uploaded via POST /api/agent/skills and stored in the virtual root /__openmaic_user_skills__ for immediate availability.
  • Invocation occurs through the Pi-native read tool accessing the skill path, with visual feedback handled by skill-load.ts.
  • Constraints can be enforced using outline-constraints.json following the OutlineConstraints schema defined in the runtime.

Frequently Asked Questions

Can I add a skill without restarting the OpenMAIC server?

Yes, for user-uploaded skills. When you upload via the POST /api/agent/skills endpoint, the skill is immediately available in the virtual file system under /__openmaic_user_skills__ and appears in the skill picker for new sessions. Built-in skills require a server restart or hot-reload to be picked up by listBuiltinSkills().

What happens if my SKILL.md is missing required front-matter fields?

The skill discovery mechanism relies on the name, description, and title fields in the YAML front-matter to populate the skill picker and system prompt. If these are missing, the readSkillTitle function may fail to properly index the skill, causing it to be omitted from the availableSkillsPromptBlock and unavailable for invocation via the / command.

How does OpenMAIC distinguish between built-in and user-uploaded skills?

The system uses path prefixes. Built-in skills reside in physical directories under skills/ and are cached in builtinCache at startup. User skills are stored in the virtual file system under /__openmaic_user_skills__/<uuid>/ and merged into the skill list by createNativeSkillReadTool, which handles both paths transparently when processing read tool calls【skills.ts-L82】.

Can I constrain the output format when using a custom skill?

Yes, by including an outline-constraints.json file in your skill directory. This JSON file follows the OutlineConstraints interface and can specify requirements like sceneCount (min/max) and allowedTypes for widgets or scenes. The runtime uses these constraints to validate or guide the agent's output structure【skills.ts-L52】.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →