ViteHub is still experimental. Expect bugs and breaking changes.

Chat History and sessions

Select prior conversation messages without confusing them with durable Agent Memory.

Chat History is the ordered set of prior messages eligible for one chat invocation. A Chat Session selects the host-visible conversation boundary. Neither is durable Agent Memory.

NeedUse
Continue the visible threadThread-backed Chat History
Continue a conversation across changing transport threadsA Chat Session
Preserve knowledge or preferences across conversationsMemory Capability

Enable thread history

Configure history on the Chat Capability:

server/agents/support.ts
import { defineAgent } from 'vite-hub/agent'
import { chat } from 'vite-hub/agent/capabilities'

export default defineAgent({
  driver: {
    model: 'openai/gpt-5.1-mini',
    instructions: 'Answer support chat messages.',
  },
  capabilities: [
    chat({
      concurrency: 'queue',
      lockScope: 'thread',
      triggerHistory: {
        maxMessages: 20,
        source: 'thread',
      },
    }),
  ],
})

The window limits messages supplied to the next invocation; it does not delete preserved history. For application-owned routes that call runAgentTrigger() or streamAgentTrigger(), supply the ordered messages for the current thread, including the new message. triggerHistory bounds that caller-supplied array; it does not load history from threadId or a session id. Adapter-backed Channels can perform their own history backfill. Thread scope is the normal choice for Discord threads, Slack threads, Teams conversations, GitHub comment threads, and application-owned support chats.

Add a session

Use a session when the product has a stable conversation id that is independent of the current provider thread.

server/agents/support.ts
import { chat } from 'vite-hub/agent/capabilities'

export const supportChat = chat({
  sessions: {
    idleTimeoutMs: 30 * 60 * 1000,
    metadataKey: 'sessionId',
    strategy: 'hybrid',
  },
  triggerHistory: {
    maxMessages: 20,
    source: 'thread',
  },
})

Use strategy: 'manual' when a trusted host passes explicit session IDs, idle-timeout when inactivity starts a conversation, or hybrid for both. The chat.message input selects a manual session with session: { action: 'switch', id }.

The authenticated route or Channel supplies that ID. Do not accept an arbitrary session ID from an untrusted request, because that can expose another conversation's history.

Partition transcripts

Keep transcript keys aligned with the product boundary. Use thread keys when each platform thread is independent; include Channel or tenant identity when ids can collide across providers.

History selection and persistence are separate decisions. The Chat Capability can select a bounded window, but the configured store owns durability, ordering, retention, and deletion. Cloudflare output defaults Agent State to its generated Durable Object binding, including Channel handlers invoked from generated Workflows. An explicit state provider still wins; a state configuration with only url keeps automatic libSQL selection instead of being replaced by the Cloudflare default. Generated non-Cloudflare production output requires a durable VITEHUB_AGENT_STATE_URL or explicit Agent State provider URL before stateful traffic. Cloudflare, Vercel, and Netlify production output reject file: URLs because their compute filesystems are ephemeral.

Inspect the result

Run two messages through the same thread or session, then inspect the second invocation in the CLI. The prepared input contains the bounded prior messages plus the current message. A different thread or session starts without that history.