Claude-skill-registry Convex Agents Streaming
Streams agent responses in real-time to clients without blocking. Use this for responsive UIs, long-running generations, and asynchronous streaming to multiple clients.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/convex-agents-streaming" ~/.claude/skills/majiayu000-claude-skill-registry-convex-agents-streaming && rm -rf "$T"
manifest:
skills/data/convex-agents-streaming/SKILL.mdsource content
Purpose
Streaming allows responses to appear character-by-character in real-time, improving UX and perceived performance. Supports async streaming and multiple clients.
When to Use This Skill
- Building real-time chat interfaces with live updates
- Generating long responses that benefit from progressive display
- Streaming to multiple clients from single generation
- Using asynchronous streaming in background actions
- Implementing smooth text animation
Basic Async Streaming
Stream and save deltas to database:
export const streamResponse = action({ args: { threadId: v.string(), prompt: v.string() }, handler: async (ctx, { threadId, prompt }) => { const { thread } = await myAgent.continueThread(ctx, { threadId }); await thread.streamText( { prompt }, { saveStreamDeltas: true } ); return { success: true }; }, });
Configure Stream Chunking
await thread.streamText( { prompt }, { saveStreamDeltas: { chunking: "line", // "word" | "line" | regex | function throttleMs: 500, // Save deltas every 500ms }, } );
Retrieve Stream Deltas
import { vStreamArgs, syncStreams } from "@convex-dev/agent"; export const listMessagesWithStreams = query({ args: { threadId: v.string(), paginationOpts: paginationOptsValidator, streamArgs: vStreamArgs, }, handler: async (ctx, { threadId, paginationOpts, streamArgs }) => { const messages = await listUIMessages(ctx, components.agent, { threadId, paginationOpts, }); const streams = await syncStreams(ctx, components.agent, { threadId, streamArgs, }); return { ...messages, streams }; }, });
Display Streaming in React
import { useUIMessages, useSmoothText } from "@convex-dev/agent/react"; function ChatStreaming({ threadId }: { threadId: string }) { const { results } = useUIMessages( api.streaming.listMessages, { threadId }, { initialNumItems: 20, stream: true } ); return ( <div> {results?.map((message) => ( <StreamingMessage key={message.key} message={message} /> ))} </div> ); } function StreamingMessage({ message }: { message: UIMessage }) { const [visibleText] = useSmoothText(message.text, { startStreaming: message.status === "streaming", }); return <div>{visibleText}</div>; }
Key Principles
- Asynchronous streaming: Best for background generations
- Delta throttling: Balances responsiveness with write volume
- Stream status: Check
message.status === "streaming" - Smooth animation: Use
for text updatesuseSmoothText - Persistence: Deltas survive page reloads
Next Steps
- See messages for message management
- See fundamentals for agent setup
- See context for streaming-aware context