Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Chat & orchestration

The chat surface at /space is where everything happens: streaming conversations, agent delegation, code workspace integration, forks and artifacts. This page documents the model end-to-end.

New to the AI side? Read AI concepts from scratch first — it explains what tokens, the context window, sampling and streaming are, which this page builds on.

A conversation is the unit of chat state:

  • Stable idcrypto.randomUUID(), synced to the URL as ?c=<id> so sessions are deep-linkable and survive refreshes.
  • Provider + model — stored per conversation, e.g. openai / gpt-4o.
  • Workspace reference (workspaceRef) — optional JSONB pointing at a repository (github/gitlab/local) or folder path. Conversations with a workspace are tagged as “code” sessions in the history.
  • Thinking leveloff / low / medium / high (reasoning-effort control where the provider supports it).
  • Fork treeparentId, rootId, childCount.

The active conversation is persisted in synthhires:activeConvId and broadcast via the synthhires:conv:focus CustomEvent so the sidebar, chat interface and history stay in sync.

Chat is where the abstract pieces from the AI primer become concrete. Four ideas do most of the heavy lifting:

  • The conversation is a growing prompt. The model has no memory after training; your chat works because the client re-sends the accumulated history on every turn, within the provider’s context window. That’s why a contextLimit setting exists and why long sessions eventually compress older messages.
  • Tokens are the unit of cost and of context. Every request is priced and sized in tokens (input, completion, cached, reasoning). The usage figures the ops panel shows come straight from per-request token accounting.
  • Streaming beats waiting. The answer is produced token-by-token and poured into the UI as it arrives, so perceived latency stays low even for long answers (see Streaming below).
  • Sampling is behind the “vibe.” Temperature, top-p and the rest live in Global Settings and decide how focused or how creative each reply is.

For the full explanations of each of these, see the AI concepts page.

  1. The chat input reads the current provider/model and the user’s encrypted key from the vault.
  2. prepareChatSendMessagesRequest (chat-transport.ts) assembles the payload — messages, media attachments snapshot, orchestration context and the handoff envelope.
  3. The client POSTs to /api/chat. The server gates with requireResolvedAuth, unwraps the envelope, and streams with streamText.
  4. The UI renders token-by-token. When the stream completes, the message and usage stats (recordUsage) are persisted.
  • Streaming is on by default (synthhires:streamResponse). Perceived latency is a product requirement: the route never buffers the full response.
  • maxRetries: 1 at the SDK level; the retry handler applies bounded backoff for 429/5xx (max 3 attempts, never an infinite loop).
  • Errors are sanitized through the redaction sink before being surfaced or logged.

The chat is not a single-model loop. The Lead Orchestrator can plan and delegate to specialized agents:

  • Execution steps — the ops panel (ops-panel.tsx) shows each step with status (pendingworkingdone/failed), which agent handled it, the model used, token counts and cost.
  • Sub-agent spawning — from the hierarchy panel you can spawn sub-agents with a chosen role and model (hierarchy-factory.ts).
  • Model comparison — the compare view (model-comparison.tsx) runs the same prompt across several providers/models side-by-side, useful for picking defaults.

When the orchestrator emits a plan in its free-text reply, the client extracts it with extractPlanFromContentsafeParsePlan (output-schemas.ts): a tolerant JSON scanner plus strict Zod validation, robust against missing fences and prose wrapping. The extracted plan feeds the Pipeline studio canvas (/space/studio).

What’s happening conceptually is structured output with tolerant parsing: the model is nudged to emit a plan shaped like a known schema, and the client reliably recovers it even when the model wraps it in prose or forgets code fences. See AI conceptsStructured output.

Forking is the Git metaphor for conversations:

  • From any assistant message you can fork: a new conversation is created with parentId = source id, rootId = the original root, and all messages up to the fork point are copied (forkConversation in chat-persistence.ts).
  • The parent’s childCount increments; deleting a fork decrements it.
  • Forks appear as separate sessions in history, sharing the original root so you can trace lineage.
Layer Storage Contents
Browser IndexedDB (local-chat-store.ts) Full messages, code, diffs — fast offline reads
Bridge (paired) SQLite on the device Full local mirror through sync.chat.push
Server Postgres (chat-persistence.ts) Light conversation index + messages for cross-device sync

Deleting a session removes it from both the local store and the server (/api/conversations DELETE), with a confirmation dialog because it is permanent.

The history page gives full control over sessions:

  • Search by title or repo; filter by type (all / code / chat / archived) and sort by last activity, creation date or title.
  • Folders — color-coded, with drag & drop to move sessions in and out.
  • Bulk actions — multi-select, bulk export and bulk delete.
  • Archive — soft-archive to synthhires:archivedConvs plus the status column, without deleting.
  • Rename — inline editing with optimistic updates.
  • Export / Import — bulk export dialog (Markdown/JSON) and import dialog to restore or transfer sessions.

The chat can produce artifacts (HTML, code, documents, images). They are rendered in a side panel (artifacts-panel.tsx) and indexed in the Artifacts gallery (/space/artifacts), so you can find generated content without remembering which conversation created it — searchable by type and origin session.

  • ?c=<conversationId> deep-links; the popstate handler keeps the UI in sync with back/forward.
  • ⌘N starts a new session; ⌘K opens the command palette; ⌘B toggles the sidebar.