feat(react-hooks): add TriggerChatTransport for AI SDK useChat
Closes #2634
✅ Checklist
- [x] I have followed every step in the contributing guide
- [x] The PR title follows the convention.
- [x] I ran and tested the code works
Summary
Adds a custom transport implementation for AI SDK's useChat hook that integrates with Trigger.dev background tasks. This enables long-running AI conversations by triggering tasks, subscribing to realtime run updates via Electric SQL, and streaming AI responses via Server-Sent Events (SSE).
Changes
-
New Hook:
useTriggerChat- A drop-in replacement for AI SDK'suseChatthat works with Trigger.dev tasks -
Transport Class:
TriggerChatTransport- Custom transport implementation following AI SDK's transport pattern -
Dependencies: Added
ai(^5.0.82),@ai-sdk/react(^2.0.14), andeventsource-parser(^3.0.0)
Technical Details
Architecture
- Uses Electric SQL ShapeStream for realtime run status updates
- Uses Server-Sent Events (SSE) with
EventSourceParserStreamfor streaming AI responses - Follows the same patterns as existing
useRealtimehook
Developer Requirements
Important: Developers must create their own server action to trigger tasks. Since useTriggerChat is a client-side hook, it cannot directly call tasks.trigger() (which requires server-side execution). The triggerTask option expects a server action that:
- Accepts the task identifier and payload
- Calls
tasks.trigger()on the server - Returns
{ success: true, runId, publicAccessToken }
Error Handling
- Gracefully handles stream disconnections and abort signals
- Warns on unparseable SSE chunks without breaking the stream
- Only closes controller when run finishes (not when individual streams end)
Testing
Manually tested with a local project using pnpm patch to verify:
- ✅ Task triggering and run creation
- ✅ Realtime run status updates
- ✅ SSE streaming of AI responses
- ✅ Multiple concurrent streams
- ✅ Graceful handling of stream completion
- ✅ TypeScript compilation
Usage Example
1. Define your Trigger.dev task (e.g. src/trigger/chat.ts):
import { metadata, task } from "@trigger.dev/sdk/v3";
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
export const chatTask = task({
id: "chat",
run: async ({ messages }: { messages: Array<{ role: string; content: string }> }) => {
const result = streamText({
model: openai("gpt-5"),
messages,
});
// CRITICAL: Stream the result to the client using metadata.stream()
// The stream key MUST match the streamKey option in useTriggerChat (default: "chat")
await metadata.stream("chat", result.toUIMessageStream());
const text = await result.text;
return { text };
},
});
2. Create a server action (e.g. src/actions.ts):
"use server";
import { tasks } from "@trigger.dev/sdk/v3";
export async function triggerChatTask(task: string, payload: unknown) {
const handle = await tasks.trigger(task, payload);
return {
success: true,
runId: handle.id,
publicAccessToken: handle.publicAccessToken,
};
}
3. Use the hook in your component (e.g. src/components/Chat.tsx):
"use client";
import { useTriggerChat } from "@trigger.dev/react-hooks";
import { chatTask } from "../trigger/chat";
import { triggerChatTask } from "../actions";
export function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useTriggerChat({
triggerTask: triggerChatTask,
});
return (
<form onSubmit={handleSubmit}>
<div>
{messages.map((msg) => (
<div key={msg.id}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
</div>
<input value={input} onChange={handleInputChange} />
<button type="submit">Send</button>
</form>
);
}
Changelog
Added useTriggerChat hook to @trigger.dev/react-hooks that provides AI SDK useChat integration with Trigger.dev background tasks. Enables long-running AI conversations with realtime streaming via custom transport implementation.
New exports:
-
useTriggerChat- Hook for AI chat integration -
TriggerChatTransport- Custom transport class -
TriggerChatTransportOptions- Transport configuration type -
TriggerChatTaskPayload- Task payload type
New dependencies:
-
ai@^5.0.82 -
@ai-sdk/react@^2.0.14 -
eventsource-parser@^3.0.0
Resources
- AI SDK Custom Transports Documentation
- AI SDK useChat Hook
- Trigger.dev Realtime API
- Electric SQL ShapeStream
- Server-Sent Events Spec
Screenshots
N/A - This is a developer-facing hook with no UI
💯
🦋 Changeset detected
Latest commit: b94f4f2f4f5f564f4de2a69dd116463f01ed348c
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 23 packages
| Name | Type |
|---|---|
| @trigger.dev/react-hooks | Minor |
| d3-chat | Patch |
| references-d3-openai-agents | Patch |
| references-nextjs-realtime | Patch |
| @trigger.dev/build | Minor |
| @trigger.dev/core | Minor |
| @trigger.dev/python | Minor |
| @trigger.dev/redis-worker | Minor |
| @trigger.dev/rsc | Minor |
| @trigger.dev/schema-to-json | Minor |
| @trigger.dev/sdk | Minor |
| @trigger.dev/database | Minor |
| @trigger.dev/otlp-importer | Minor |
| trigger.dev | Minor |
| @internal/cache | Patch |
| @internal/clickhouse | Patch |
| @internal/redis | Patch |
| @internal/replication | Patch |
| @internal/run-engine | Patch |
| @internal/schedule-engine | Patch |
| @internal/testcontainers | Patch |
| @internal/tracing | Patch |
| @internal/zod-worker | Patch |
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
Walkthrough
Adds a new TriggerChatTransport class and accompanying useTriggerChat React hook that provide Trigger.dev–backed streaming chat integration for the AI SDK. Introduces types, helpers for SSE/stream subscription and metadata parsing, reconnect logic, access-token handling, and runtime abort/cleanup behavior. Exports the new hook from the package index, updates packages/react-hooks/package.json to declare four optional peer dependencies (@ai-sdk/react, @electric-sql/client, ai, eventsource-parser), and adds a changelog entry for a minor release. No existing public APIs were removed.
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~50 minutes
- Areas to focus on:
- packages/react-hooks/src/hooks/useTriggerChat.ts (TriggerChatTransport lifecycle, sendMessages/reconnectToStream behavior, SSE parsing, stream enqueueing, abort and cleanup)
- subscribeToDataStreams / streamDataFromTrigger and metadata parsing correctness and error handling
- Access token resolution (static vs function) and caching logic
- package.json peerDependencies and peerDependenciesMeta entries for optionality
- packages/react-hooks/src/index.ts export addition
- .changeset entry for correctness and release metadata consistency
Pre-merge checks and finishing touches
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | Title clearly describes the main feature: adding TriggerChatTransport for AI SDK useChat integration, directly matching the primary code changes. |
| Description check | ✅ Passed | Description is comprehensive and follows the template with completed checklist, testing details, detailed changelog, and technical documentation. |
| Linked Issues check | ✅ Passed | All coding requirements from issue #2634 are met: custom transport implemented, task triggering enabled, metadata stream subscription integrated, and realtime features leveraged. |
| Out of Scope Changes check | ✅ Passed | All changes are directly aligned with issue #2634 objectives: new hook, transport class, optional peer dependencies, and exports supporting AI SDK integration. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.