How to Create and Use Executable Skills as Python Packages in Prime Agent

Prime Agent treats an executable skill as a Python directory containing SKILL.md, pyproject.toml, and a src/ package with an async run() function, then installs it editable into the persistent IPython kernel where it becomes directly awaitable.

Prime Agent provides a powerful skill system that lets you extend agent capabilities with reusable Python code. This guide explains how to create and use executable skills as Python packages—full Python modules that install into the agent's kernel and expose both programmatic and shell interfaces.

What Makes a Skill Executable

A skill becomes a Python-backed skill only when four requirements are met. According to the Prime Agent source code, missing any requirement degrades the skill to markdown-only mode with a load warning.

The detection contract in [packages/coding-agent/src/core/skills.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/skills.ts) requires:

Requirement Purpose
SKILL.md with YAML front-matter Describes capability to the LLM
pyproject.toml at skill root Drives editable installation
Valid Python import name (- → _) Determines module exposure in kernel
src/<import_name>/__init__.py Provides callable implementation

Minimal Skill Directory Structure

Every executable skill follows this layout:

my-skill/
├── SKILL.md
├── pyproject.toml
└── src/
    └── my_skill/
        └── __init__.py

The directory name my-skill becomes the import name my_skill after hyphen-to-underscore conversion. This naming convention is enforced in the skill discovery logic.

SKILL.md: Defining the Contract

The SKILL.md file serves as the user-visible contract. Only name and description from the YAML front-matter are shown to the LLM; implementation details load on demand.

Example from [python-skills.md](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/skills/skill-creator/references/python-skills.md):

---
name: word-count
description: Count word frequencies in text and return the most common words.
---

# Word Count

Call directly from the kernel:

    await word_count("some text to analyze", top=3)

Or from a shell cell:

    !word_count "some text to analyze" --top 3

pyproject.toml: Package Configuration

The pyproject.toml drives the editable install and optional CLI registration:

[project]
name = "word-count"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = []

[project.scripts]
word_count = "rlm.skill:cli"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/word_count"]

Key points:

  • [project.scripts] creates the shell command word_count via rlm.skill:cli
  • Hatchling is required when the distribution name differs from the package directory (common with hyphenated names)
  • The wheel target explicitly maps src/word_count to resolve path mismatches

Implementation: The run() Function

The core implementation lives in src/<import_name>/__init__.py. From the reference example:

from collections import Counter

async def run(text: str, top: int = 5) -> str:
    """Count words in text and return the most common ones."""
    counts = Counter(text.lower().split())
    return "\n".join(f"{word}: {count}" for word, count in counts.most_common(top))

Critical implementation rules from the source:

  • run can be async or sync—the kernel always awaits it
  • The function's docstring and signature are copied to the module object for help() visibility
  • Return values should be strings for clean REPL display

How the Kernel Exposes Your Skill

After installation into the persistent IPython kernel (default ~/.prime/agent/kernel-venv, override with PRIME_AGENT_KERNEL_VENV), the kernel:

  1. Imports the package under the derived import name
  2. Binds it to a matching variable in the REPL namespace
  3. Wraps the module to make it directly awaitable—calling await word_count(...) invokes word_count.run(...)
  4. Captures import failures: broken skills bind to a placeholder that raises RuntimeError with details

This behavior is implemented in [packages/coding-agent/src/core/skill-blocks.ts](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/skill-blocks.ts), which handles lazy loading of Python packages on demand.

Three Ways to Use Your Skill

Context Syntax Notes
IPython REPL await word_count("text", top=3) Direct await on the bound module
Shell cell !word_count "text" --top 3 Uses [project.scripts] entry point
Other skills import rlm; await rlm.run("subtask") Spawn sub-agents via rlm module

Verification Steps

Follow this checklist to validate your executable skill:

1. Contract check

Verify the directory structure, valid Python identifier conversion, and wheel configuration.

2. Standalone test

Run outside the kernel before loading into Prime Agent:

cd <skill-dir> && uv run python -c \
  "import asyncio, word_count; print(asyncio.run(word_count.run('a b a', top=1)))"

3. Kernel test

Start a fresh Prime Agent session, then verify:

help(word_count)          # Shows docstring and signature

await word_count("test")  # Executes or raises RuntimeError with details

If any step fails, Prime Agent logs a warning and falls back to markdown-only mode.

Summary

  • Executable skills as Python packages require SKILL.md, pyproject.toml, and a src/ package with __init__.py containing a run() function
  • Prime Agent installs packages editable into ~/.prime/agent/kernel-venv (configurable via PRIME_AGENT_KERNEL_VENV)
  • The kernel makes modules directly awaitable: await skill_name(...) calls skill_name.run(...)
  • Add [project.scripts] to expose shell commands usable with ! prefix
  • Use async run() functions for consistency; the kernel awaits both sync and async variants

Frequently Asked Questions

What happens if pyproject.toml is missing?

Prime Agent degrades the skill to markdown-only mode with a load warning. The SKILL.md description remains visible to the LLM, but no Python code executes.

Why does the import name convert hyphens to underscores?

Python identifiers cannot contain hyphens. The conversion rule (my-skill → my_skill) ensures valid module names while preserving descriptive directory naming.

Can I use setuptools instead of hatchling?

Yes, any PEP 517 build backend works. Hatchling is documented in the reference because it cleanly handles cases where the distribution name (with hyphens) differs from the package directory name (with underscores).

How do skills handle dependencies?

List requirements under [project] dependencies in pyproject.toml. Prime Agent installs them during the editable install into the persistent kernel environment.

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 →