Skip to main content

theo.complete(request)

Sends a prompt through the full orchestration pipeline and returns the complete response.
const res = await theo.complete({
  prompt: "Explain microservices architecture",
  mode: "auto",           // or "fast", "think", "code", "research", etc.
  skills: ["deep-research"],
  conversation_id: "conv_abc123",  // optional — continue a conversation
  persona: { system_prompt: "You are a senior architect..." },
  tools: [/* inline tool definitions */],
  temperature: 0.7,
  max_iterations: 8,
  metadata: { source: "my-app" },
});

console.log(res.content);                  // Generated text
console.log(res.model.label);              // "Theo Reason"
console.log(res.resolved_mode);            // "think"
console.log(res.tools_used);               // [{ name, status, description? }]
console.log(res.usage.cost_cents);         // 0.15
console.log(res.usage.prompt_tokens);      // 42
console.log(res.usage.completion_tokens);  // 128
console.log(res.usage.total_tokens);       // 170
console.log(res.usage.cached);             // true when served from semantic cache
console.log(res.conversation_id);          // server-side conversation id or null
console.log(res.request_id);               // mirror of the X-Request-Id header

CompletionRequest

FieldTypeRequiredDefaultDescription
promptstringThe prompt text
modeChatMode"auto"Execution mode
conversation_idstring | nullContinue a persisted conversation (null accepted)
conversationInlineConversationInline history envelope for stateless callers
skillsstring[]Skill slugs to activate
toolsToolDef[]Inline tool definitions
personaPersonaInput"theo"Persona override
personality_configPersonalityConfigInputTrait intensities + uncensored mode override
response_styleResponseStyleInputFormat / preciseness / intent override
theo_brandingbooleanfalse strips Theo personality/branding from this response
brand_soulbooleanfalse disables the API key’s Brand Soul for this request
temperaturenumberSampling temperature
max_iterationsnumber8Max agent loop iterations
streambooleanfalseEnable SSE streaming
model_overridesRecord<string, string>Override model per mode
metadataRecord<string, unknown>Custom metadata
attachmentsCompletionAttachment[]Image attachments for vision analysis
image_modelTheoImageEnginePin a Theo image sub-engine when mode resolves to image
image_qualityTheoImageQuality"draft" | "standard" | "hd"
stealth_modelstringPin a stealth model (stealth modes only)
stealth_aspectTheoStealthAspectStealth image aspect ratio
stealth_durationTheoStealthDurationStealth video duration
null is accepted in place of any optional field and treated as the field being absent (matches OpenAI / Anthropic / Stripe behavior).

CompletionResponse.usage

interface CompletionUsage {
  cost_cents: number;           // markup-inclusive
  prompt_tokens: number;        // always 0 for non-text modes
  completion_tokens: number;    // always 0 for non-text modes
  total_tokens: number;
  cached?: boolean;             // true when served from the semantic cache
}
For image / video / tts / stt modes, token counts are always 0. Use cost_cents as the sole usage metric on those modes.

theo.stream(request)

Returns a TheoStream — an async-iterable handle with a cancel() method plus final-metadata properties populated as events arrive.
const stream = theo.stream({ prompt: "Explain DNS" });

// Hook up a "Stop generating" button
stopButton.onclick = () => stream.cancel();

for await (const event of stream) {
  switch (event.type) {
    case "meta":     console.log("Mode:", event.data.resolved_mode); break;
    case "token":    process.stdout.write(event.token); break;
    case "tool":     console.log("Tool:", event.data.name, event.data.status); break;
    case "artifact": renderArtifact(event.data); break;
    case "error":    console.error("Stream error:", event.data.error); break;
    case "done":     console.log("\nCost:", event.data.usage.cost_cents); break;
  }
}

// Populated from meta + done events:
console.log("conversation_id:", stream.conversationId);
console.log("usage:", stream.usage);
console.log("model:", stream.model);
console.log("request_id:", stream.requestId);
console.log("full content:", stream.content); // accumulated from token events
console.log("was cancelled?", stream.isCancelled);

TheoStream

MemberTypeDescription
[Symbol.asyncIterator]()AsyncIterator<StreamEvent>Standard async iteration — works with for await
cancel()voidAbort the underlying HTTP connection; stops generation + billing
isCancelledbooleantrue after cancel() has been called
requestIdstring | nullServer request id (from done event or X-Request-Id header)
model{ id, label, engine } | nullPopulated from the meta event
resolvedModeChatMode | nullMode after intent classification (from meta)
conversationIdstring | nullPopulated from meta / done (null for stateless callers)
usageCompletionUsage | nullPopulated from the done event
contentstringAccumulated text content from token events

StreamEvent (discriminated union)

switch (event.type) narrows event.data automatically.
event.typeevent.data shape
metaStreamMetaData — id, mode, resolved_mode, model, tools, artifacts, brand?, routing?, conversation_id, request_id
token{ token: string } — also exposed as event.token for convenience
tool{ name, status, description? }
artifactRecord<string, unknown> — shape varies by artifact type (image / video / document / code)
skills{ active: Array<{ id, slug, name, intensity? }> }
genui_meta{ library, tools[] } (GenUI mode only)
doneStreamDoneData — id, content, follow_ups, structured_output?, skills_active?, routing?, usage, conversation_id, request_id
error{ error: { message, type, code, request_id } } — matches the REST error envelope
See Streaming Completions (API reference) for the full wire format and a mid-stream 429 example.