@rkat/sdk
v0.6.20
Published
TypeScript SDK for Meerkat agent runtime
Downloads
2,368
Readme
Meerkat TypeScript SDK
TypeScript client for the Meerkat runtime. The SDK is a thin session-first wrapper over the same runtime-backed contracts used by the CLI, REST, JSON-RPC, and MCP surfaces. It communicates with a local rkat-rpc subprocess over JSON-RPC 2.0 (newline-delimited JSON on stdin/stdout).
Current contract version: 0.6.3.
Installation
npm install @rkat/sdkPrerequisites
rkat-rpcbinary on PATH -- build it from the Meerkat repo withcargo build -p meerkat-rpc, then ensure the resultingrkat-rpcbinary is in your$PATH.- Node.js >= 18 (uses
node:child_process,node:readline,node:test). - API key for at least one LLM provider set in your environment (e.g.
ANTHROPIC_API_KEY,OPENAI_API_KEY, orGOOGLE_API_KEY).
tsconfig Requirements
The SDK is published as ESM ("type": "module" in package.json). Your project's tsconfig.json must use Node16 module resolution:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"lib": ["ES2022"],
"strict": true,
"esModuleInterop": true
}
}Quick Start
import { MeerkatClient } from "@rkat/sdk";
const client = new MeerkatClient();
// Connect spawns `rkat-rpc`, performs the initialize handshake,
// and fetches runtime capabilities.
await client.connect();
// Create a session (runs the first turn immediately).
const session = await client.createSession("What is the capital of Sweden?");
console.log(session.text); // "Stockholm..."
console.log(session.id); // UUID of the new session
console.log(session.usage); // { inputTokens, outputTokens, ... }
// Multi-turn: send a follow-up in the same session.
const followUp = await session.turn("And what is its population?");
console.log(followUp.text);
// Clean up.
await session.archive();
await client.close();API Reference: MeerkatClient
Constructor
new MeerkatClient(rkatPath?: string)| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| rkatPath | string | "rkat-rpc" | Path to the RPC binary. |
connect()
async connect(options?: ConnectOptions): Promise<this>Spawns rkat-rpc as a child process, performs the initialize handshake, checks contract version compatibility, and fetches runtime capabilities via capabilities/get. Returns this for chaining.
Pass { liveWs: true } only for live-adapter flows that need live/*; it requires a configured live provider.
Throws MeerkatError with code "VERSION_MISMATCH" if the server's contract version is incompatible with the SDK's CONTRACT_VERSION.
close()
async close(): Promise<void>Kills the rkat-rpc subprocess and cleans up resources.
createSession(prompt, options?)
async createSession(
prompt: string | ContentBlock[],
options?: SessionOptions,
): Promise<Session>Creates a new session and immediately runs the first turn with the given prompt. Returns a runtime-backed Session wrapper whose lastResult tracks the latest RunResult and whose methods (turn, stream, history, archive) stay aligned with canonical backend semantics.
Parameters:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| prompt | string \| ContentBlock[] | (required) | The user prompt for the first turn. |
| options.model | string | Server default (typically claude-sonnet-4-5) | LLM model name (e.g. "gpt-5.2", "gemini-3.5-flash", "claude-opus-4-6"). |
| options.provider | string | Resolved from the model registry | Force a specific provider ("anthropic", "openai", "gemini"). |
| options.systemPrompt | string | undefined | Override the default system prompt. |
| options.maxTokens | number | undefined | Maximum output tokens for the LLM response. |
| options.outputSchema | Record<string, unknown> | undefined | JSON Schema for structured output extraction. |
| options.structuredOutputRetries | number | 2 (server default) | Max retries for structured output validation. |
| options.hooksOverride | Record<string, unknown> | undefined | Run-scoped hook overrides. |
| options.enableBuiltins | boolean | false | Enable built-in tools (task management, etc.). |
| options.enableShell | boolean | false | Enable the shell tool (requires enableBuiltins). |
| options.enableMemory | boolean | false | Enable semantic memory (memory_search tool + compaction indexing). |
| options.enableMob | boolean | false | Enable mob orchestration helpers. |
| options.keepAlive | boolean | false | Run in keep-alive mode for inter-agent comms. |
| options.commsName | string | undefined | Agent name for comms (required when keepAlive is true). |
| options.peerMeta | Record<string, unknown> | undefined | Metadata advertised to peer comms surfaces. |
| options.budgetLimits | Record<string, unknown> | undefined | Runtime budget limits for the session. |
| options.providerParams | Record<string, unknown> | undefined | Provider-specific parameters (e.g. thinking config). |
| options.preloadSkills | string[] | undefined | Skill source UUIDs to load before the run. |
| options.skillRefs | SkillRef[] | undefined | Canonical structured skill references. |
| options.skillReferences | string[] | undefined | Legacy string skill references; prefer skillRefs. |
| options.labels | Record<string, string> | undefined | Session labels used for filtering and metadata. |
| options.additionalInstructions | string[] | undefined | Extra instruction blocks appended to the system prompt. |
| options.appContext | unknown | undefined | Opaque app context passed to custom builders. |
| options.shellEnv | Record<string, string> | undefined | Per-session shell environment variables. |
| options.externalTools | Record<string, unknown>[] | undefined | Inline callback tool definitions for this session. |
createDeferredSession(prompt, options?)
async createDeferredSession(
prompt: string | ContentBlock[],
options?: SessionOptions,
): Promise<DeferredSession>Creates a session identity without running the first turn yet. Use await deferred.startTurn(...) when you want the first runtime-backed turn to happen later.
listSessions()
async listSessions(options?: {
labels?: Record<string, string>;
limit?: number;
offset?: number;
}): Promise<SessionInfo[]>Returns an array of typed SessionInfo objects with camelCase fields such as sessionId, sessionRef, messageCount, isActive, and labels.
readSession(sessionId)
async readSession(sessionId: string): Promise<SessionInfo>Returns typed session details including model, provider, lastAssistantText, and labels.
Session ingress helpers
async sendExternalEvent(sessionId: string, payload: unknown, options?: { source?: string }): Promise<Record<string, unknown>>
async injectContext(sessionId: string, text: string, options?: { source?: string; idempotencyKey?: string }): Promise<{ status: string }>These expose session/external_event and session/inject_context as first-class public APIs.
Schedules, Models, and Mob profile APIs
async getModelsCatalog(): Promise<ModelsCatalog>
async createSchedule(request: CreateScheduleRequest): Promise<Schedule>
async getSchedule(scheduleId: string): Promise<Schedule>
async listSchedules(options?: ScheduleListOptions): Promise<Schedule[]>
async updateSchedule(request: UpdateScheduleRequest): Promise<Schedule>
async pauseSchedule(scheduleId: string): Promise<Schedule>
async resumeSchedule(scheduleId: string): Promise<Schedule>
async deleteSchedule(scheduleId: string): Promise<Schedule>
async listScheduleOccurrences(scheduleId: string, options?: ScheduleOccurrencesOptions): Promise<ScheduleOccurrencesResult>
async listScheduleTools(): Promise<ScheduleToolsResult>
async callScheduleTool(request: ScheduleToolCallRequest): Promise<Record<string, unknown>>
// WorkGraph is read-only from the SDK; agents mutate it through WorkGraph tools.
async getWorkGraphItem(itemId: string, options?: WorkGraphItemLookupOptions): Promise<WorkItem>
async listWorkGraphItems(filter?: WorkGraphItemFilter): Promise<WorkItemListResult>
async listReadyWorkGraphItems(filter?: WorkGraphReadyFilter): Promise<WorkItemListResult>
async getWorkGraphSnapshot(filter?: WorkGraphSnapshotFilter): Promise<WorkGraphSnapshot>
async listWorkGraphEvents(filter?: WorkGraphEventFilter): Promise<WorkGraphEventsResult>
async readMobEvents(mobId: string, options?: MobEventsOptions): Promise<MobEventsResult>
async spawnMobMembers(mobId: string, specs: SpawnSpec[]): Promise<MobSpawnManyResultEntry[]>
async createMobProfile(name: string, profile: MobProfile): Promise<MobProfileLookupResult>
async getMobProfile(name: string): Promise<MobProfileLookupResult>
async listMobProfiles(): Promise<MobProfileLookupResult[]>
async updateMobProfile(name: string, profile: MobProfile, expectedRevision: number): Promise<MobProfileLookupResult>
async deleteMobProfile(name: string, expectedRevision: number): Promise<MobProfileDeleteResult>Session lifecycle on wrappers
Cancellation and archive operations live on the runtime-backed session wrappers:
await session.interrupt();
await session.archive();
const history = await session.history({ limit: 20 });capabilities
client.capabilitiesReturns the cached Capability[] collected during connect().
hasCapability(capabilityId)
hasCapability(capabilityId: string): booleanReturns true if the given capability is "Available" in the runtime. Known capability IDs:
| Capability ID | Description |
|---------------|-------------|
| "sessions" | Session lifecycle (create/turn/list/read/archive) |
| "streaming" | Real-time event streaming |
| "structured_output" | JSON schema-based structured output extraction |
| "hooks" | Lifecycle hooks |
| "builtins" | Built-in tools |
| "shell" | Shell tool |
| "comms" | Inter-agent communication |
| "memory_store" | Semantic memory |
| "session_store" | Session persistence |
| "session_compaction" | Context compaction |
| "skills" | Skill loading and invocation |
requireCapability(capabilityId)
requireCapability(capabilityId: string): voidThrows MeerkatError with code "CAPABILITY_UNAVAILABLE" if the capability is not available.
getConfig()
async getConfig(): Promise<ConfigEnvelope>Returns a config envelope: { config, generation, realmId?, instanceId?, backend?, resolvedPaths? }.
setConfig(config)
async setConfig(config: Record<string, unknown>): Promise<ConfigEnvelope>Replaces the entire runtime configuration and returns the updated envelope.
patchConfig(patch)
async patchConfig(patch: Record<string, unknown>): Promise<ConfigEnvelope>Merge-patches the runtime configuration and returns the updated envelope.
Public Types
The TypeScript SDK exposes camelCase domain types at the package root. The JSON-RPC snake_case wire format stays internal.
RunResultis available fromsession.lastResult,await session.turn(...),await deferred.startTurn(...), andstream.result.Usage,SessionInfo,Capability, andSchemaWarningmodel the runtime responses directly.SessionandDeferredSessionare the canonical runtime-backed wrappers for session lifecycle.EventStreamyields typed events such astext_delta,turn_completed, andtool_execution_completed.
Use the built-in client helpers directly for capability and skill flows:
const client = new MeerkatClient();
await client.connect();
if (client.hasCapability("skills")) {
const session = await client.createSession("Review this function");
const result = await session.invokeSkill(
{ sourceUuid: "source-123", skillName: "code-review" },
"Focus on performance regressions.",
);
console.log(result.text);
}Error Handling
The SDK provides a hierarchy of error classes, all extending the base MeerkatError:
MeerkatError
class MeerkatError extends Error {
readonly code: string;
readonly details?: unknown;
readonly capabilityHint?: {
capability_id: string;
message: string;
};
constructor(
code: string,
message: string,
details?: unknown,
capabilityHint?: { capability_id: string; message: string },
);
}Base error class. The code field contains a machine-readable error code (e.g. "VERSION_MISMATCH", "NOT_CONNECTED", "CAPABILITY_UNAVAILABLE"). The optional capabilityHint suggests which capability needs to be enabled.
CapabilityUnavailableError
class CapabilityUnavailableError extends MeerkatError {}Thrown when a required capability is not available in the runtime (e.g. feature not compiled in, disabled by policy).
SessionNotFoundError
class SessionNotFoundError extends MeerkatError {}Thrown when a session ID does not exist in the runtime.
SkillNotFoundError
class SkillNotFoundError extends MeerkatError {}Thrown when a referenced skill cannot be found.
Error handling example
import {
MeerkatClient,
MeerkatError,
CapabilityUnavailableError,
} from "@rkat/sdk";
const client = new MeerkatClient();
try {
await client.connect();
const session = await client.createSession("Hello");
console.log(session.text);
} catch (err) {
if (err instanceof CapabilityUnavailableError) {
console.error("Missing capability:", err.message);
if (err.capabilityHint) {
console.error("Hint:", err.capabilityHint.message);
}
} else if (err instanceof MeerkatError) {
console.error(`Meerkat error [${err.code}]: ${err.message}`);
} else {
throw err;
}
} finally {
await client.close();
}Version Compatibility
The SDK exports CONTRACT_VERSION (currently "0.6.3"). During connect(), the SDK checks that the server's contract version is compatible:
- While the major version is
0, minor versions must match exactly (e.g. SDK0.1.xrequires server0.1.x). - Once
1.0.0is reached, major versions must match (standard semver).
import { CONTRACT_VERSION } from "@rkat/sdk";
console.log(CONTRACT_VERSION); // "0.6.3"If the versions are incompatible, connect() throws a MeerkatError with code "VERSION_MISMATCH".
Config Management Example
const client = new MeerkatClient();
await client.connect();
// Read the current config.
const config = await client.getConfig();
console.log(config.generation, config.config);
// Replace the entire config.
await client.setConfig({ ...config.config, max_tokens: 4096 });
// Or merge-patch specific fields.
const updated = await client.patchConfig({ max_tokens: 8192 });
console.log(updated.config.max_tokens); // 8192
await client.close();Structured Output Example
const client = new MeerkatClient();
await client.connect();
const session = await client.createSession("List three European capitals", {
outputSchema: {
type: "object",
properties: {
capitals: {
type: "array",
items: { type: "string" },
},
},
required: ["capitals"],
},
structuredOutputRetries: 3,
});
// Parsed structured output (matches the schema).
console.log(session.structuredOutput);
// { capitals: ["Paris", "Berlin", "Madrid"] }
// Schema warnings from provider-specific validation issues.
if (session.lastResult.schemaWarnings) {
for (const w of session.lastResult.schemaWarnings) {
console.warn(`[${w.provider}] ${w.path}: ${w.message}`);
}
}
await client.close();Multi-turn Conversation Example
const client = new MeerkatClient();
await client.connect();
// Create session with first turn.
const session = await client.createSession("My name is Alice.", {
model: "claude-sonnet-4-5",
});
// Follow-up turns reuse the runtime-backed session handle.
const turn2 = await session.turn("What is my name?");
console.log(turn2.text); // Should mention "Alice"
// Check session state.
const state = await client.readSession(session.id);
console.log(state);
// List all active sessions.
const sessions = await client.listSessions();
console.log(`Active sessions: ${sessions.length}`);
// Clean up.
await session.archive();
await client.close();License
MIT OR Apache-2.0
