# How Python-Backed Skills Use Typed Host Requests in Prime Agent

> Learn how Python-backed skills in Prime Agent use typed host requests. Discover the communication process between Python skills and the TypeScript host runtime for efficient data exchange and routing.

- Repository: [Prime Intellect/prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)
- Tags: deep-dive
- Published: 2026-09-05

---

**Python-backed skills in Prime Agent communicate with the TypeScript host runtime by calling `rlm.host_request()` with a type string and JSON-serializable payload, which the kernel routes through the typed `HostRequestHandlers` map defined in [`packages/coding-agent/src/core/kernel/shared.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/kernel/shared.ts).**

The Prime Agent framework allows developers to write skills in Python while leveraging host-side services like web search, file system access, and sub-agent spawning. This integration relies on a strictly typed host request protocol that bridges the IPython REPL environment with the JavaScript kernel.

## Understanding the Typed Host Request Architecture

The architecture separates concerns between the Python execution environment and the host runtime. Python skills request capabilities through typed messages, while the host implements handlers that fulfill these requests asynchronously.

### The Host Request Type System

At the core of this system is the type definition found in [`packages/coding-agent/src/core/kernel/shared.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/kernel/shared.ts). This file establishes the contract between Python skills and the host runtime:

```typescript
// packages/coding-agent/src/core/kernel/shared.ts
export type HostRequestHandler = (
  payload: Record<string, unknown>
) => Promise<Record<string, unknown>>;

export type HostRequestHandlers = Record<string, HostRequestHandler>;

```

The **HostRequestHandler** type defines a function that accepts a `Record<string, unknown>` payload and returns a promise resolving to another record. This loose typing on the host side allows for dynamic request routing while maintaining type safety through the dispatcher pattern.

The **HostRequestHandlers** type creates a registry map where keys are the request type strings (such as `"websearch.query"` or `"http.fetch"`) and values are the corresponding handler implementations.

### The Python Bridge

The IPython bridge in [`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) exposes the `rlm` module to Python skills. This module provides the `host_request` function that serializes Python dictionaries into JSON payloads and dispatches them across the language boundary:

```python

# Inside a Python-backed skill

import rlm

async def fetch_data():
    result = await rlm.host_request(
        "http.fetch", 
        {"url": "https://api.example.com/data"}
    )
    return result

```

The bridge ensures that all payloads remain JSON-serializable, preserving type information as dictionaries on both sides of the communication channel.

## Implementing Typed Host Requests in Python Skills

Python skills initiate host requests by importing the `rlm` module and awaiting the `host_request` coroutine. The function signature requires two parameters: the request type string and the payload dictionary.

### Basic Request Pattern

When a skill needs to perform a web search, it issues a typed request like this:

```python

# skills/websearch_example.py

import rlm

async def search_primes(query: str):
    # Typed host request with specific request type

    response = await rlm.host_request(
        "websearch.query",
        {"query": query, "max_results": 10}
    )
    
    # Response is a Python dict matching the handler's return type

    return response.get("results", [])

```

The first argument `"websearch.query"` serves as the lookup key in the host's `HostRequestHandlers` registry. The second argument must be a dictionary that serializes to valid JSON, matching the expected schema for that specific request type.

### Sub-Agent Creation Requests

Skills can also request the host to spawn sub-agents through typed requests:

```python

# skills/orchestrator.py

import rlm

async def create_worker(model: str):
    reply = await rlm.host_request(
        "subagent.spawn",
        {"name": "worker", "model": model, "timeout": 300}
    )
    
    # Typed response contains agent identifier

    return reply["agentId"]

```

The payload structure varies by request type, but all follow the same pattern: a string key identifying the capability and a dictionary containing the parameters.

## Registering Handlers on the Host Side

On the TypeScript side, developers register handlers by populating the `HostRequestHandlers` map. Each entry connects a request type string to an async function that implements the requested functionality.

### Handler Registration Example

Consider the implementation of an HTTP fetch handler:

```typescript
// packages/coding-agent/src/core/tools/http.ts
import { HostRequestHandlers } from "../kernel/shared";

export const httpHandlers: HostRequestHandlers = {
  "http.fetch": async ({ url, method = "GET" }) => {
    const response = await fetch(url as string, { 
      method: method as string 
    });
    const body = await response.text();
    
    return { 
      status: response.status, 
      body,
      headers: Object.fromEntries(response.headers)
    };
  },
};

```

The handler receives the payload as `Record<string, unknown>` and must return a `Promise<Record<string, unknown>>`. The kernel automatically serializes this return value back to Python as a dictionary.

### Integrating Handlers into the Kernel

Handlers are aggregated into a single registry during kernel initialization:

```typescript
// packages/coding-agent/src/core/kernel/index.ts
import { httpHandlers } from "../tools/http";
import { websearchHandlers } from "../tools/websearch";

const hostHandlers: HostRequestHandlers = {
  ...httpHandlers,
  ...websearchHandlers,
  // Additional handlers merged here
};

```

This centralized registration allows the dispatch mechanism to route incoming requests from Python skills to the appropriate TypeScript implementation.

## Request Flow and Data Flow

The execution flow follows a strict async request-response pattern across the language boundary:

1. **Request Initiation**: The Python skill calls `await rlm.host_request("type", payload)`
2. **Serialization**: The IPython bridge serializes the payload to JSON and emits a `host_request` event
3. **Dispatch**: The kernel receives the event, extracts the request type, and looks up the handler in the `HostRequestHandlers` map in [`shared.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/shared.ts)
4. **Execution**: The matched handler executes with the deserialized payload
5. **Response**: The handler returns a promise that resolves to a record
6. **Reply**: The kernel emits a `host_reply` event containing the result
7. **Deserialization**: The bridge converts the response back to a Python dictionary
8. **Resolution**: The original `rlm.host_request()` call returns the dictionary to the skill

This flow ensures that Python skills remain agnostic to the implementation details of host services while maintaining type contracts through the `Record<string, unknown>` interfaces.

## Summary

- **Type Safety**: The `HostRequestHandlers` map in [`packages/coding-agent/src/core/kernel/shared.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/kernel/shared.ts) provides a typed registry for routing requests from Python to TypeScript.
- **Python API**: Skills use `rlm.host_request(type, payload)` where the type string identifies the handler and the payload is a JSON-serializable dictionary.
- **Async Communication**: All host requests are asynchronous, returning promises on the TypeScript side and coroutines on the Python side.
- **Handler Pattern**: Host-side implementations follow the `HostRequestHandler` type signature, accepting `Record<string, unknown>` and returning `Promise<Record<string, unknown>>`.
- **Bridge Implementation**: The IPython bridge in [`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) manages serialization and event transmission between the Python REPL and the JavaScript kernel.

## Frequently Asked Questions

### What happens if a Python skill requests an unregistered host request type?

If the `rlm.host_request()` call specifies a type string that does not exist in the `HostRequestHandlers` map, the kernel will fail to find a matching handler and return an error response to the Python skill. The skill should handle this case by catching exceptions or checking for error keys in the response dictionary.

### Can Python skills pass complex objects like NumPy arrays through host requests?

No, payloads must be JSON-serializable. Complex objects like NumPy arrays, Pandas DataFrames, or custom class instances cannot pass directly through `rlm.host_request()`. Skills should convert such objects to primitive types (lists, dictionaries, strings) before making the request, or use alternative data sharing mechanisms provided by the framework.

### How does the host handle concurrent requests from multiple Python skills?

The host request system is fully asynchronous. Each request from Python generates a unique event that the kernel processes independently. TypeScript handlers defined in the `HostRequestHandlers` map can execute concurrently using standard JavaScript async patterns, and the bridge ensures that responses are routed back to the correct awaiting Python coroutine without blocking the IPython REPL.