Reasoning traces

Users trust agents they can see thinking. When the model calls a tool, the SDK streams a tool_invocation part into the message. Render it as a card with the tool name, arguments, and result. Suddenly the chat feels grounded instead of mysterious.

components/chat/tool-call-card.tsx
tsx
'use client';

import { Wrench } from 'lucide-react';

type ToolCallCardProps = {
  toolName: string;
  args?: unknown;
  result?: unknown;
  state?: string;
};

export function ToolCallCard({ toolName, args, result, state }: ToolCallCardProps) {
  return (
    <div className="my-2 rounded-md border border-amber-200 bg-amber-50 p-3 text-xs">
      <div className="flex items-center gap-2 font-medium text-amber-900">
        <Wrench className="h-3.5 w-3.5" />
        <span>Tool call: {toolName}</span>
        {state && <span className="ml-auto text-amber-700">{state}</span>}
      </div>
      {args !== undefined && (
        <pre className="mt-2 overflow-x-auto rounded bg-white p-2">
          {JSON.stringify(args, null, 2)}
        </pre>
      )}
      {result !== undefined && (
        <pre className="mt-2 overflow-x-auto rounded bg-white p-2">
          {JSON.stringify(result, null, 2)}
        </pre>
      )}
    </div>
  );
}

Each tool invocation renders as a card. The state field tells you whether the call is running, completed, or errored. Users can read the arguments and the result right next to the assistant reply.

components/chat/chat-panel.tsx
tsx
{parts.map((part, idx) => {
  if (part.type === 'text') {
    return (
      <div key={idx} className="whitespace-pre-wrap text-sm">
        {part.text}
      </div>
    );
  }
  if (part.type === 'tool-invocation' && part.toolInvocation) {
    const ti = part.toolInvocation;
    return (
      <ToolCallCard
        key={idx}
        toolName={ti.toolName}
        args={ti.args}
        result={ti.result}
        state={ti.state}
      />
    );
  }
  return null;
})}

Walk message.parts and render each kind. Text becomes a paragraph. Tool invocations become cards. The UI follows the structure of the stream exactly.

Trust and debugging. When the agent says "the weather in Tokyo is 18C" and users can see the tool call that produced that number, hallucinations become obvious. When the reply is wrong, the tool card usually shows you why. Hiding reasoning looks cleaner but costs you every time something misfires.