Infer types from the agent
Type useChat with the message type inferred from your agent.
AI SDK docsai-sdk.dev
Full type safety for your messages and tools
From ai-sdk, “Building and Consuming Agents”.
The server renames a field
Press Rename city → location, then read each result.
Untyped useChatBad
agent.ts
part.input as { city: string }Typed useChatGood
agent.ts
InferAgentUIMessage<typeof weatherAgent>// agent/weather-agent.ts
import { ToolLoopAgent, tool, type InferAgentUIMessage } from 'ai';
import { z } from 'zod';
export const weatherAgent = new ToolLoopAgent({
model: 'anthropic/claude-sonnet-5',
tools: {
weather: tool({
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => getWeather(city),
}),
},
});
export type WeatherAgentUIMessage = InferAgentUIMessage<typeof weatherAgent>;
// components/chat.tsx
'use client';
import { useChat } from '@ai-sdk/react';
import type { WeatherAgentUIMessage } from '@/agent/weather-agent';
const { messages } = useChat<WeatherAgentUIMessage>();
// part.type === 'tool-weather' → part.input is { city: string }
Why it matters, pros and cons
Why it matters
Tools are defined on the server and rendered on the client. One inferred type keeps both sides in step.
Pros
- A renamed tool or field fails the build, not the user.
- Tool part names and inputs autocomplete.
- No hand-written copy of the schema to drift.
Cons
- The client imports a type from the agent file; keep it type-only.
- Stored old messages still have the old shape.
- A cast like
as { city }switches it off again.