Get Started

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.

Chat manages the conversation state — messages, threads, context, memory. Channels (Slack, email, widget) manage the delivery surface. A single conversation might be accessed through multiple channels.

Creating a conversation

Create a conversation scoped to a user session. Each conversation is backed by an agent definition and includes configurable context management.

chat.ts
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.

send.ts
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.

stream.ts
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">// true

Context 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.

fullAll messages included. Falls back to sliding_window if it exceeds the model limit. Best for short conversations (<20 messages).
sliding_windowMost recent N messages that fit in maxTokens. Older messages dropped. Fast, no extra cost.
summarizeAfter 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 context

Conversation 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')

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_sent

User or assistant message created in a conversation.

chat.response_completed

Agent finished generating a response. Includes cost and token count.

chat.handoff_requested

Agent requested handoff to human or another agent.

chat.handoff_resolved

Handoff was resolved and conversation resumed.

chat.context_summarized

Context window was summarized (summarize strategy). Includes message count.

chat.conversation_archived

Conversation was archived by user or system.

Edge cases

Context overflowIf full strategy exceeds model limit, auto-falls back to sliding_window for that call. Logs a warning.
Summarization failsFalls back to sliding_window temporarily. Retries summarization on next message.
Concurrent messagesMessages are queued and processed in order. Two model calls never run simultaneously for the same conversation.
No agent attachedConversations can exist without an agent. Messages are stored but no model calls happen until an agent is attached.
Archived conversationSending to an archived conversation returns 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.
Was this page helpful?
Ask anything...⌘I