Agent chat

Stream SSE agent chat in the AI SDK UIMessage format.

The streaming module speaks the same wire protocol as the bundled UI: AI SDK UIMessage chunks, SSE-framed, resumable. A task is one conversation thread; client-generated UUIDs are fine (the first message creates the task).

These examples assume an authenticated lunnoa client from the overview.

Stream a turn

agent-chat.ts
const taskId = crypto.randomUUID();const stream = await lunnoa.agentChat.streamMessage(  agentId,  taskId,  'Hello!',);for await (const chunk of stream) {  if (chunk.type === 'text-delta') process.stdout.write(chunk.delta);}// Reattach after a disconnect (returns null when nothing is running)const resumed = await lunnoa.agentChat.resumeStream(agentId, taskId);// Cancel a running turn (optionally persist the partial reply)await lunnoa.agentChat.stop(agentId, taskId);

Chunk types include start, text-start, text-delta, text-end, tool-input-available, tool-output-available, reasoning-*, finish, and error.

Framework notes

  • React: use @ai-sdk/react's useChat with a transport pointed at ${baseUrl}/api/agents/${agentId}/tasks/${taskId}/stream-message and an Authorization header. Use @lunnoa/client for everything non-chat.
  • Non-React: iterate AgentChatStream, or pass stream.toUIMessageStream() to the AI SDK's readUIMessageStream for assembled UIMessage snapshots.
  • History: tasks.get(taskId, { expansion: ['messages'] }) returns the persisted conversation in UIMessage format.
  • Non-streaming: tasks.message(agentId, taskId, text) waits for the full turn.

Next