Generation, streaming, and tools
Use the portable primitives for streaming text, validated objects, messages, and local tools.
The high-level SDK primitives share the same model contract. You can move from a single response to streaming, structured output, or tools without rewriting provider plumbing.
Stream a response
streamText() starts the request and exposes an async text stream. Call collect() when you also need the normalized final result.
import { streamText } from "@zhivex-ai/sdk";
import { createOpenAI } from "@zhivex-ai/openai";
const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });
const stream = streamText({
model: openai("gpt-4o-mini"),
prompt: "Draft a short release note."
});
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
const final = await stream.collect();
console.log(final.finishReason, final.usage);
Always consume or collect a production stream so terminal state, usage, and persistence work can finish.
Return validated data
Use generateObject() when downstream code needs a typed object instead of prose.
import { generateObject } from "@zhivex-ai/sdk";
import { createGemini } from "@zhivex-ai/gemini";
import { z } from "zod";
const gemini = createGemini({ apiKey: process.env.GEMINI_API_KEY });
const result = await generateObject({
model: gemini("gemini-3.6-flash"),
prompt: "Create a release summary for developers.",
schema: z.object({
title: z.string(),
highlights: z.array(z.string()).min(2)
}),
mode: "native",
schemaName: "release_summary"
});
console.log(result.object);
Provider capabilities differ. Choose the model from the current provider matrix and handle UnsupportedFeatureError instead of assuming silent fallback.
Give the model a local tool
Tools are application-owned functions. Their schema validates model-generated input before execute runs.
import { generateText, tool } from "@zhivex-ai/sdk";
import { z } from "zod";
const result = await generateText({
model,
prompt: "Check order ord_123.",
maxSteps: 2,
tools: {
lookupOrder: tool({
name: "lookupOrder",
description: "Reads an order from the application database.",
schema: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => ({
orderId,
status: "shipped"
})
})
}
});
console.log(result.text, result.toolResults);
Treat a tool like any other privileged backend operation: authorize the user, scope database access to the tenant, bound its runtime, and require approval before side effects.
Use explicit messages
Use the message helpers for multi-part or pre-existing conversations:
import { assistant, system, user } from "@zhivex-ai/sdk";
const messages = [
system("You are a support assistant."),
user("My order has not arrived."),
assistant("I can check it. What is the order id?"),
user("ord_123")
];
For user-facing multi-turn history, prefer a Runner and durable session service instead of reconstructing the transcript in browser state.