Partial tool results and loading states
Every tool call goes through three states: call (the model emitted the call), result (the execute function returned), and error (something threw). The SDK streams each state as a separate update. Your UI can show "Calling web_search..." the instant the call starts, then fill in the result when it arrives.
import { Wrench, Loader2, Check, AlertTriangle } from 'lucide-react';
export function ToolCallCard({ toolName, args, result, state }: ToolCallCardProps) {
const Icon =
state === 'result' ? Check : state === 'error' ? AlertTriangle : Loader2;
const spinning = state !== 'result' && state !== 'error';
return (
<div className="my-2 rounded-md border border-emerald-200 bg-emerald-50 p-3 text-xs">
<div className="flex items-center gap-2 font-medium text-emerald-900">
<Icon className={'h-3.5 w-3.5 ' + (spinning ? 'animate-spin' : '')} />
<span>
{state === 'result' ? 'Tool result: ' : 'Calling '}
{toolName}
</span>
</div>
{args !== undefined && (
<pre className="mt-2 overflow-x-auto rounded bg-white p-2">
{JSON.stringify(args, null, 2)}
</pre>
)}
{state === 'result' && result !== undefined && (
<pre className="mt-2 overflow-x-auto rounded bg-white p-2">
{JSON.stringify(result, null, 2)}
</pre>
)}
</div>
);
}One card, three looks. Spinning while the tool runs, a check when it completes, a warning on error. The arguments render immediately so users see what was called even before the result arrives.
Quiz: Quiz
Loading practice…