# How Prime Agent Integrates the IPython Kernel for Stateful Code Execution

> Discover how Prime Agent integrates the IPython kernel for stateful code execution. Explore its three-layer architecture: tool definition, provisioner, and terminal UI.

- Repository: [Prime Intellect/prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)
- Tags: how-to-guide
- Published: 2026-08-15

---

**Prime Agent integrates a persistent IPython kernel through a three-layer architecture: a tool definition that exposes notebook cells to the model, a provisioner that manages kernel lifecycle and state persistence, and a terminal UI component that renders rich output.**

The integration turns Prime Agent into a long-lived **RLM (Reasoning & Learning Machine)**—a Python environment where variables, imports, and async tasks survive across multiple agent turns. This implementation lives in the `PrimeIntellect-ai/prime-agent` repository and powers the agent's ability to execute Python, run shell commands via `%%bash` magic, and maintain computational state.

## Core Architecture: Three Integration Layers

The IPython integration is split across three coordinated systems:

| Layer | Responsibility | Primary Source File |
|-------|--------------|---------------------|
| **Tool Definition** | Registers the `ipython` tool, handles execution flow, error recovery, and result packaging | [[`packages/coding-agent/src/core/tools/ipython.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/tools/ipython.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/tools/ipython.ts) |
| **Kernel Provisioner** | Lazily creates, starts, restores, and disposes `KernelManager` instances per session | [[`packages/coding-agent/src/core/tools/ipython.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/tools/ipython.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/tools/ipython.ts) (class `IpythonKernelProvisioner`) |
| **UI Component** | Renders cells with streaming output, image attachments, diffs, and status indicators | [[`packages/coding-agent/src/modes/interactive/components/ipython-cell.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/interactive/components/ipython-cell.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/interactive/components/ipython-cell.ts) |

## Kernel Lifecycle and Bootstrap Process

### Lazy Initialization with `ensure()`

The `IpythonKernelProvisioner` class guarantees exactly one kernel per agent session. The first tool invocation triggers `ensure()`, which:

1. **Spawns** a `KernelManager` from [[`packages/coding-agent/src/kernel/index.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/kernel/index.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/kernel/index.ts)
2. **Restores state** from `snapshotDir` if configured (via `restoreState()`)
3. **Executes bootstrap code** to configure the environment

### Bootstrap Code Injection

The kernel receives `RLM_BOOTSTRAP_BASE_CODE` (lines 24–38 in [`ipython.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/ipython.ts)) on every fresh start:

```python

# Simplified representation of RLM_BOOTSTRAP_BASE_CODE

import nest_asyncio
nest_asyncio.apply()  # Enable nested event loops

# Disable colored output for clean TUI rendering

%colors NoColor

# Attempt to import the RLM runtime

try:
    import rlm
except ImportError:
    pass

```

For sessions with custom **Python skills**, `buildRlmBootstrapCode` (lines 70–84) extends this base with dynamic imports:

```typescript
// From packages/coding-agent/src/core/tools/ipython.ts
function buildRlmBootstrapCode(skills: PythonSkill[]): string {
  const imports = skills.map(s => `import ${s.module}`).join('\n');
  return `${RLM_BOOTSTRAP_BASE_CODE}\n${imports}\n${RLM_RUNTIME_CODE}`;
}

```

## Execution Flow: From Model Request to Result

### Step 1: Tool Registration

```typescript
// Register the ipython tool at agent initialization
import { createIpythonTool } from "@prime-agent/coding-agent";

const ipythonTool = createIpythonTool(process.cwd(), {
  python: "python3",                           // Custom interpreter path
  snapshotDir: "~/.prime/agent/ipython",       // Persist namespace across restarts
  skills: [{ module: "pandas" }, { module: "numpy" }]  // Auto-import skills
});

agent.registerTool(ipythonTool);

```

### Step 2: Model Invocation

When the model requests code execution:

```typescript
// Automatic invocation when model calls tool
await agent.invokeTool("ipython", { 
  code: "import numpy as np; np.arange(5).tolist()" 
});

```

### Step 3: Shell Magic Transformation

For `%%bash` cells, `applyShellSettingsToBashMagicCell` (lines 99–119) rewrites the source:

```typescript
// Before: %%bash\necho $HOME
// After:  %%bash\nexport HOME=/explicit/path; echo $HOME
const transformed = applyShellSettingsToBashMagicCell(rawCode, {
  shellCmd: "/bin/bash",
  env: { PATH: "/usr/local/bin" }
});

```

### Step 4: Kernel Execution with Busy-Handling

The `executeWithBusyKernelChoice` function handles concurrent execution attempts:

- **Wait**: Queue until prior cell completes
- **Kill**: Restart kernel, losing state but freeing executor
- **Cancel**: Abort without execution

Killing inserts `KERNEL_RESTART_NOTICE` into output to alert the model.

### Step 5: Result Packaging

`createIpythonToolDefinition` assembles a `ToolResult` containing:

```typescript
interface ToolResult {
  content: Array<TextContent | ImageContent>;  // stdout + images
  isError: boolean;                            // Execution status
  details: {
    executionTimeMs: number;
    diff?: string;                             // File modifications
    attachments: Map<string, Buffer>;          // Generated images
  };
}

```

Image extraction uses `IMAGE_MIME_TYPES` from [[`packages/coding-agent/src/utils/mime.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/utils/mime.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/utils/mime.ts):

```typescript
const IMAGE_MIME_TYPES = [
  'image/png',
  'image/jpeg',
  'image/svg+xml',
  'image/gif'
];

```

## State Persistence and Recovery

### Snapshot Directory Structure

When `snapshotDir` is provided:

```

~/.prime/agent/ipython/
├── namespace.pickle          # Serialized globals

├── history.jsonl             # Execution history

└── attachments/              # Saved plots/images

    ├── plot_001.png
    └── chart_002.svg

```

### Restore on Boot

```typescript
// Inside IpythonKernelProvisioner.ensure()
if (this.snapshotDir && fs.existsSync(this.snapshotDir)) {
  await this.kernelManager.restoreState(this.snapshotDir);
  reportStartupProgress({ phase: 'restored', elapsedMs: Date.now() - start });
}

```

This enables **long-running computational sessions**—a data analysis pipeline can survive agent restarts with dataframes and trained models intact.

## Terminal UI Rendering

The `IPythonCellComponent` transforms kernel output into rich terminal displays:

```tsx
// Simplified usage from ipython-cell.ts
import { IPythonCellComponent } from "./ipython-cell";

const component = new IPythonCellComponent({
  code: codeString,
  result: toolResult,
  executionStarted: timestamp,
  isPartial: false,  // True for streaming output
  diff: fileDiff,    // Optional file change visualization
});

const lines = component.render(terminalWidth);
// Returns formatted lines with ANSI styling, image placeholders, status icons

```

Key rendering features:

- **Streaming output**: Real-time stdout/stderr updates via `isPartial`
- **Image display**: Terminal-compatible representations (sixel, kitty graphics, or placeholders)
- **Diff blocks**: Side-by-side or inline file modifications
- **Status icons**: ⏳ running, ✅ completed, 🔄 restarted, ❌ error

## Key Source Files Reference

| File | Lines of Interest | Purpose |
|------|-------------------|---------|
| [`packages/coding-agent/src/core/tools/ipython.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/tools/ipython.ts) | 1–400+ | Tool definition, provisioner, bootstrap, execution |
| [`packages/coding-agent/src/core/tools/ipython-cell-code.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/tools/ipython-cell-code.ts) | parse functions | `%%bash` magic parsing |
| [`packages/coding-agent/src/kernel/index.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/kernel/index.ts) | KernelManager class | ZMQ process management, `execute()`, `listNamespaceNames()` |
| [`packages/coding-agent/src/utils/mime.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/utils/mime.ts) | IMAGE_MIME_TYPES | Output type filtering |
| [`packages/coding-agent/src/modes/interactive/components/ipython-cell.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/interactive/components/ipython-cell.ts) | Render methods | TUI component implementation |

## Summary

- **Prime Agent's IPython kernel integration** centers on `createIpythonToolDefinition` in [`ipython.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/ipython.ts), which bridges the model's tool calls to a persistent notebook environment.
- **The `IpythonKernelProvisioner`** handles lazy boot, state restore from `snapshotDir`, and graceful degradation when kernels hang or crash.
- **Bootstrap code injection** (`RLM_BOOTSTRAP_BASE_CODE` + `buildRlmBootstrapCode`) prepares a reproducible execution environment with `nest_asyncio`, disabled colors, and requested skill imports.
- **Shell magic rewriting** ensures `%%bash` cells execute with consistent environment settings.
- **Rich terminal output** via `IPythonCellComponent` delivers images, diffs, and streaming execution status to the user.

## Frequently Asked Questions

### How does Prime Agent handle kernel crashes during execution?

The `executeWithBusyKernelChoice` function detects unresponsive kernels and presents three options: wait for completion, force-kill and restart, or cancel the request. Killing triggers `KERNEL_RESTART_NOTICE` insertion so the model understands state was reset. The provisioner then spawns a fresh `KernelManager` instance.

### Can the IPython kernel persist variables between agent sessions?

Yes. When `snapshotDir` is configured, the provisioner calls `restoreState()` on boot to reload pickled namespace data. Variables, imports, and defined functions survive agent restarts. The bootstrap code re-executes after restoration to ensure environment consistency.

### What image formats does Prime Agent support from kernel output?

According to [[`packages/coding-agent/src/utils/mime.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/utils/mime.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/utils/mime.ts), the system recognizes PNG, JPEG, SVG, and GIF attachments. These are extracted from kernel messages and rendered in the terminal UI via `imageBlocksFromAttachments` in the tool result handler.

### How does Prime Agent prevent kernel state pollution between unrelated tasks?

Each agent session receives exactly one `KernelManager` via the provisioner's singleton pattern. For complete isolation, users can configure separate `snapshotDir` paths per workflow or omit persistence entirely. The busy-kernel handler also allows intentional state reset through kernel restart when execution context drifts.