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

> Learn how to extend or add new skills to OpenMAIC. This developer guide details creating skill directories, SKILL.md files, and utilizing API endpoints for seamless integration.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: how-to-guide
- Published: 2026-09-01

---

**To add a new skill to OpenMAIC, create a self-contained directory containing a [`SKILL.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/SKILL.md) file with YAML front-matter (defining `name`, `description`, and `title`) and an optional [`outline-constraints.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/SKILL.md) file. The [`lib/workbench/skill-load.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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.

```bash
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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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】.

```yaml
---
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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/server/agent-runtime/skills.ts)【skills.ts-L52】.

```json
{
  "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:

```json
{
  "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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/SKILL.md) file (or a ZIP archive containing it):

```bash
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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/skill-load.ts)** — Client-side detector that recognizes `read` operations targeting [`SKILL.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/SKILL.md) files and renders the skill-load timeline card【skill-load.ts-L26】.
- **[`app/api/agent/skills/route.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/SKILL.md) with YAML front-matter (`name`, `description`, `title`) and optional [`outline-constraints.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/skill-load.ts).
- **Constraints** can be enforced using [`outline-constraints.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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】.