How to Create Custom Python-Backed Skills for Prime Agent: A Complete Guide
Define a python_import field in your skill metadata and implement a JSON-stdio protocol to run Python code as a first-class Prime Agent skill.
Prime Agent's modular architecture lets you extend its capabilities without modifying the TypeScript core. By creating custom Python-backed skills, you can leverage any Python library—from standard modules to heavy data-science stacks—while the agent treats your code like native functionality. This guide walks through the skill discovery system, runtime execution model, and implementation patterns found in the PrimeIntellect-ai/prime-agent source code.
How Prime Agent Discovers and Loads Python Skills
Prime Agent uses a filesystem-based skill discovery system centered in packages/coding-agent/src/core/skills.ts. The loadSkillsFromDir() function recursively scans a configurable skills directory (default: <repo-root>/skills or ~/.prime-agent/skills) and builds Skill objects from metadata files.
A Python-backed skill is identified by the presence of a python_import: string field in its metadata. When detected, the loader invokes getPythonSkillRuntimeInfo() to construct a SkillRuntimeInfo record containing:
- The module path for
python -mexecution - Environment configuration
- STDIO communication settings
This information is stored alongside TypeScript-native skills, making Python skills indistinguishable to the LLM at call time.
The Python Skill Runtime Architecture
The RLM (Remote Language Model) runtime in packages/prime-agent-runtime/src/rlm/skill.py manages Python skill execution. When the LLM generates an <invoke skill="..."> message, the flow proceeds through:
- SkillInvocationMessageComponent (
packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts) parses the invocation - SkillRuntime.execute() spawns a subprocess using the stored command from
getPythonSkillRuntimeInfo() - JSON message protocol over STDIN/STDOUT carries requests and responses
- assistantMessageEventStream processes results identically to built-in tools
The Python side requires no Prime Agent dependencies—only adherence to the line-delimited JSON protocol.
Required JSON-stdio Protocol for Python Skills
Your Python module must implement a bidirectional message exchange:
| Message Direction | Format | Purpose |
|---|---|---|
| STDIN → Python | {"type": "invoke", "args": {...}} |
Carry LLM-provided arguments |
| Python → STDOUT | {"type": "result", "content": ...} |
Return final output |
| Python → STDOUT | {"type": "log", "content": ...} |
Optional streaming updates |
All messages are single-line JSON objects terminated by newline characters. The flush() call is critical—buffered output breaks protocol synchronization.
Creating a Minimal Python-Backed Skill
This example implements a time-reporting skill with complete metadata and runtime code:
# my-skill/__init__.py
# Metadata read by Prime Agent's skill loader
name = "my-skill"
description = "Returns current UTC time"
python_import = "my_skill" # Module name passed to python -m
# ----------------------------------------------------------------------
# Runtime implementation - executes in subprocess managed by RLM
# ----------------------------------------------------------------------
import json
import sys
import datetime
def json_msg(obj):
"""Emit a JSON message with proper flushing for STDIO protocol."""
sys.stdout.write(json.dumps(obj) + "\n")
sys.stdout.flush()
def main():
for line in sys.stdin:
request = json.loads(line)
if request.get("type") == "invoke":
now = datetime.datetime.utcnow().isoformat() + "Z"
json_msg({
"type": "result",
"content": f"The current UTC time is {now}"
})
break # Single invocation per process
if __name__ == "__main__":
main()
Deploy by placing the folder in your skills directory:
mkdir -p ~/.prime-agent/skills/my-skill/src/my_skill
cp my-skill/__init__.py ~/.prime-agent/skills/my-skill/src/my_skill/__init__.py
Prime Agent's loadSkillsFromDir() will detect python_import on next startup and register the skill.
Integrating Data Science Libraries
The protocol supports arbitrary complexity. This pandas-backed skill accepts CSV data and returns statistical summaries:
# data-skill/__init__.py
name = "data-analyzer"
description = "Analyze CSV data with pandas"
python_import = "data_analyzer"
import json
import sys
from io import StringIO
import pandas as pd
def json_msg(obj):
sys.stdout.write(json.dumps(obj) + "\n")
sys.stdout.flush()
def main():
line = sys.stdin.readline()
request = json.loads(line)
csv_text = request.get("args", {}).get("csv", "")
df = pd.read_csv(StringIO(csv_text))
result = {
"type": "result",
"content": {
"shape": df.shape,
"summary": df.describe().to_dict(),
"dtypes": {k: str(v) for k, v in df.dtypes.items()}
}
}
json_msg(result)
if __name__ == "__main__":
main()
Invoke from Prime Agent prompts naturally:
User: Analyze this data: <invoke skill="data-analyzer" csv="a,b\n1,2\n3,4"/>
Key Source Files and Their Roles
| File | Function | Relevance to Python Skills |
|---|---|---|
packages/coding-agent/src/core/skills.ts |
loadSkillsFromDir(), getPythonSkillRuntimeInfo() |
Discovers python_import metadata, builds runtime commands |
packages/prime-agent-runtime/src/rlm/skill.py |
SkillRuntime.execute(), subprocess management |
Forks Python interpreter, manages STDIO protocol |
packages/coding-agent/src/modes/interactive/components/skill-invocation-message.ts |
SkillInvocationMessageComponent |
Renders LLM skill calls in UI |
packages/coding-agent/test/fixtures/skills/python-skill/src/python_skill/__init__.py |
Test fixture | Reference implementation showing expected structure |
Configuration and Environment Setup
Prime Agent respects standard Python environment conventions. For dependency management:
- Create a virtual environment in your skill directory
- Activate it before Prime Agent startup, or
- Specify interpreter path via
PRIME_AGENT_PYTHON_PATHenvironment variable
The getPythonSkillRuntimeInfo() function constructs commands like:
# Conceptual output from source analysis
command = ["python", "-m", skill.python_import]
Override this by providing a python_executable field in advanced skill configurations.
Error Handling and Debugging
Python skills surface errors through the same JSON protocol. Emit error responses as:
json_msg({
"type": "error",
"content": str(exception),
"traceback": traceback.format_exc() # Optional, development only
})
Prime Agent logs subprocess stderr to ~/.prime-agent/logs/skills/<skill-name>/ for inspection when json_msg fails or protocol is violated.
Summary
- Discovery:
loadSkillsFromDir()inskills.tsfinds Python skills viapython_importmetadata - Protocol: Line-delimited JSON over STDIN/STDOUT—no Prime Agent dependencies required
- Runtime:
packages/prime-agent-runtime/src/rlm/skill.pymanages subprocess lifecycle - Flexibility: Any Python library works; the agent treats output identically to native skills
- Deployment: Filesystem-based; drop modules into
~/.prime-agent/skills/
Frequently Asked Questions
What Python version does Prime Agent require for custom skills?
Prime Agent uses the system python executable found in PATH. The source code in skill.py calls python -m <module> without version pinning. Use virtual environments or PRIME_AGENT_PYTHON_PATH to target specific Python 3.x installations.
Can Python skills maintain state between invocations?
No—each <invoke> spawns a fresh subprocess per SkillRuntime.execute() implementation. For persistent state, write to external storage (files, databases) or implement a long-running service that your skill communicates with via HTTP.
How do I debug a Python skill that fails silently?
Check ~/.prime-agent/logs/skills/<skill-name>/stderr for traceback output. Add explicit json_msg({"type": "log", "content": ...}) calls during development, or run your module standalone with echo '{"type":"invoke","args":{}}' | python -m your_module to verify protocol compliance.
Are there performance limits on Python skill execution?
The RLM runtime in skill.py does not implement execution timeouts in the core skill execution path. However, Prime Agent's event system may surface timeouts at higher layers. Heavy computations should stream progress via "type": "log" messages to prevent apparent hangs.
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 →