How to Define Skills in an OpenAI Plugin Structure: A Complete Guide
To define a skill in an OpenAI plugin structure, create a dedicated directory under plugins/<plugin-name>/skills/ containing a SKILL.md file with YAML front matter, an agents/openai.yaml UI specification, and optional helper scripts that implement the runtime logic.
OpenAI plugins are organized as collections of reusable capabilities called skills, each residing in the openai/plugins repository. Learning how to define skills in an OpenAI plugin structure enables you to extend Codex with custom tools that integrate seamlessly into the agentic workflow. Every skill follows a strict three-part architecture that separates metadata declaration from implementation logic.
The Three Core Components of an OpenAI Plugin Skill
Each skill lives in its own directory under plugins/<plugin-name>/skills/<skill-name>/ and requires three mandatory parts to function within the Codex ecosystem.
SKILL.md: Metadata and Documentation
The SKILL.md file serves as the canonical declaration of the skill's identity. It must begin with a YAML front-matter block that registers the skill with the system:
---
name: Zotero
description: Use Zotero Desktop to search your library and add citations
---
The name field becomes the skill identifier used in prompts (e.g., $Zotero), while the description appears in the plugin catalogue. Following the front matter, the markdown body contains usage guidelines, command references, workflow documentation, and safety policies. According to the source code in plugins/zotero/skills/zotero/SKILL.md, this file should remain self-contained so users understand capabilities without referencing external documentation.
agents/openai.yaml: UI and Prompt Configuration
The agents/openai.yaml file, located at plugins/<plugin-name>/skills/<skill-name>/agents/openai.yaml, defines how the skill appears in the UI and how the model interacts with it:
interface:
display_name: "Zotero"
short_description: "Search Zotero and add citations"
icon_small: "./assets/icon.png"
default_prompt: "Use $Zotero to search my Zotero library..."
This specification dictates which model to invoke, what system prompt to prepend to user queries, and which icons render in the interface. The default_prompt is automatically injected when the skill is selected, establishing the context for the LLM.
Helper Scripts and Assets: Runtime Implementation
The actual logic resides in executable helpers stored under plugins/<plugin-name>/skills/<skill-name>/scripts/. These scripts must use stdlib-only Python (no external dependencies) and are executed by Codex via the python3 command line. Static assets such as icons and images belong in the assets/ directory and are referenced relative to the skill root.
How Skills Are Wired Together
Understanding the runtime flow clarifies how the three components interact when a user invokes a capability:
-
Registration – Codex loads the YAML front matter from
SKILL.mdto register the skill identifier and description. -
Prompt Construction – When selected, the system merges the
default_promptfromagents/openai.yamlwith the user's query, creating a contextualized instruction set for the model. -
Execution – The model identifies the need to call a helper script (e.g.,
python3 <plugin-root>/skills/zotero/scripts/zotero.py --json "query") and executes it via the command line. -
Response Parsing – The script outputs JSON or plain text, which the model receives and uses to render the final response to the user.
Creating a New Skill with the Plugin Creator
The repository provides a scaffolding tool to generate the complete directory structure. Run the following command from the repository root:
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py \
my-plugin \
--path ./plugins \
--marketplace-path ./.agents/plugins/marketplace.json \
--with-skills --with-scripts --with-assets --with-marketplace
This generates:
plugins/my-plugin/
└─ skills/
└─ my-skill/
├─ SKILL.md
├─ agents/
│ └─ openai.yaml
├─ scripts/
│ └─ my_script.py
└─ assets/
└─ icon.png
The generated SKILL.md includes template sections for "Fast starts", "Workflow", and "Output standards". Refer to .agents/skills/plugin-creator/SKILL.md for detailed scaffolding options.
Best Practices for Skill Definition
Follow these patterns established in the plugins/zotero and plugins/github/skills/yeet implementations:
-
Keep documentation self-contained – All commands, safety notes, and usage examples must reside in
SKILL.mdso users understand the skill without external references. -
Expose JSON output – Helper scripts should implement a
--jsonflag (as demonstrated in the Zotero skill) to return machine-readable data that Codex can parse reliably. -
Declare safety guards – For write-heavy actions like commits or pushes, explicitly document required user confirmations in the "Write Safety" section, following the pattern in
plugins/github/skills/yeet/SKILL.md. -
Version-control assets – Store icons as PNG or SVG files under
assets/and reference them with relative paths inagents/openai.yaml.
Complete Example: Building an Echo Skill
Here is a minimal, functional skill that echoes user input back unchanged.
SKILL.md Definition
Create plugins/echo/skills/echo/SKILL.md:
---
name: echo
description: Return the supplied text unchanged – useful for quick tests.
---
# Echo
## Fast start
```bash
python3 <plugin-root>/skills/echo/scripts/echo.py "Hello world"
Workflow
- The model receives the user request.
- It injects the request into the default prompt (
Use $echo …). - The helper prints the payload as JSON:
python3 <plugin-root>/skills/echo/scripts/echo.py --json "Hello world"
# → {"result":"Hello world"}
Output standards
- Always return a JSON object with a single
resultfield. - No side‑effects; safe for any user context.
### Agent Configuration
Create [`plugins/echo/skills/echo/agents/openai.yaml`](https://github.com/openai/plugins/blob/main/plugins/echo/skills/echo/agents/openai.yaml):
```yaml
interface:
display_name: "Echo"
short_description: "Echo back whatever you give me"
icon_small: "./assets/icon.png"
icon_large: "./assets/icon.png"
default_prompt: "Use $echo to repeat the user’s input exactly."
Helper Script Implementation
Create plugins/echo/skills/echo/scripts/echo.py:
#!/usr/bin/env python3
import json, sys
if "--json" in sys.argv:
# Strip the flag and any leading option names
text = " ".join(arg for arg in sys.argv[1:] if not arg.startswith("--"))
print(json.dumps({"result": text}))
else:
print(" ".join(sys.argv[1:]))
Runtime Flow
When a user requests "Please repeat the phrase 'quick brown fox'", Codex constructs the prompt:
Use $echo to repeat the user’s input exactly.
User: Please repeat the phrase 'quick brown fox'.
Codex executes the helper and receives {"result":"quick brown fox"}, then renders the final response:
quick brown fox
Summary
- Three files are mandatory:
SKILL.md(with YAML front matter),agents/openai.yaml, and the optional but typical helper scripts underscripts/. - Directory structure matters: Skills must reside at
plugins/<plugin-name>/skills/<skill-name>/to be discovered by the Codex runtime. - Use stdlib-only Python: Helper scripts run via
python3command line and cannot rely on external packages. - JSON output preferred: Implement
--jsonflags for reliable machine-readable communication between scripts and the model. - Safety documentation is critical: Document write-operation safeguards explicitly in
SKILL.md, as shown in the GitHubyeetskill.
Frequently Asked Questions
What is the mandatory file structure for an OpenAI plugin skill?
Every skill requires a SKILL.md file (containing YAML front matter with name and description fields) and an agents/openai.yaml file (containing the interface configuration). These must reside in plugins/<plugin-name>/skills/<skill-name>/. Helper scripts are optional but typically placed in a scripts/ subdirectory.
How does the SKILL.md front matter connect to the Codex runtime?
The first three lines of SKILL.md contain a YAML block that Codex reads during skill discovery to register the identifier. The name field becomes the invocation token (e.g., $Zotero), while the description populates the plugin catalogue UI. This registration happens before any code execution occurs.
Can skills depend on external Python packages?
No. Helper scripts must be stdlib-only and execute via the system's python3 binary without external dependencies. As implemented in the openai/plugins repository, scripts like zotero.py rely solely on standard library modules to ensure portability and security.
How do I add safety guards to prevent destructive operations?
Document safety requirements in the "Write Safety" section of SKILL.md, explicitly stating required user confirmations (e.g., "Never push without confirming scope"). For write-heavy skills like the GitHub yeet skill, include policy notes that Codex can reference to ensure destructive actions receive explicit user approval before execution.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →