In the latest post, Prime Agent in SuperQode, we described the first integration over Agent Client Protocol (ACP), compared Prime Agent with RLM Code, and documented the part that Python applications could not yet reach. Prime Agent shipped a TypeScript application host and prime-agent-runtime, a Python package used by code inside its IPython kernel. It did not ship a Python client for the application hosting the agent.
We have now released prime-agent-python-client, an async Python host for Prime Agent's public RPC mode. It starts prime-agent --mode rpc, correlates commands and responses, streams the event feed, handles cancellation and process failure, and exposes session operations through typed Python methods. SuperQode 0.2.82 uses the same package for its prime-agent HarnessSpec backend.
prime-agent-runtime runs inside Prime Agent's kernel. prime-agent-python-client runs in the host application and controls the Prime Agent process. The host can be a CLI, service, notebook, IDE, test runner, or agent harness.
Why we built the Python client
We needed the client for SuperQode. ACP works well for the interactive terminal connection: :prime connect starts Prime Agent as an ACP agent and SuperQode provides the TUI. A HarnessSpec backend must also run headlessly, stream normalized lifecycle events, return usage in a stable result, cancel an active run, and retain native events for analysis. Prime Agent already offered these operations over RPC, so a Python RPC client was the direct integration for SuperQode's Python backend.
We published the client separately because the RPC code is useful outside SuperQode. Python applications can install a small package without bringing in the TUI, provider catalog, policy system, or HarnessSpec implementation.
The Python package does not reimplement Prime Agent. Prime Agent continues to own its prompt, IPython kernel, tools, continual harness, model providers, session store, and recursive sub-agents. TypeScript and Python applications therefore run the same Prime Agent runtime.
The host boundary
Python application or SuperQode HarnessSpec
|
PrimeSession
|
PrimeRpcTransport
|
stdin/stdout: LF-delimited JSON
|
prime-agent --mode rpc
|
IPython kernel, tools and RLM sub-agentsPrimeSession is the application API. It converts construction options into an argument vector, performs a version probe, starts the RPC process, and checks readiness with get_state. PrimeRpcTransport is the lower layer. It writes one JSON object per line to stdin and reads responses and events from stdout. It uses asyncio.create_subprocess_exec, never invokes a shell, and keeps stderr separate from protocol output.
The implementation is dependency-free at runtime and supports Python 3.10 through 3.13. It has explicit compatibility metadata for the Prime Agent releases tested by the package, currently 0.7.0 and 0.7.1. An unknown version does not cause the client to discard data or pretend that an untested combination is verified; applications can inspect session.version, session.compatibility.tested, and session.capabilities.
Framing and correlation
RPC over stdio is simple until requests overlap. Each command receives a unique ID, and the transport keeps a future for that ID until the matching response arrives. A write lock prevents concurrent coroutines from interleaving JSON records, while response correlation allows the commands themselves to remain concurrent. A timeout removes only the affected pending request, so the transport can continue serving later commands.
The wire format is UTF-8 JSON separated by line feed. The reader accepts a trailing carriage return for compatibility, preserves Unicode line-separator characters inside JSON strings, imposes a configurable line-size limit, and turns malformed output into a protocol_error event. An invalid record is observable and does not silently disappear.
Events stay open to protocol evolution
Prime Agent's event schema changes more quickly than its command surface. PrimeEvent provides conveniences such as text_delta and is_terminal and retains the entire wire object in event.raw. Unknown event types and fields pass through unchanged, so applications can read new protocol data before the Python package adds named accessors for it.
Event consumers are independent. Each call to events() receives its own queue, and optional observer callbacks cannot block delivery to other observers. That permits a UI, an audit recorder, and a metrics collector to watch the same process without competing for a single stream.
Process lifecycle, timeout and cancellation
The transport captures a bounded tail of stderr for diagnostics. If Prime Agent exits while requests are pending, each caller receives a PrimeProcessExited error containing the return code and captured diagnostic output. Startup, requests, prompts, and refinement have separate timeout settings. Closing the context manager terminates the owned subprocess and closes event streams; restart() replaces the process and repeats the version and readiness checks.
If the task consuming prompt_stream() is cancelled, or if its deadline expires, the client asks Prime Agent to abort the active run before returning the cancellation or timeout to the caller. The Prime Agent process does not continue editing the repository after its calling coroutine has stopped.
Using the package directly
Install Prime Agent and complete its normal provider setup first. Prime Agent continues to own credentials. Then add the Python host with uv:
uv add "prime-agent-python-client>=0.2.0"The smallest streaming program is:
import asyncio
from prime_agent_client import PrimeSession
async def main() -> None:
async with PrimeSession(
cwd=".",
provider="github-copilot",
model="gpt-4.1",
) as session:
async for event in session.prompt_stream(
"Explain the repository and identify the highest-risk module"
):
if event.text_delta:
print(event.text_delta, end="", flush=True)
stats = await session.stats()
print(f"\n{stats}")
asyncio.run(main())Save the program as prime_agent_example.py and run it with uv run prime_agent_example.py. Prime Agent works in the directory passed through cwd and streams text as the run progresses.
The session can use Prime Agent's default provider and model, or receive explicit provider and model values. It also accepts a working directory, session directory, resume path, continuation flag, environment overrides, command argument sequence, persistence choice, timeouts, and a logger. These are launch and host settings; they do not copy authentication into the Python process.
The complete session surface
prompt() prompt_stream() prompt_and_wait()
steer() follow_up() abort()
state() messages() stats()
last_assistant_text() available_models() set_model()
new() switch_session() set_session_name()
fork() clone() compact()
refine() request()prompt() acknowledges that Prime Agent accepted a prompt. prompt_stream() combines that command with the event lifecycle and stops at agent_end. prompt_and_wait() collects the same events when a list is more convenient. steer() changes an active run, while follow_up() queues the next instruction. State, messages, usage, last assistant text, model discovery, compaction, refinement, and session-tree operations are all available without reaching into transport internals.
The lower-level request() method remains public. When Prime Agent adds an RPC command, a Python application can use it immediately and retain the raw response before the package adds a named convenience method.
Extension UI requests without a TypeScript host
Prime Agent extensions can ask their host to select an item, confirm an action, collect input, or open an editor. A headless Python process must answer those requests or cancel them explicitly. PrimeSession accepts a synchronous or asynchronous ui_handler and converts its result into the matching extension_ui_response.
import asyncio
from prime_agent_client import PrimeSession
async def answer_ui(event):
if event.get("method") == "confirm":
return True
if event.get("method") in {"input", "editor"}:
return "response from the Python host"
return None
async def main() -> None:
async with PrimeSession(ui_handler=answer_ui) as session:
await session.prompt_and_wait("Run the task")
asyncio.run(main())A mapping supplies the complete response payload. A boolean answers a confirmation, a string supplies an input value, and None cancels the request. Terminal applications and web services can connect this handler to their existing input components.
How SuperQode uses the client
SuperQode now has two Prime Agent routes. The existing ACP route drives the interactive :prime command surface in the TUI. The RPC route is a HarnessSpec backend for repeatable, programmatic runs. Both launch the official Prime Agent executable and use Prime Agent's agent loop.
Create prime-agent.yaml in the repository Prime Agent should work on:
name: prime-agent-coder
inherits: coding
runtime:
backend: prime-agent
config:
prime_agent:
persist_session: true
session_dir: .superqode/prime-agent/sessions
request_timeout: 30
startup_timeout: 30
prompt_timeout: 900
check_version: true
model_policy:
primary: github-copilot/gpt-4.1Install and run the published SuperQode package with uv:
uv tool install "superqode>=0.2.82"
superqode harness doctor --spec prime-agent.yaml --json
superqode harness run \
--spec prime-agent.yaml \
--prompt "Explain the repository and identify the highest-risk module" \
--provider github-copilot \
--model gpt-4.1 \
--streamharness doctor checks the specification and executable before the run. Normal output prints the completed answer, --stream emits model deltas as they arrive, and --json returns the normalized harness result for another program. All three modes use the same Python-hosted RPC backend.
Normalizing events without losing Prime data
The backend maps known Prime events into SuperQode's harness vocabulary. Text and thinking updates become model_delta and thinking_delta. Tool start, update, and end records become tool_call, tool_update, and tool_result. Agent and turn boundaries become lifecycle events. Session statistics become a usage event and populate input tokens, output tokens, total tokens, and cost in the final AgentResponse.
Every normalized event also includes the complete Prime object under prime_event, including fields that SuperQode does not interpret. Unrecognized event types are emitted as prime_event. Debuggers and recorders can use the original event, while TUI and automation code use the normalized type.
Security and backend capabilities
Prime Agent executes its IPython kernel, shell operations, files, and sub-agents with the permissions of the process that started it. The Python RPC client provides transport and lifecycle management; it does not sandbox execution. SuperQode reports supports_sandbox: false and supports_approvals: false for this backend.
The first ACP integration could not obtain complete session statistics or invoke every session operation exposed by RPC. The native backend adds those operations for programmatic runs. ACP remains available for interactive, editor-style sessions.
What we tested
The client test suite uses a deterministic fake RPC subprocess rather than mocks around the transport. It checks concurrent response correlation, restart, readiness probing, malformed records, unknown events, Unicode separators, command errors, timeouts, cancellation, process death, bounded stderr capture, tool lifecycle ordering, UI responses, and structured logging. Package CI runs lint, format, type checking, tests, wheel and source builds, and installation smoke tests across supported Python versions.
SuperQode tests the integration at the backend boundary. The suite launches the same fake RPC fixture through PrimeSession, verifies registry and configuration behaviour, checks event normalization and raw payload preservation, and asserts the final token and cost accounting. The released package was also exercised through SuperQode 0.2.82 from PyPI, using the dependency and runtime path installed by users.
Why this is a separate package
The package began as part of the SuperQode integration. Keeping it in an independent repository gives Python applications a focused, dependency-free RPC package. SuperQode declares a compatible 0.2.x range and uses it as a normal dependency.
Protocol compatibility, framing, and process lifecycle are maintained in the client repository. Harness event mapping, CLI output, HarnessSpec configuration, and SuperQode policy stay in SuperQode. RPC fixes can therefore be released for other Python hosts without changing SuperQode.
What comes next
The immediate work is compatibility tracking as Prime Agent's RPC surface evolves. New released versions will be tested explicitly, new commands will receive convenience methods where they improve the Python API, and raw event preservation will remain the fallback for additions that arrive between client releases. Real-process tests will continue to complement the deterministic protocol suite.
The next RLM Code release can also consume this client. RLM Code and Prime Agent have different execution models: RLM Code provides bounded, sandboxed recursive computation and measurable trajectories; Prime Agent provides persistent sessions, a continual harness, and live recursive agents. The Python host makes it possible to add an optional Prime Agent runtime while retaining RLM Code's trajectory and evidence model and recording the raw Prime event stream.
SuperQode will remain the richer interactive surface. RLM Code's CLI and TUI are smaller, so the planned integration will focus on its runtime, trajectory, and evaluation features rather than duplicating the SuperQode terminal application.
Install and source
The package is available from PyPI, and the source, architecture notes, compatibility policy, and examples are in the prime-agent-python-client repository. The native SuperQode backend is documented in the Prime Agent Python client guide.
prime-agent-python-client is maintained by Superagentic AI. It is not an official Prime Intellect product and is not endorsed by Prime Intellect. Prime Agent remains a separate installation and is governed by its own project and provider terms.

