# How to Structure a Python Project for AI Agents: A Production-Ready Monorepo Architecture

> Structure your Python AI agent project with a production-ready monorepo. Learn how to separate runtime core, AI providers, orchestration, and UIs for modularity and extensibility.

- Repository: [Prime Intellect/prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)
- Tags: architecture
- Published: 2026-08-10

---

**Prime Agent uses a multi-package monorepo that cleanly separates runtime core, AI providers, agent orchestration, and user interfaces while keeping Python-specific components modular and extensible.**

If you're building AI agents in Python, organizing your codebase for maintainability and scalability is critical. This article examines how the Prime Intellect team structures `PrimeIntellect-ai/prime-agent`—a production-grade agent framework—to achieve clean separation of concerns, easy skill development, and provider independence.

## The Monorepo Layer Architecture

Prime Agent organizes code into distinct layers, each with a clear responsibility. This structure prevents tight coupling between LLM providers, agent logic, and presentation layers.

| Layer | Purpose | Location |
|-------|---------|----------|
| **Runtime Core** | Sub-agent execution, skill management, messaging protocol | `prime-agent-runtime/src/rlm/` |
| **AI Provider Layer** | LLM backend abstractions (OpenAI, Anthropic, Bedrock) | `packages/ai/` |
| **Agent Orchestration** | Agent lifecycle, configuration, CLI | `packages/agent/` |
| **Coding Agent** | Python code execution, tool-running sub-agent | `packages/coding-agent/` |
| **Text-User-Interface (TUI)** | Interactive terminal UI | `packages/tui/` |
| **Support Scripts** | Build, release, benchmarking utilities | `scripts/` |

The Python-specific runtime lives in `prime-agent-runtime/`, while TypeScript-based packages share the `packages/` directory. This hybrid approach isolates performance-critical Python code from UI and tooling layers.

## Core Python Runtime: Skills, Messages, and Harnesses

The runtime layer implements the **Remote Call Protocol (RCP)**—the message-passing system that lets sub-agents invoke skills asynchronously. Understanding these three files is essential for extending the framework.

### Skill Registration ([`skill.py`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/skill.py))

In [`prime-agent-runtime/src/rlm/skill.py`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/prime-agent-runtime/src/rlm/skill.py), the `SkillBase` class defines the contract for all capabilities. Skills are self-registering via a decorator pattern.

```python

# prime-agent-runtime/src/rlm/my_skill.py

from .skill import SkillBase, register_skill

class MySkill(SkillBase):
    """Example skill that echoes a message."""
    name = "my-echo"

    async def run(self, input_text: str) -> str:
        return f"Echo: {input_text}"

register_skill(MySkill)

```

The `register_skill` function updates a global registry that the runtime queries at startup. No manual configuration files are required—**discovery is automatic**.

### Test Harness ([`harness.py`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/harness.py))

The `SubAgentHarness` class in [`prime-agent-runtime/src/rlm/harness.py`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/prime-agent-runtime/src/rlm/harness.py) spawns a daemon subprocess and drives message exchange. Use it to test skills in isolation without running the full agent stack.

```python
import json
import asyncio
from prime_agent_runtime.src.rlm.harness import SubAgentHarness

async def demo():
    async with SubAgentHarness() as harness:
        response = await harness.call_skill(
            skill_name="my-echo",
            args={"input_text": "Hello, AI!"}
        )
        print(json.loads(response)["result"])

asyncio.run(demo())

```

The harness handles serialization, daemon lifecycle, and timeout management—**your tests focus on skill logic, not plumbing**.

### Multi-Channel Protocol ([`mcp_base.py`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/mcp_base.py))

For advanced use cases, [`prime-agent-runtime/src/rlm/mcp_base.py`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/prime-agent-runtime/src/rlm/mcp_base.py) provides **Multi-Channel Protocol** utilities. This enables skills to stream partial results, handle interruptions, and manage long-running operations across multiple communication channels.

## AI Provider Abstraction

