# How to Debug Issues with Plugin Skill Loading or Invocation in OpenAI Plugins

> Debug OpenAI plugin skill loading and invocation issues by validating SKILL.md, checking the entry-point script, and ensuring the JSON response includes required keys.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: how-to-guide
- Published: 2026-06-19

---

**To debug issues with plugin skill loading or invocation, verify that your [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) metadata is valid, the entry-point script exposes a callable `main` function, and the JSON response includes the required `skill`, `passed`, `checks`, and `errors` keys.**

When you need to debug issues with plugin skill loading or invocation in the openai/plugins repository, systematic troubleshooting requires inspecting the metadata definitions, entry-point validations, and environment configuration that govern how the runtime discovers and executes each skill.

## Understanding the Skill Loading Pipeline

The runtime follows a strict five-step process to discover and execute skills. First, it scans the repository for [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) files located at `plugins/<plugin-name>/skills/<skill-name>/SKILL.md`. It then parses these markdown files to extract required fields including `skill_name`, `description`, and the entry-point script path. The system validates that the referenced script exists and contains a callable `main` function, as seen in [`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py). Finally, it registers the skill in an in-process skill hub, whose location defaults to `~/.physical-ai-skill-hub` but can be overridden via the `PHYSICAL_AI_SKILL_HUB_HOME` environment variable as implemented in [`plugins/nvidia/skills/omniverse-cad-to-simready/shared/preflight_manifest.py`](https://github.com/openai/plugins/blob/main/plugins/nvidia/skills/omniverse-cad-to-simready/shared/preflight_manifest.py).

## Common Skill Loading Failures and Solutions

### Skill Discovery Failures

Symptom: The runtime does not recognize your skill. Cause: The [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) file is missing or malformed. Check the file exists at the correct path and follows the schema demonstrated in [`plugins/zotero/skills/zotero/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/SKILL.md).

### Entry Point Not Found

Symptom: Validation errors regarding missing scripts. Cause: The path specified in [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) is incorrect or the file lacks execute permissions. Verify the script path matches the actual file location, such as [`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py), and ensure the file is readable.

### Missing main Function

Symptom: Runtime error stating the entry point is not callable. Cause: The implementation script does not expose a `main` function. Add `def main(request: dict) -> dict:` to your script, ensuring it accepts a dictionary and returns a dictionary.

### Payload Validation Errors

Symptom: Invocation succeeds but returns errors or fails silently. Cause: The response JSON lacks required keys. The return dictionary must include `skill`, `passed`, `checks`, and `errors`. Reference the pattern in [`plugins/nvidia/skills/omniverse-cad-to-simready/references/simready-validate/scripts/check_dependencies.py`](https://github.com/openai/plugins/blob/main/plugins/nvidia/skills/omniverse-cad-to-simready/references/simready-validate/scripts/check_dependencies.py) for the correct structure.

### Environment-Specific Failures

Symptom: Skills load in development but not in production. Cause: The `PHYSICAL_AI_SKILL_HUB_HOME` variable points to a non-existent directory. Check that this environment variable is set correctly or unset it to use the default location.

## Diagnostic Commands for Local Testing

Use these commands to verify your configuration before deployment.

List all discovered skills to confirm your [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) is detected:

```bash
python -c "
import json, pathlib, os
from pathlib import Path
root = Path('.')
skills = [p for p in root.rglob('SKILL.md')]
print('Discovered skills:', len(skills))
for s in skills:
    print('-', s.parent.relative_to(root))
"

```

Validate that a specific skill's entry point loads correctly and exposes the required `main` function:

```bash
python -c "
import importlib.util, pathlib, sys
script = pathlib.Path('plugins/zotero/skills/zotero/scripts/zotero.py')
spec = importlib.util.spec_from_file_location('zotero', script)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
print('Has main:', hasattr(module, 'main'))
"

```

Test local invocation using curl to verify the endpoint and payload handling:

```bash
curl -X POST http://localhost:8000/skills/zotero \
  -H 'Content-Type: application/json' \
  -d '{"action":"search","query":"machine learning"}'

```

## Key Source Files to Inspect

When debugging, examine these canonical implementations:

- **[`plugins/zotero/skills/zotero/SKILL.md`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/SKILL.md)**: Reference implementation showing the required metadata schema.
- **[`plugins/zotero/skills/zotero/scripts/zotero.py`](https://github.com/openai/plugins/blob/main/plugins/zotero/skills/zotero/scripts/zotero.py)**: Example entry-point script with the correct `main` function signature.
- **[`plugins/nvidia/skills/omniverse-cad-to-simready/shared/preflight_manifest.py`](https://github.com/openai/plugins/blob/main/plugins/nvidia/skills/omniverse-cad-to-simready/shared/preflight_manifest.py)**: Contains the logic for resolving the skill hub home directory via `PHYSICAL_AI_SKILL_HUB_HOME`.
- **[`plugins/nvidia/skills/omniverse-cad-to-simready/references/simready-validate/scripts/check_dependencies.py`](https://github.com/openai/plugins/blob/main/plugins/nvidia/skills/omniverse-cad-to-simready/references/simready-validate/scripts/check_dependencies.py)**: Demonstrates the expected JSON response format and error handling patterns.
- **[`.agents/skills/plugin-creator/scripts/create_basic_plugin.py`](https://github.com/openai/plugins/blob/main/.agents/skills/plugin-creator/scripts/create_basic_plugin.py)**: Utility script for scaffolding new skills with the correct directory structure.

## Summary

- Debug issues with plugin skill loading or invocation by checking the [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) metadata file for schema compliance.
- Ensure entry-point scripts expose a `main` function with the signature `def main(request: dict) -> dict:`.
- Verify JSON responses include the required keys: `skill`, `passed`, `checks`, and `errors`.
- Check the `PHYSICAL_AI_SKILL_HUB_HOME` environment variable if skills are not discovered in the expected location.
- Use the diagnostic Python commands to validate file discovery and entry-point loading locally.

## Frequently Asked Questions

### What directory structure is required for a skill to be discovered?

The runtime expects skills to reside at `plugins/<plugin-name>/skills/<skill-name>/` with a mandatory [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md) file in that directory. Missing this structure prevents the scanner from detecting the skill during the repository scan phase.

### How does the runtime validate skill entry points?

After parsing [`SKILL.md`](https://github.com/openai/plugins/blob/main/SKILL.md), the runtime checks that the specified script path exists and that the module contains a callable object named `main`. This validation occurs before registration to ensure the skill can handle invocation requests.

### What JSON format should a skill return?

The `main` function must return a dictionary containing four keys: `skill` (the skill identifier), `passed` (boolean status), `checks` (list of validation results), and `errors` (list of error messages). This schema is enforced during invocation as shown in the validation scripts.

### How can I override the default skill hub location?

Set the `PHYSICAL_AI_SKILL_HUB_HOME` environment variable to your desired path. If unset, the system defaults to `~/.physical-ai-skill-hub`. This setting is managed by the helper functions in [`plugins/nvidia/skills/omniverse-cad-to-simready/shared/preflight_manifest.py`](https://github.com/openai/plugins/blob/main/plugins/nvidia/skills/omniverse-cad-to-simready/shared/preflight_manifest.py).