KDS
Chatbot

Tool

Surface colapsável de tool-call — header com badge de status, input/output, suporte a HITL.

Overview

Tool mostra a execução de um tool-call — function call do modelo. Status com ícone (running, completed, error, denied, awaiting approval), input formatado em JSON, output renderizado.

Aceita o tipo ToolUIPart da AI SDK direto — você pega o state, type, input, output da resposta do modelo e passa pros props correspondentes.

Preview
Tool em execução (state input-available).

Parameters

Anatomy

<Tool>
  ├─ <ToolHeader type="..." state="..." title="..." />
  └─ <ToolContent>
       ├─ <ToolInput input={...} />     ← JSON formatado
       └─ <ToolOutput output={...} errorText={...} />
</Tool>

Usage

import { Tool, ToolContent, ToolHeader, ToolInput, ToolOutput } from "@kalvner/kds/ai/tool";

<Tool defaultOpen>
  <ToolHeader
    type="tool-search"
    state="output-available"
    title="search"
  />
  <ToolContent>
    <ToolInput input={{ query: "tokens", limit: 5 }} />
    <ToolOutput output={<pre>{JSON.stringify(results, null, 2)}</pre>} />
  </ToolContent>
</Tool>

Props

Tool (Root)

PropTipoDefaultDescrição
open / defaultOpenbooleanControle do collapsible.
classNamestringOverride; padrão tem border rounded-md.

Herda os outros props de Collapsible.

ToolHeader

PropTipoDefaultDescrição
typeToolUIPart["type"]Tipo do tool — string como tool-search, tool-fetch. Mostrado como label.
stateToolUIPart["state"]Estado da execução. Controla o badge + ícone.
titlestringOverride do label exibido (default: type sem prefixo tool-).
classNamestringOverride do header.

state values e visuais

StateBadgeÍcone
input-streaming"Pending"CircleIcon
input-available"Running"ClockIcon (animate-pulse)
approval-requested"Awaiting Approval"ClockIcon (yellow)
approval-responded"Responded"CheckCircleIcon (blue)
output-available"Completed"CheckCircleIcon (green)
output-error"Error"XCircleIcon (red)
output-denied"Denied"XCircleIcon (orange)

ToolContent

PropTipoDefaultDescrição
classNamestringOverride.

Aceita ToolInput + ToolOutput como filhos canônicos.

ToolInput

PropTipoDefaultDescrição
inputunknownObjeto/valor que será serializado como JSON pretty-print via CodeBlock.
classNamestringOverride.

ToolOutput

PropTipoDefaultDescrição
outputReactNodeResultado renderizado. Pode ser JSX, string, JSON pretty-print.
errorTextstringQuando presente, sobrescreve o output mostrando erro em vermelho.
classNamestringOverride.

Subcomponents

  • Tool — root colapsável. Sem ele, os filhos não funcionam (são detalhes do collapsible).
  • ToolHeader — display do tool name + badge de status. O ícone do badge muda conforme state.
  • ToolContent — wrapper das duas seções (input + output). Esconde quando Tool está collapsed.
  • ToolInput — JSON pretty-print do input enviado pro tool. Usa CodeBlock por baixo (com Shiki highlighting).
  • ToolOutput — resultado. Aceita output (sucesso) OU errorText (falha); errorText tem prioridade.

States

Ver tabela em ToolHeader → state values. O state afeta:

  • Cor + ícone do badge
  • Comportamento do TolOutput (mostra errorText quando state é output-error/output-denied)
  • Visibilidade automática do ToolOutput em alguns states

Variants

Não há variantes embutidas — variação é via composição do state. Pra UI custom de approval, combine com Confirmation.

Composition

HITL — approval flow

<Tool defaultOpen>
  <ToolHeader
    type="tool-delete-record"
    state="approval-requested"
    title="delete_record"
  />
  <ToolContent>
    <ToolInput input={{ recordId: "user_42" }} />
  </ToolContent>
  <Confirmation approval={part.approval} state={part.state}>
    <ConfirmationTitle>
      Aprovar exclusão?
    </ConfirmationTitle>
    <ConfirmationActions>
      <ConfirmationAction onClick={approve}>Aprovar</ConfirmationAction>
      <ConfirmationAction variant="outline" onClick={reject}>
        Rejeitar
      </ConfirmationAction>
    </ConfirmationActions>
  </Confirmation>
</Tool>

Streaming input

<Tool defaultOpen>
  <ToolHeader type="tool-fetch" state="input-streaming" />
  <ToolContent>
    <ToolInput input={partialInput} />
  </ToolContent>
</Tool>

When to use

  • Toda função call do modelo (search, fetch, calculator, exec).
  • Surface de tool execution em UI de agente.

When not to use

  • Mensagem texto pura — use Message.
  • Pensamento interno (sem execução) — use Reasoning.
  • Pra exibir o RESULTADO sem colapsável (ex.: tabela de search results) — Tool é sempre colapsável; pra mostrar inline use só o output formatado direto.

Best practices

  • type deve refletir o nome da tool. Modelos com tool-use marcam type: "tool-<name>" — mantenha o prefixo pra parsing consistente.
  • title curto e útil. Default tira o tool- mas você pode customizar (ex.: title="🔍 search").
  • defaultOpen=true durante streaming, fechado depois. Usuário quer ver execução happening, mas não bloat depois que terminou.
  • Pra HITL, sempre combine com Confirmation. Tool sozinho não oferece UI de approve/deny — precisa do Confirmation pra isso.

Accessibility

ConcernComportamento
RolesTrigger é <button> com aria-expanded. Content é <region>.
Badgearia-label no ícone (ex.: "Awaiting approval").
Status changesMudanças de state são visuais — combine com aria-live="polite" no parent (Conversation role="log" já cobre).
Code highlightingToolInput herda acessibilidade do CodeBlock.
  • Message — wrapper dentro do qual Tool vive.
  • Confirmation — fluxo de approve/deny pra HITL.
  • Reasoning — pensamento, não execução.
  • CodeBlock — usado por ToolInput pra JSON pretty-print.

On this page