Skip to main content

TypeScript runtime client

Import CortexRuntimeClient and public types from @cortexmemory/sdk/runtime. This entry point is browser safe and does not bundle root SDK orchestration, backend functions, graph drivers or model factories.

Open and observe a run​

import { CortexRuntimeClient, CortexRuntimeError } from '@cortexmemory/sdk/runtime';
import type { RuntimeObservation } from '@cortexmemory/sdk/runtime';

export async function openRun(options: {
deploymentUrl: string;
assetHttpUrl: string;
agentId: string;
agentVersion: number;
text: string;
clientRequestId: string;
fetchToken: (request: { forceRefreshToken: boolean }) => Promise<string | null>;
render: (observation: RuntimeObservation) => void;
clearPrivateViews: () => void;
onError: (error: unknown) => void;
}) {
const client = new CortexRuntimeClient({
deploymentUrl: options.deploymentUrl,
assetHttpUrl: options.assetHttpUrl,
fetchToken: options.fetchToken,
onAuthChange: authenticated => {
if (!authenticated) options.clearPrivateViews();
},
});
let disconnect = () => {};
const clearOnAuthorityError = (error: unknown) => {
if (error instanceof CortexRuntimeError &&
['FORBIDDEN', 'UNAUTHENTICATED', 'AUTHORITY_EXPIRED', 'SESSION_CHANGED'].includes(error.code)) {
options.clearPrivateViews();
}
};
try {
await client.session();
const handle = await client.submit({
version: 1,
agentId: options.agentId,
agentVersion: options.agentVersion,
clientRequestId: options.clientRequestId,
parts: [{ type: 'text', text: options.text }],
});
disconnect = client.watchObservation(handle, options.render, error => {
if (error instanceof CortexRuntimeError &&
['FORBIDDEN', 'UNAUTHENTICATED', 'AUTHORITY_EXPIRED', 'SESSION_CHANGED'].includes(error.code)) {
clearOnAuthorityError(error);
disconnect();
void client.close();
}
options.onError(error);
});
await client.start(handle, { streaming: true });
return { client, handle, disconnect, close: async () => {
disconnect();
await client.close();
} };
} catch (error) {
clearOnAuthorityError(error);
disconnect();
await client.close();
throw error;
}
}

The caller generates and retains clientRequestId before calling openRun, so a lost submit response can be recovered with the same identity. The returned close() owns observer/client cleanup; authority errors also clear and close this view. Keep the same request identity for the same semantic intent. submit retains admission; start begins execution after configured input approval. Never write the returned exchange to memory again.

Methods​

GroupMethods
Authenticationsession(), refreshAuth(fetchToken?), close()
Runssubmit(input), attach(runId), start(handle, { streaming? }), get(handle), cancel(handle)
Observationobserve(handle, { cursor?, finalOnly?, limit? }), watchRun(handle, onUpdate, onError?), watchObservation(handle, onUpdate, onError?, options?)
ApprovalapproveInput(handle), approveTool(handle, approval)
Definitions/historygetDefinition(agentId, version), messages(conversationId, { cursor?, limit? }), listConversations(limit?)
MemorygetEmbeddingProfile(options?), getDefaultProfile(), memoryReadiness(options?), recall({ text, requestId, limit? })
ContentsubmitContentJob(input), getContentJob(jobId), listContentJobs(options?), cancelContentJob(jobId), reconcileContentJob(jobId), applyContentSuggestion(input)
Media/artifactssubmitMediaJob(input), getMediaJob(jobId), listMediaJobs(options?), cancelMediaJob(jobId), reconcileMediaJob(jobId), getArtifact(artifactId)
Private assetsuploadAsset(bytesOrBlob, options), getAsset(reference), fetchAsset(reference, options?), createAssetUrl(reference, options?)

watchObservation options include attempt/sequence cursor and final-only projection. Returned disconnect functions affect only the observer. An optional borrowed Convex client remains caller-owned when the runtime client closes.

Contracts and outcomes​

TextSubmitV1 accepts only new text parts, Agent selectors, optional conversation and a stable clientRequestId. Scope is server-resolved. RuntimeRunHandle pins actor/scope/run/conversation/definition identity but grants no access.

RuntimeRun exposes separate response, memory and graph status, context completeness and failure codes. RuntimeObservation includes retained sequenced parts, cursor and exact tool approvals. Canonical history is paginated.

RuntimeMediaSubmit retains a stable request, image/video kind, prompt and optional immutable input asset/conversation in its type contract. The qualified image path uses kind: 'image' and a text prompt without inputAsset. Its observed descriptor has callbacks: false; serving identity and USD charges remain unknown. Models/options/budgets are server policy.

The video kind, media.video.generate operation, video input and signed callback/native polling/provider-download contracts are reserved. Asynchronous video generation is unavailable in Convex Gateway, cannot be enabled for an individual team or deployment, and is explicitly deferred until official support and real qualification with independent acceptance. These retained methods and types do not imply a functional video capability. Existing video-file uploads and authenticated asset delivery remain in scope.

getMediaJob and listMediaJobs read retained state. reconcileMediaJob preserves the original job identity, can mark expired submissions unknown and can resume eligible retained-output recovery; it does not blindly generate again or guarantee recovery of a lost upstream image result. Native polling/download and missed-callback recovery describe the future video path. ContentSubmitV1 accepts a closed intent and version-bound sources.

Defaults are 10 seconds for authentication and 12 seconds for RPC observation. CortexRuntimeError includes code and outcome classification. Uncertain issued mutations are recovered by their original identity, never blindly retried as new work. Clear private views on authority loss and close owned clients/previews.

See streaming, memory, artifacts, assets/media and types.