Chat
Managed conversational state for agents. Message history, threads, context window management, multi-turn memory, handoff, and search. The core primitive for any AI company building chat-based products.
Creating a conversation
Create a conversation scoped to a user session. Each conversation is backed by an agent definition and includes configurable context management.
import { Theazo } from class="cb-str">'theazo'
const theazo = new Theazo({ apiKey: class="cb-str">'th_live_...' })
const session = await theazo.sessions.forUser(class="cb-str">'user_123')
const conversation = await session.chat.create({
agent: class="cb-str">'support_agent',
title: class="cb-str">'Help with billing',
metadata: { page: class="cb-str">'/settings/billing' },
context: {
strategy: class="cb-str">'sliding_window', class="cb-cmt">// 'full' | 'sliding_window' | 'summarize'
maxTokens: class="cb-num">8192,
summarizeAfter: class="cb-num">20,
},
systemPrompt: class="cb-str">'You are a billing support agent...',
knowledge: class="cb-str">'support-docs', class="cb-cmt">// optional: attach knowledge collection
})
console.log(conversation.id) class="cb-cmt">// 'conv_abc'
console.log(conversation.status) class="cb-cmt">// 'active'Sending messages
Send a user message and receive the agent's response. Theazo manages the context window automatically based on your chosen strategy.
const response = await session.chat.send(class="cb-str">'conv_abc', {
content: class="cb-str">'Why was I charged twice this month?',
attachments: [class="cb-str">'file_abc'], class="cb-cmt">// optional file attachments
})
console.log(response.id) class="cb-cmt">// 'msg_def'
console.log(response.role) class="cb-cmt">// 'assistant'
console.log(response.content) class="cb-cmt">// 'Let me look into your billing...'
console.log(response.toolCalls) class="cb-cmt">// [{ name: 'query_billing', input: {...} }]
console.log(response.cost) class="cb-cmt">// { amount: 3, currency: 'usd' }Streaming responses
Stream the agent response token-by-token for real-time UI updates.
const stream = await session.chat.stream(class="cb-str">'conv_abc', {
content: class="cb-str">'Can you explain in more detail?',
})
for await (const chunk of stream) {
if (chunk.type === class="cb-str">'text') process.stdout.write(chunk.text)
class="cb-cmt">// chunk types:
class="cb-cmt">// { type: 'text', text: '...' }
class="cb-cmt">// { type: 'tool_call', name: '...', input: {...} }
class="cb-cmt">// { type: 'tool_result', name: '...', output: '...' }
class="cb-cmt">// { type: 'done', messageId: 'msg_ghi', cost: {...}, tokenCount: 847 }
}Message history
Retrieve paginated message history for a conversation, ordered by most recent first.
const messages = await session.chat.messages(class="cb-str">'conv_abc', {
limit: class="cb-num">50,
cursor: class="cb-str">'...', class="cb-cmt">// pagination cursor
order: class="cb-str">'desc', class="cb-cmt">// 'asc' | 'desc'
})
console.log(messages.data) class="cb-cmt">// [{ id, role, content, toolCalls, createdAt }]
console.log(messages.hasMore) class="cb-cmt">// trueContext management
Theazo automatically manages what goes into the model's context window before each call. AgentCo doesn't need to worry about token limits or message truncation.
maxTokens. Older messages dropped. Fast, no extra cost.summarizeAfter messages, older ones are summarized by LLM. New messages + summary fit in window. Costs extra.Inspecting context state
const ctx = await session.chat.context(class="cb-str">'conv_abc')
console.log(ctx.totalMessages) class="cb-cmt">// 47
console.log(ctx.contextMessages) class="cb-cmt">// 12 (messages in current window)
console.log(ctx.contextTokens) class="cb-cmt">// 6200
console.log(ctx.summary) class="cb-cmt">// 'User asked about billing charges...'
console.log(ctx.strategy) class="cb-cmt">// 'summarize'Injecting system context
Inject invisible context the agent can see but the user cannot. Useful for passing account data or business rules without exposing them in the conversation.
await session.chat.injectContext(class="cb-str">'conv_abc', {
content: class="cb-str">'User is on the Enterprise plan. Account created 2024-01-15.',
role: class="cb-str">'system', class="cb-cmt">// not shown in message history to user
})Threads
Create sub-conversations within a conversation. Threads share the parent conversation's system prompt and knowledge, but have their own message history. Thread messages don't appear in the main conversation's context window.
// Create a thread anchored to a message
const thread = await session.chat.createThread(class="cb-str">'conv_abc', {
parentMessageId: class="cb-str">'msg_def',
title: class="cb-str">'Billing charge details',
})
// Send messages in the thread
await session.chat.send(thread.id, {
content: class="cb-str">'Which specific charge are you referring to?',
})
// List threads in a conversation
const threads = await session.chat.threads(class="cb-str">'conv_abc')
// → [{ id: 'thrd_abc', parentMessageId: 'msg_def', title: '...', messageCount: 4 }]Handoff
Escalate a conversation to a human or a different agent. The conversation is paused with statushanded_off until resolved.
Agent to human
await session.chat.handoff(class="cb-str">'conv_abc', {
reason: class="cb-str">'Customer requesting refund over $500',
to: class="cb-str">'human',
metadata: { refundAmount: class="cb-num">650 },
})
// → Fires webhook: chat.handoff_requested
// → AgentCo routes to their human support queue
// When human resolves:
await session.chat.resolveHandoff(class="cb-str">'conv_abc')Agent to agent
await session.chat.handoff(class="cb-str">'conv_abc', {
reason: class="cb-str">'Technical issue requires engineering agent',
to: class="cb-str">'agent:engineering_agent',
})
// → Same conversation, new agent picks up with full contextConversation management
// List conversations for a user
const conversations = await session.chat.list({
status: class="cb-str">'active', class="cb-cmt">// 'active' | 'archived' | 'all'
limit: class="cb-num">20,
})
// Update conversation
await session.chat.update(class="cb-str">'conv_abc', {
title: class="cb-str">'Billing double charge issue',
metadata: { resolved: false, priority: class="cb-str">'high' },
})
// Archive (soft close — preserves history, stops accepting messages)
await session.chat.archive(class="cb-str">'conv_abc')
// Resume archived conversation
await session.chat.unarchive(class="cb-str">'conv_abc')
// Delete (hard delete — removes all messages)
await session.chat.delete(class="cb-str">'conv_abc')Search
Full-text search across message content within a user's conversations.
const results = await session.chat.search({
query: class="cb-str">'refund',
userId: class="cb-str">'user_123',
limit: class="cb-num">10,
})
// → [{ conversationId, messageId, content: '...', score: 0.89, createdAt: '...' }]Webhook events
chat.message_sentUser or assistant message created in a conversation.
chat.response_completedAgent finished generating a response. Includes cost and token count.
chat.handoff_requestedAgent requested handoff to human or another agent.
chat.handoff_resolvedHandoff was resolved and conversation resumed.
chat.context_summarizedContext window was summarized (summarize strategy). Includes message count.
chat.conversation_archivedConversation was archived by user or system.
Edge cases
full strategy exceeds model limit, auto-falls back to sliding_window for that call. Logs a warning.sliding_window temporarily. Retries summarization on next message.chat_conversation_archived. Unarchive first.API reference
session.chat.create(opts)Promise<ChatConversation>Create a new conversation with agent, context config, and optional knowledge.session.chat.send(id, { content, attachments })Promise<ChatMessage>Send a user message and receive the agent response.session.chat.stream(id, { content })AsyncIterable<ChatStreamEvent>Stream the agent response token-by-token via SSE.session.chat.messages(id, opts)Promise<{ data, hasMore }>Get paginated message history. Supports cursor pagination and ordering.session.chat.list(opts)Promise<{ data, hasMore }>List conversations for the session user. Filter by status.session.chat.get(id)Promise<ChatConversation>Get a single conversation by ID.session.chat.update(id, opts)Promise<ChatConversation>Update title and metadata.session.chat.archive(id)Promise<void>Soft close. Preserves history, stops accepting messages.session.chat.unarchive(id)Promise<void>Resume an archived conversation.session.chat.delete(id)Promise<void>Hard delete conversation and all messages.session.chat.context(id)Promise<ChatContextState>Get context window state: message count, token count, summary, strategy.session.chat.injectContext(id, opts)Promise<void>Add invisible system context the agent sees but the user does not.session.chat.createThread(id, opts)Promise<ChatThread>Create a sub-conversation thread anchored to a message.session.chat.threads(id)Promise<ChatThread[]>List all threads in a conversation.session.chat.handoff(id, opts)Promise<ChatHandoff>Escalate to human or another agent. Fires chat.handoff_requested webhook.session.chat.resolveHandoff(id)Promise<void>Resolve a pending handoff and resume the conversation.session.chat.search(opts)Promise<ChatSearchResult[]>Full-text search across messages. Filter by userId or conversationId.