Traditional chat only needs text bubbles, but AI Agent conversations must surface thinking, tool calls, citations, and progress — we solved this with 12 Vue components, three DisplayModes, and a unified chatBlocks rendering pipeline.
A user set retrieval top_k to 15, but the monitoring dashboard showed 5 and the streaming UI flashed 5 before jumping to 15. The same top_k value existed at four layers — LLM tool arguments, runtime, trace DB, and streaming payload — each requiring its own override. Three sequential fixes, each revealing the next layer was also wrong.
OMP's Agent stream does more than print tokens: it separates agent, turn, message, and tool-execution events. Understand the contract to render text deltas, tool progress, and errors without mistaking a partial message for committed conversation state.
SSE sends text/event-stream over ordinary HTTP, with browser reconnection and Last-Event-ID; simple transport is not durable unless the server retains events behind that cursor.
The AI SDK splits an AI message into a parts array — text, reasoning, source-url, tool-* — each an independent typed fragment (introduced in v5, unchanged since). That data structure dictates how modern AI conversation UIs are written: render by switching on part.type, handing each fragment to its component. This post unpacks the design logic of the parts model, useChat's streaming behavior, and how it became the foundation for component libraries like AI Elements.
The agent loop is a serialized per-session run. The part worth studying is how it handles concurrency: an admitted run records an activeWriterRunId claim, every transcript write supplies expectedWriterRunId, and the commit transaction verifies the match — so a superseded run cannot commit stale data.
Building a chatbot is more than just calling an API. Conversation state management, memory mechanisms, streaming, guardrails, observability, and tech stack selection — every layer affects the user experience.
LLM generation takes 3-5 seconds, and waiting for the full response before displaying it makes for a terrible experience. SSE pushes tokens as they're generated, reducing time-to-first-character from 5 seconds to under 1 second.