The `packages/ai/` directory implements provider-agnostic LLM access. According to the codebase, all providers conform to a unified interface exposing a single `stream()` function returning `AssistantMessageEventStream`.

Provider-specific modules live in `packages/ai/src/providers/`. Adding a new LLM backend requires implementing this interface—no changes to agent logic are needed.

```typescript
import { stream } from "prime-agent/packages/ai";

const events = await stream("gpt-4o-mini", {
  prompt: "Explain the difference between a function and a method."
});

for await (const ev of events) {
  if (ev.type === "text") process.stdout.write(ev.text);
}

```

This abstraction ensures **your agents remain provider-agnostic** even as underlying models and APIs evolve.

## Agent Orchestration and CLI

The `packages/agent/` directory handles high-level concerns: agent lifecycle, command-line argument parsing, and provider display naming. The top-level entry point [`prime-agent.sh`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/prime-agent.sh) coordinates daemon startup, agent loading, and optional TUI launch.

```bash

# Start with interactive terminal UI

./prime-agent.sh --tui

# Run headless with specific configuration

./prime-agent.sh --config agents/default.json

```

## Coding Agent: Specialized Sub-Agent for Code Execution

The `packages/coding-agent/` package demonstrates how to build **domain-specific sub-agents**. It includes:

- Skill plug-ins (`websearch`, `attach-image`, etc.)
- Extension scaffolding for adding new tools
- Comprehensive test suites

This pattern—**runtime core + specialized agent packages**—lets you compose complex agent systems without bloating the core.

## Text-User-Interface Layer

The `packages/tui/` package renders rich terminal output: syntax-highlighted code, images, and interactive prompts. It connects to the same Python runtime via the daemon protocol, proving that **UI and business logic separation works in practice**.

## Development Environment Setup

The repository includes helper scripts for reproducible environments. Run [`scripts/setup-kernel-venv.sh`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/scripts/setup-kernel-venv.sh) to create an isolated Python virtual environment for the runtime:

```bash
./scripts/setup-kernel-venv.sh

```

This ensures consistent dependencies across developer machines and CI pipelines.

## Testing Strategy

Each package maintains its own test suite:

- **Python tests**: `prime-agent-runtime/test/` using pytest
- **TypeScript tests**: Vitest suites in relevant `packages/`

Python tests specifically validate skill registry behavior, message serialization, and harness correctness. Run them with:

```bash
cd prime-agent-runtime && pytest test/

```

## Summary

- **Monorepo structure** separates runtime, providers, agents, and UI into independent packages
- **Skill-based architecture** in `prime-agent-runtime/src/rlm/` enables modular capability extension via `SkillBase` subclasses
- **Automatic discovery** through `register_skill()` eliminates manual configuration
- **Harness testing** via `SubAgentHarness` provides fast, isolated skill validation
- **Provider abstraction** in `packages/ai/` ensures LLM backend flexibility
- **Sub-agent specialization** demonstrated by `packages/coding-agent/` shows how to build domain-specific agents

## Frequently Asked Questions

### How do I add a new skill to Prime Agent?

Create a Python file in `prime-agent-runtime/src/rlm/` that subclasses `SkillBase`, implement the `run()` coroutine, and call `register_skill(YourClass)`. The runtime discovers it automatically at startup. Test it with `SubAgentHarness` before integration.

### What is the Remote Call Protocol (RCP)?

RCP is Prime Agent's message-passing system for sub-agent communication. It serializes skill invocations and responses as JSON exchanged with a daemon process. The protocol handles async execution, streaming, and error propagation transparently.

### Can I use Prime Agent with proprietary LLM providers?

Yes. The `packages/ai/` abstraction accepts any provider implementing the streaming interface. Add your provider in `packages/ai/src/providers/` and reference it by name in agent configurations—no core runtime changes required.

### How does the TUI communicate with Python skills?

The TUI connects to the same daemon as CLI mode. It sends user input as RCP messages, receives rendered output streams, and displays them through a virtual terminal. This shared runtime ensures **behavioral parity** between headless and interactive modes.