Agents, tools, and sessions
Build a tool-using agent, add durable multi-turn sessions, and introduce approval boundaries.
Use Agent when the model should choose whether to call tools or delegate work. Wrap it in Runner + SessionService when the experience belongs to a user-facing, multi-turn product.
Create an agent
import { Agent, tool } from "@zhivex-ai/sdk";
import { createOpenAI } from "@zhivex-ai/openai";
import { z } from "zod";
const openai = createOpenAI({ apiKey: process.env.OPENAI_API_KEY });
const agent = new Agent({
model: openai("gpt-4o-mini"),
instructions: "Answer with verified account facts and keep replies short.",
maxSteps: 3,
tools: {
lookupAccount: tool({
name: "lookupAccount",
schema: z.object({ accountId: z.string() }),
execute: async ({ accountId }) => loadAccount(accountId)
})
}
});
const result = await agent.run({
prompt: "Check account acct_123."
});
console.log(result.outputText);
console.log(result.state);
Every run returns serializable state with messages, steps, tool results, approvals, usage, status, schema version, and revision. Persist that state or attach an SDK run store when a process restart must not lose the run.
Add multi-turn sessions
import {
createFileSessionService,
createRunner
} from "@zhivex-ai/sdk";
const runner = createRunner({
appName: "support-copilot",
agent,
sessionService: createFileSessionService({
directory: ".zhivex/sessions"
})
});
const first = await runner.run({
userId: "user_123",
sessionId: "demo",
prompt: "Remember that I prefer short answers."
});
const second = await runner.run({
userId: "user_123",
sessionId: first.session.sessionId,
prompt: "Summarize the account status."
});
File-backed sessions are useful for local development. Use Postgres for shared or serverless production deployments.
Pause before a side effect
Local tools can interrupt the run and wait for an application-owned approval decision:
const deploy = tool({
name: "deploy",
schema: z.object({ target: z.string() }),
requiresApproval: true,
approvalMode: "interrupt",
approvalVersion: "2026-07-29",
execute: async ({ target }, context) =>
deployRelease(target, {
signal: context?.abortSignal,
idempotencyKey: context?.idempotencyKey
})
});
The SDK can bind and persist approval state, but your application still owns identity, role checks, queue-token validation, expiration, audit records, and one-time consumption.
For a governed application boundary, TypeScript 1.5 exposes the Stable @zhivex-ai/agents/control-plane entrypoint. It composes capsules, tool policy, approval queues, ledgers, capability routing, inspectable runs, and durable single-consumer approval resume. This is a library contract, not a hosted control plane: the application still owns IAM, tenancy, secrets, storage, network policy, and the approval UI.
Agent or workflow?
- Use an agent when the model chooses the next action.
- Use a workflow when the application already knows the sequence.
- Use subagents when the model should decide whether to delegate.
- Use a parallel workflow group when application code always fans out.
For a product UI and server route, continue with the Next.js integration.
For model-directed delegation, continue with subagents. If application code already knows the order, use a workflow instead.
For low-latency audio or text sessions, use the Stable shared realtime lifecycle and streamLiveAgent() described in multimodal and realtime. Provider model IDs and preview availability remain provider-scoped even though the shared SDK contract is Stable.