Engine Client API

Complete reference for the EngineClient interface that all QuantumReef engines implement. Use this reference when building custom engine adapters or when integrating QuantumReef's engine layer into your own tooling.

Overview

The EngineClient interface is the contract between QuantumReef's UI layer and individual engine adapters. It is defined in TypeScript and implemented once per engine. Every method is async; the interface is designed to support both HTTP-based engines (like OpenCode) and subprocess-based engines (like Claude Code and Aider).

typescript
import type { EngineClient } from "@quantumreef/engine-client";

global.health()

Returns the health status of the engine process.

typescript
health(): Promise<HealthStatus>

interface HealthStatus {
  ok: boolean;        // true if the engine is reachable and responsive
  latencyMs: number;  // round-trip time in milliseconds
  error?: string;     // present only when ok is false
}

Example

typescript
const status = await client.health();
if (!status.ok) {
  console.error("Engine unavailable:", status.error);
}

session.list()

Returns all sessions managed by the engine, ordered by updatedAt descending.

typescript
session.list(): Promise<Session[]>

interface Session {
  id: string;
  title: string;
  engineId: string;
  createdAt: number;         // Unix milliseconds
  updatedAt: number;
  status: "idle" | "running" | "completed" | "error";
  model?: string;
  workingDirectory?: string;
  starred?: boolean;
  archived?: boolean;
}

Example

typescript
const sessions = await client.session.list();
const active = sessions.filter(s => s.status === "running");

session.create()

Creates a new session and returns it.

typescript
session.create(opts: CreateSessionOpts): Promise<Session>

interface CreateSessionOpts {
  title?: string;              // Human-readable session name
  model?: string;              // Override the engine's default model
  workingDirectory?: string;   // Filesystem root for this session
  systemPrompt?: string;       // Injected as the first system message
}

Example

typescript
const session = await client.session.create({
  title: "Refactor auth module",
  workingDirectory: "/home/user/my-project",
  model: "claude-opus-4-5",
});
console.log("Created session:", session.id);

session.get()

Fetches a single session by ID.

typescript
session.get(id: string): Promise<Session>

Example

typescript
const session = await client.session.get("sess_01abc");
console.log(session.status); // "idle"

session.messages()

Returns the full message history for a session, ordered chronologically.

typescript
session.messages(id: string): Promise<Message[]>

interface Message {
  id: string;
  sessionId: string;
  role: "user" | "assistant" | "tool";
  content: MessageContent;
  createdAt: number;
  toolCalls?: ToolCall[];
  toolResults?: ToolResult[];
}

interface MessageContent {
  type: "text" | "image" | "file";
  text?: string;
  url?: string;
  mimeType?: string;
}

session.prompt()

Sends a user prompt to a session and returns an AsyncIterable of streaming events. This is the primary method for interacting with an engine.

typescript
session.prompt(
  id: string,
  prompt: string,
  opts?: PromptOpts
): Promise<AsyncIterable<MessageEvent>>

interface PromptOpts {
  model?: string;
  maxTokens?: number;
  temperature?: number;
}

type MessageEvent =
  | { type: "text_delta";       delta: string }
  | { type: "tool_call_start";  toolCall: ToolCall }
  | { type: "tool_call_result"; toolCallId: string; result: unknown }
  | { type: "message_done";     message: Message }
  | { type: "error";            error: string };

Example — streaming to console

typescript
const stream = await client.session.prompt(
  session.id,
  "Add input validation to the login form"
);

for await (const event of stream) {
  if (event.type === "text_delta") {
    process.stdout.write(event.delta);
  } else if (event.type === "tool_call_start") {
    console.log("\nTool:", event.toolCall.name, event.toolCall.input);
  } else if (event.type === "message_done") {
    console.log("\nDone.");
  } else if (event.type === "error") {
    console.error("Error:", event.error);
  }
}

session.abort()

Aborts a running session. Pending tool calls are cancelled. The session status becomes idle.

typescript
session.abort(id: string): Promise<void>

Example

typescript
// Abort after 30 seconds
const timer = setTimeout(() => client.session.abort(session.id), 30_000);
for await (const event of stream) { /* ... */ }
clearTimeout(timer);

session.summarize()

Requests a text summary of the session's conversation history. Used internally by QuantumReef for context handoff during engine switching.

typescript
session.summarize(id: string): Promise<string>

message.create()

Creates a message in a session without triggering an AI response. Useful for injecting context, notes, or tool results manually.

typescript
message.create(
  sessionId: string,
  content: MessageContent
): Promise<Message>

Example

typescript
await client.message.create(session.id, {
  type: "text",
  text: "Context note: the team uses pnpm, not npm.",
});

events.subscribe()

Subscribes to the engine's global event bus. Returns an unsubscribe function. Events fire for all sessions managed by the engine process.

typescript
events.subscribe(
  handler: (event: EngineEvent) => void
): Unsubscribe

type EngineEvent =
  | { type: "session_created";       session: Session }
  | { type: "session_updated";       session: Session }
  | { type: "message_created";       message: Message }
  | { type: "permission_requested";
      permissionId: string;
      description: string;
      sessionId: string };

type Unsubscribe = () => void;

Example

typescript
const unsubscribe = client.events.subscribe((event) => {
  if (event.type === "permission_requested") {
    console.log("Permission needed:", event.description);
    client.permissions.reply(event.permissionId, "allow");
  }
});

// Later, clean up
unsubscribe();

permissions.reply()

Responds to a pending permission request from the engine.

typescript
permissions.reply(
  permissionId: string,
  decision: PermissionDecision
): Promise<void>

type PermissionDecision = "allow" | "deny" | "allow_session";
// "allow_session" approves this and all future identical requests in the session

Error Handling

All methods throw a typed EngineError on failure:

typescript
class EngineError extends Error {
  code: EngineErrorCode;
  engineId: string;
  sessionId?: string;
}

type EngineErrorCode =
  | "ENGINE_UNAVAILABLE"    // health check failed
  | "SESSION_NOT_FOUND"     // invalid session ID
  | "SESSION_RUNNING"       // tried to create while another runs (some engines)
  | "PROMPT_ABORTED"        // session.abort() was called mid-stream
  | "PERMISSION_DENIED"     // tool call was denied
  | "RATE_LIMITED"          // engine or provider rate limit hit
  | "CONTEXT_OVERFLOW"      // prompt exceeds model context window
  | "UNKNOWN";

Retry on RATE_LIMITED

Implement exponential backoff when catching RATE_LIMITED errors. QuantumReef's built-in retry logic handles this automatically for sessions initiated from the UI, but custom integrations should handle it explicitly.