DirectChatTransport
A transport that directly communicates with an Agent in-process, without going through HTTP. This is useful for:
- Server-side rendering scenarios
- Testing without network
- Single-process applications
Unlike DefaultChatTransport which sends HTTP requests to an API endpoint, DirectChatTransport invokes the agent's stream() method directly and converts the result to a UI message stream.
import { useChat } from '@ai-sdk/react';import { DirectChatTransport, ToolLoopAgent } from 'ai';
const agent = new ToolLoopAgent({ model: "anthropic/claude-sonnet-4.5", instructions: 'You are a helpful assistant.',});
export default function Chat() { const { messages, sendMessage, status } = useChat({ transport: new DirectChatTransport({ agent }), });
// ... render chat UI}Import
import { DirectChatTransport } from "ai"Constructor
Parameters
agent:
options?:
originalMessages?:
generateMessageId?:
messageMetadata?:
sendReasoning?:
sendSources?:
sendFinish?:
sendStart?:
onError?:
Methods
sendMessages()
Sends messages to the agent and returns a streaming response. This method validates and converts UI messages to model messages, calls the agent's stream() method, and returns the result as a UI message stream.
const stream = await transport.sendMessages({ chatId: 'chat-123', trigger: 'submit-message', messages: [...], abortSignal: controller.signal,});chatId:
trigger:
messageId:
messages:
abortSignal:
headers?:
body?:
metadata?:
Returns
Returns a Promise<ReadableStream<UIMessageChunk>> - a stream of UI message chunks that can be processed by the chat UI.
reconnectToStream()
Direct transport does not support reconnection since there is no persistent server-side stream to reconnect to.
Returns
Always returns Promise<null>.
Examples
Basic Usage
import { useChat } from '@ai-sdk/react';import { DirectChatTransport, ToolLoopAgent } from 'ai';import { openai } from '@ai-sdk/openai';
const agent = new ToolLoopAgent({ model: openai('gpt-4o'), instructions: 'You are a helpful assistant.',});
export default function Chat() { const { messages, sendMessage, status } = useChat({ transport: new DirectChatTransport({ agent }), });
return ( <div> {messages.map(message => ( <div key={message.id}> {message.role === 'user' ? 'User: ' : 'AI: '} {message.parts.map((part, index) => part.type === 'text' ? <span key={index}>{part.text}</span> : null, )} </div> ))} <button onClick={() => sendMessage({ text: 'Hello!' })}>Send</button> </div> );}With Agent Tools
import { useChat } from '@ai-sdk/react';import { DirectChatTransport, ToolLoopAgent, tool } from 'ai';import { openai } from '@ai-sdk/openai';import { z } from 'zod';
const weatherTool = tool({ description: 'Get the current weather', parameters: z.object({ location: z.string().describe('The city and state'), }), execute: async ({ location }) => { return `The weather in ${location} is sunny and 72°F.`; },});
const agent = new ToolLoopAgent({ model: openai('gpt-4o'), instructions: 'You are a helpful assistant with access to weather data.', tools: { weather: weatherTool },});
export default function Chat() { const { messages, sendMessage } = useChat({ transport: new DirectChatTransport({ agent }), });
// ... render chat UI with tool results}With Custom Agent Options
import { useChat } from '@ai-sdk/react';import { DirectChatTransport, ToolLoopAgent } from 'ai';import { openai } from '@ai-sdk/openai';
const agent = new ToolLoopAgent<{ userId: string }>({ model: openai('gpt-4o'), prepareCall: ({ options, ...rest }) => ({ ...rest, providerOptions: { openai: { user: options.userId }, }, }),});
export default function Chat({ userId }: { userId: string }) { const { messages, sendMessage } = useChat({ transport: new DirectChatTransport({ agent, options: { userId }, }), });
// ... render chat UI}With Reasoning
import { useChat } from '@ai-sdk/react';import { DirectChatTransport, ToolLoopAgent } from 'ai';import { openai } from '@ai-sdk/openai';
const agent = new ToolLoopAgent({ model: openai('o1-preview'),});
export default function Chat() { const { messages, sendMessage } = useChat({ transport: new DirectChatTransport({ agent, sendReasoning: true, }), });
return ( <div> {messages.map(message => ( <div key={message.id}> {message.parts.map((part, index) => { if (part.type === 'text') { return <p key={index}>{part.text}</p>; } if (part.type === 'reasoning') { return ( <pre key={index} style={{ opacity: 0.6 }}> {part.text} </pre> ); } return null; })} </div> ))} </div> );}