Pré-requisitos

  • Node.js 18+

Instalação

Instale @anthropic-ai/claude-code do NPM:
npm install -g @anthropic-ai/claude-code
Para visualizar o código-fonte do SDK TypeScript, visite a página @anthropic-ai/claude-code no NPM.

Uso básico

A interface principal via SDK TypeScript é a função query, que retorna um iterador assíncrono que transmite mensagens conforme chegam:
import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Analisar desempenho do sistema",
  options: {
    maxTurns: 5,
    appendSystemPrompt: "Você é um engenheiro de desempenho",
    allowedTools: ["Bash", "Read", "WebSearch"],
    abortController: new AbortController(),
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Opções de configuração

ArgumentoTipoDescriçãoPadrão
abortControllerAbortControllerControlador de aborto para cancelar operaçõesnew AbortController()
additionalDirectoriesstring[]Diretórios adicionais para incluir na sessãoundefined
allowedToolsstring[]Lista de ferramentas que Claude tem permissão para usarTodas as ferramentas habilitadas por padrão
appendSystemPromptstringTexto para anexar ao prompt do sistema padrãoundefined
canUseTool(toolName: string, input: any) => Promise<ToolPermissionResult>Função de permissão personalizada para uso de ferramentasundefined
continuebooleanContinuar a sessão mais recentefalse
customSystemPromptstringSubstituir completamente o prompt do sistema padrãoundefined
cwdstringDiretório de trabalho atualprocess.cwd()
disallowedToolsstring[]Lista de ferramentas que Claude não tem permissão para usarundefined
envDict<string>Variáveis de ambiente para definirundefined
executable'bun' | 'deno' | 'node'Qual runtime JavaScript usarnode quando executando com Node.js, bun quando executando com Bun
executableArgsstring[]Argumentos para passar ao executável[]
fallbackModelstringModelo para usar se o modelo principal falharundefined
hooksPartial<Record<HookEvent, HookCallbackMatcher[]>>Hooks de ciclo de vida para personalizaçãoundefined
includePartialMessagesbooleanIncluir eventos de streaming parciais no fluxo de mensagensfalse
maxThinkingTokensnumberTokens máximos para o processo de pensamento do Claudeundefined
maxTurnsnumberNúmero máximo de turnos de conversaundefined
mcpServersRecord<string, McpServerConfig>Configurações do servidor MCPundefined
modelstringModelo Claude para usarUsa padrão da configuração CLI
pathToClaudeCodeExecutablestringCaminho para o executável Claude CodeExecutável que vem com @anthropic-ai/claude-code
permissionModePermissionModeModo de permissão para a sessão"default" (opções: "default", "acceptEdits", "bypassPermissions", "plan")
resumestringID da sessão para retomarundefined
stderr(data: string) => voidCallback para saída stderrundefined
strictMcpConfigbooleanAplicar validação rigorosa de configuração MCPundefined

Streaming de mensagens parciais

Quando includePartialMessages está habilitado, o SDK emitirá mensagens stream_event que contêm eventos de streaming brutos da API Claude. Isso permite acessar conteúdo parcial conforme está sendo gerado, útil para implementar atualizações de UI em tempo real ou indicadores de progresso.
import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Escreva um ensaio longo sobre inteligência artificial",
  options: {
    includePartialMessages: true,
    maxTurns: 1
  }
})) {
  // Lidar com eventos de streaming parciais
  if (message.type === "stream_event") {
    const event = message.event;
    
    // Acessar texto parcial conforme transmite
    if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
      process.stdout.write(event.delta.text);
    }
    
    // Rastrear progresso de pensamento
    if (event.type === "content_block_start" && event.content_block.type === "thinking") {
      console.log("\n[Claude está pensando...]");
    }
  }
  
  // Ainda obter o resultado final
  if (message.type === "result" && message.subtype === "success") {
    console.log("\nResultado final:", message.result);
  }
}
Cada mensagem stream_event inclui:
  • event: O evento de streaming bruto da API
  • session_id: O identificador da sessão atual
  • parent_tool_use_id: O ID da ferramenta sendo executada (se aplicável)
  • uuid: Um identificador único para este evento
O streaming de mensagens parciais é principalmente útil para casos de uso avançados onde você precisa de controle granular sobre a resposta de streaming. Para a maioria das aplicações, o comportamento padrão (aguardar mensagens completas) é suficiente.

Conversas multi-turno

Para conversas multi-turno, você tem duas opções. Você pode gerar respostas e retomá-las, ou pode usar o modo de entrada de streaming que aceita um async/generator para um array de mensagens. Por enquanto, o modo de entrada de streaming é a única maneira de anexar imagens via mensagens.

Retomar com gerenciamento de sessão

import { query } from "@anthropic-ai/claude-code";

// Continuar conversa mais recente
for await (const message of query({
  prompt: "Agora refatore isso para melhor desempenho",
  options: { continue: true }
})) { 
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Retomar sessão específica
for await (const message of query({
  prompt: "Atualizar os testes",
  options: {
    resume: "550e8400-e29b-41d4-a716-446655440000",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Modo de entrada de streaming

O modo de entrada de streaming permite fornecer mensagens como um iterável assíncrono em vez de uma única string. Isso habilita conversas multi-turno, anexos de imagem e geração dinâmica de mensagens:
import { query } from "@anthropic-ai/claude-code";

// Criar um gerador assíncrono para streaming de mensagens
async function* generateMessages() {
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Começar a analisar esta base de código"
    }
  };
  
  // Aguardar alguma condição ou entrada do usuário
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: "Agora focar no módulo de autenticação"
    }
  };
}

// Usar entrada de streaming
for await (const message of query({
  prompt: generateMessages(),
  options: {
    maxTurns: 5,
    allowedTools: ["Read", "Grep", "Bash"]
  }
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
  }
}

Entrada de streaming com imagens

O modo de entrada de streaming é a única maneira de anexar imagens via mensagens:
import { query } from "@anthropic-ai/claude-code";
import { readFileSync } from "fs";

async function* messagesWithImage() {
  // Enviar uma imagem com texto
  yield {
    type: "user" as const,
    message: {
      role: "user" as const,
      content: [
        {
          type: "text",
          text: "Analise esta captura de tela e sugira melhorias"
        },
        {
          type: "image",
          source: {
            type: "base64",
            media_type: "image/png",
            data: readFileSync("screenshot.png", "base64")
          }
        }
      ]
    }
  };
}

for await (const message of query({
  prompt: messagesWithImage()
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Prompts de sistema personalizados

Prompts de sistema definem o papel, expertise e comportamento do seu agente:
import { query } from "@anthropic-ai/claude-code";

// Agente de resposta a incidentes SRE
for await (const message of query({
  prompt: "API está fora do ar, investigar",
  options: {
    customSystemPrompt: "Você é um especialista SRE. Diagnostique problemas sistematicamente e forneça soluções acionáveis.",
    maxTurns: 3
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// Anexar ao prompt de sistema padrão
for await (const message of query({
  prompt: "Refatorar esta função",
  options: {
    appendSystemPrompt: "Sempre inclua tratamento de erro abrangente e testes unitários.",
    maxTurns: 2
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Integração com Servidor MCP

O Model Context Protocol (MCP) permite dar aos seus agentes ferramentas e capacidades personalizadas:
import { query } from "@anthropic-ai/claude-code";

// Agente SRE com ferramentas de monitoramento
for await (const message of query({
  prompt: "Investigar a interrupção do serviço de pagamento",
  options: {
    mcpConfig: "sre-tools.json",
    allowedTools: ["mcp__datadog", "mcp__pagerduty", "mcp__kubernetes"],
    appendSystemPrompt: "Você é um SRE. Use dados de monitoramento para diagnosticar problemas.",
    maxTurns: 4
  }
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Ferramentas personalizadas com servidores MCP em processo

Servidores SDK MCP permitem criar ferramentas personalizadas que executam diretamente no processo da sua aplicação, fornecendo execução de ferramenta type-safe sem a sobrecarga de processos separados ou comunicação de rede.

Criando ferramentas personalizadas

Use as funções auxiliares createSdkMcpServer e tool para definir ferramentas personalizadas type-safe:
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-code";
import { z } from "zod";

// Criar um servidor SDK MCP com ferramentas personalizadas
const customServer = createSdkMcpServer({
  name: "my-custom-tools",
  version: "1.0.0",
  tools: [
    tool(
      "calculate_compound_interest",
      "Calcular juros compostos para um investimento",
      {
        principal: z.number().describe("Valor do investimento inicial"),
        rate: z.number().describe("Taxa de juros anual (como decimal, ex: 0.05 para 5%)"),
        time: z.number().describe("Período de investimento em anos"),
        n: z.number().default(12).describe("Frequência de capitalização por ano")
      },
      async (args) => {
        const amount = args.principal * Math.pow(1 + args.rate / args.n, args.n * args.time);
        const interest = amount - args.principal;
        
        return {
          content: [{
            type: "text",
            text: `Valor final: R$${amount.toFixed(2)}\nJuros ganhos: R$${interest.toFixed(2)}`
          }]
        };
      }
    ),
    tool(
      "fetch_user_data",
      "Buscar dados do usuário do banco de dados da sua aplicação",
      {
        userId: z.string().describe("O ID do usuário para buscar"),
        fields: z.array(z.string()).optional().describe("Campos específicos para retornar")
      },
      async (args) => {
        // Acesso direto à camada de dados da sua aplicação
        const userData = await myDatabase.getUser(args.userId, args.fields);
        
        return {
          content: [{
            type: "text",
            text: JSON.stringify(userData, null, 2)
          }]
        };
      }
    )
  ]
});

// Usar as ferramentas personalizadas na sua consulta
for await (const message of query({
  prompt: "Calcular juros compostos para R$10.000 a 5% por 10 anos",
  options: {
    mcpServers: {
      "my-custom-tools": customServer
    },
    maxTurns: 3
  }
})) {
  if (message.type === "result") {
    console.log(message.result);
  }
}

Segurança de tipos com Zod

O auxiliar tool fornece inferência completa de tipos TypeScript dos seus esquemas Zod:
tool(
  "process_data",
  "Processar dados estruturados com segurança de tipos",
  {
    // Esquema Zod define tanto validação em tempo de execução quanto tipos TypeScript
    data: z.object({
      name: z.string(),
      age: z.number().min(0).max(150),
      email: z.string().email(),
      preferences: z.array(z.string()).optional()
    }),
    format: z.enum(["json", "csv", "xml"]).default("json")
  },
  async (args) => {
    // args é totalmente tipado baseado no esquema
    // TypeScript sabe: args.data.name é string, args.data.age é number, etc.
    console.log(`Processando dados de ${args.data.name} como ${args.format}`);
    
    // Sua lógica de processamento aqui
    return {
      content: [{
        type: "text",
        text: `Dados processados para ${args.data.name}`
      }]
    };
  }
)

Hooks

Hooks permitem personalizar e estender o comportamento do Claude Code executando callbacks personalizados em vários pontos do ciclo de vida do agente. Diferente dos hooks CLI que executam comandos bash, hooks SDK são funções JavaScript/TypeScript que executam em processo.

Definindo hooks

Hooks são organizados por tipo de evento, com matchers opcionais para filtrar quando executam:
import { query } from "@anthropic-ai/claude-code";

for await (const message of query({
  prompt: "Analisar a base de código",
  options: {
    hooks: {
      PreToolUse: [
        {
          matcher: "Write",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`Prestes a escrever arquivo: ${input.tool_input.file_path}`);
              
              // Validar a operação
              if (input.tool_input.file_path.includes('.env')) {
                return {
                  decision: 'block',
                  stopReason: 'Não é possível escrever em arquivos de ambiente'
                };
              }
              
              // Permitir a operação
              return { continue: true };
            }
          ]
        }
      ],
      PostToolUse: [
        {
          matcher: "Write|Edit",
          hooks: [
            async (input, toolUseId, { signal }) => {
              console.log(`Arquivo modificado: ${input.tool_response.filePath}`);
              // Executar sua formatação ou validação personalizada
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Eventos de hook disponíveis

  • PreToolUse: Executa antes da execução da ferramenta. Pode bloquear ferramentas ou fornecer feedback.
  • PostToolUse: Executa após execução bem-sucedida da ferramenta.
  • UserPromptSubmit: Executa quando usuário submete um prompt.
  • SessionStart: Executa quando uma sessão inicia.
  • SessionEnd: Executa quando uma sessão termina.
  • Stop: Executa quando Claude está prestes a parar de responder.
  • SubagentStop: Executa quando um subagente está prestes a parar.
  • PreCompact: Executa antes da compactação da conversa.
  • Notification: Executa quando notificações são enviadas.

Tipos de entrada de hook

Cada hook recebe entrada tipada baseada no evento:
// Entrada PreToolUse
type PreToolUseHookInput = {
  hook_event_name: 'PreToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
}

// Entrada PostToolUse
type PostToolUseHookInput = {
  hook_event_name: 'PostToolUse';
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
  tool_name: string;
  tool_input: unknown;
  tool_response: unknown;
}

Saída de hook

Hooks retornam saída que controla o fluxo de execução:
interface HookJSONOutput {
  // Continuar execução (padrão: true)
  continue?: boolean;
  
  // Suprimir saída para usuário
  suppressOutput?: boolean;
  
  // Razão de parada (mostrada ao modelo)
  stopReason?: string;
  
  // Decisão para hooks PreToolUse
  decision?: 'approve' | 'block';
  
  // Mensagem do sistema para mostrar
  systemMessage?: string;
  
  // Saída específica do hook
  hookSpecificOutput?: {
    // Para PreToolUse
    permissionDecision?: 'allow' | 'deny' | 'ask';
    permissionDecisionReason?: string;
    
    // Para UserPromptSubmit ou PostToolUse
    additionalContext?: string;
  };
}

Exemplos práticos

Logging e monitoramento

const hooks = {
  PreToolUse: [
    {
      hooks: [
        async (input) => {
          // Registrar todo uso de ferramenta
          await logToMonitoring({
            event: 'tool_use',
            tool: input.tool_name,
            input: input.tool_input,
            session: input.session_id
          });
          
          return { continue: true };
        }
      ]
    }
  ]
};

Validação de operações de arquivo

const hooks = {
  PreToolUse: [
    {
      matcher: "Write|Edit",
      hooks: [
        async (input) => {
          const filePath = input.tool_input.file_path;
          
          // Bloquear arquivos sensíveis
          const sensitivePatterns = ['.env', '.git/', 'secrets/', '*.key'];
          
          for (const pattern of sensitivePatterns) {
            if (filePath.includes(pattern)) {
              return {
                decision: 'block',
                stopReason: `Não é possível modificar arquivo sensível correspondente a ${pattern}`
              };
            }
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Auto-formatação de código

import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

const hooks = {
  PostToolUse: [
    {
      matcher: "Write|Edit|MultiEdit",
      hooks: [
        async (input) => {
          const filePath = input.tool_response.filePath;
          
          // Auto-formatar baseado no tipo de arquivo
          if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
            await execAsync(`prettier --write "${filePath}"`);
          } else if (filePath.endsWith('.py')) {
            await execAsync(`black "${filePath}"`);
          }
          
          return { continue: true };
        }
      ]
    }
  ]
};

Melhoria de prompt

const hooks = {
  UserPromptSubmit: [
    {
      hooks: [
        async (input) => {
          // Adicionar contexto aos prompts
          const projectContext = await loadProjectContext();
          
          return {
            continue: true,
            hookSpecificOutput: {
              hookEventName: 'UserPromptSubmit',
              additionalContext: `Contexto do projeto: ${projectContext}`
            }
          };
        }
      ]
    }
  ]
};

Instruções de compactação personalizadas

const hooks = {
  PreCompact: [
    {
      hooks: [
        async (input) => {
          const trigger = input.trigger; // 'manual' ou 'auto'
          
          return {
            continue: true,
            systemMessage: 'Foque em preservar detalhes de implementação e resoluções de erro'
          };
        }
      ]
    }
  ]
};

Comportamento de execução de hook

  • Paralelização: Todos os hooks correspondentes executam em paralelo
  • Timeout: Hooks respeitam o sinal de aborto das opções
  • Tratamento de erro: Erros de hook são registrados mas não param a execução
  • Matchers: Suportam padrões regex (ex: "Write|Edit")

Combinando hooks com canUseTool

Enquanto canUseTool fornece controle de permissão, hooks oferecem integração mais ampla do ciclo de vida:
for await (const message of query({
  prompt: "Construir a funcionalidade",
  options: {
    // Controle de permissão refinado
    canUseTool: async (toolName, input) => {
      // Modificar entradas ou negar baseado em condições de tempo de execução
      return { behavior: "allow", updatedInput: input };
    },
    
    // Hooks de ciclo de vida para monitoramento e automação
    hooks: {
      PreToolUse: [
        {
          hooks: [
            async (input) => {
              // Registrar, validar ou preparar
              return { continue: true };
            }
          ]
        }
      ]
    }
  }
})) {
  // Processar mensagens
}

Controle de permissão com canUseTool

O callback canUseTool fornece controle refinado sobre execução de ferramentas. É chamado antes de cada uso de ferramenta e pode permitir, negar ou modificar entradas de ferramenta:
type ToolPermissionResult = 
  | { behavior: "allow"; updatedInput?: any }
  | { behavior: "deny"; message?: string };

for await (const message of query({
  prompt: "Analisar comportamento do usuário e calcular métricas",
  options: {
    mcpServers: {
      "analytics": analyticsServer
    },
    canUseTool: async (toolName: string, input: any) => {
      // Controlar quais ferramentas podem ser usadas
      if (toolName.startsWith("mcp__analytics__")) {
        // Verificar permissões para ferramentas de analytics
        const hasPermission = await checkUserPermissions(toolName);
        
        return hasPermission
          ? { behavior: "allow", updatedInput: input }
          : { behavior: "deny", message: "Permissões insuficientes" };
      }
      
      // Modificar entradas para certas ferramentas
      if (toolName === "Bash") {
        // Adicionar verificações de segurança ou modificar comandos
        const safeInput = sanitizeBashCommand(input);
        return { behavior: "allow", updatedInput: safeInput };
      }
      
      // Permitir outras ferramentas por padrão
      return { behavior: "allow", updatedInput: input };
    }
  }
})) {
  if (message.type === "result") console.log(message.result);
}

Casos de uso para canUseTool

  • Gerenciamento de permissões: Verificar permissões do usuário antes de permitir execução de ferramenta
  • Validação de entrada: Validar ou sanitizar entradas de ferramenta antes da execução
  • Limitação de taxa: Implementar limites de taxa para operações caras
  • Log de auditoria: Registrar uso de ferramenta para conformidade ou depuração
  • Permissões dinâmicas: Habilitar/desabilitar ferramentas baseado em condições de tempo de execução
// Exemplo: Limitador de taxa para web scraping
const rateLimits = new Map<string, { count: number; resetTime: number }>();

const canUseTool = async (toolName: string, input: any) => {
  // Limitar taxa de web scraping para prevenir banimentos de IP e problemas de cota de API
  if (toolName === "WebFetch" || toolName === "WebSearch") {
    const now = Date.now();
    const limit = rateLimits.get(toolName) || { count: 0, resetTime: now + 60000 };
    
    // Resetar contador a cada minuto
    if (now > limit.resetTime) {
      limit.count = 0;
      limit.resetTime = now + 60000;
    }
    
    // Permitir máximo 10 requisições por minuto
    if (limit.count >= 10) {
      return { 
        behavior: "deny", 
        message: `Limite de taxa excedido: máximo 10 requisições ${toolName} por minuto. Reseta em ${Math.ceil((limit.resetTime - now) / 1000)}s` 
      };
    }
    
    limit.count++;
    rateLimits.set(toolName, limit);
    
    // Registrar atividade de scraping para monitoramento
    console.log(`Requisição ${toolName} ${limit.count}/10 para: ${input.url || input.query}`);
  }
  
  // Prevenir loops infinitos acidentais em scripts bash
  if (toolName === "Bash" && input.command?.includes("while true")) {
    return { 
      behavior: "deny", 
      message: "Loops infinitos não são permitidos" 
    };
  }
  
  return { behavior: "allow", updatedInput: input };
};

Formatos de saída

Saída de texto (padrão)

// Saída de texto padrão
for await (const message of query({
  prompt: "Explicar arquivo src/components/Header.tsx"
})) {
  if (message.type === "result" && message.subtype === "success") {
    console.log(message.result);
    // Saída: Este é um componente React mostrando...
  }
}

Saída JSON

// Coletar todas as mensagens para acesso tipo JSON
const messages = [];
for await (const message of query({
  prompt: "Como funciona a camada de dados?"
})) {
  messages.push(message);
}

// Acessar mensagem de resultado com metadados
const result = messages.find(m => m.type === "result" && message.subtype === "success");
console.log({
  result: result.result,
  cost: result.total_cost_usd,
  duration: result.duration_ms
});

Formatos de entrada

// Prompt direto
for await (const message of query({
  prompt: "Explicar este código"
})) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

// De variável
const userInput = "Explicar este código";
for await (const message of query({ prompt: userInput })) {
  if (message.type === "result" && message.subtype === "success") console.log(message.result);
}

Exemplos de integração de agente

Agente de resposta a incidentes SRE

import { query } from "@anthropic-ai/claude-code";

// Agente automatizado de resposta a incidentes
async function investigateIncident(
  incidentDescription: string,
  severity = "medium"
) {
  const messages = [];

  for await (const message of query({
    prompt: `Incidente: ${incidentDescription} (Severidade: ${severity})`,
    options: {
      appendSystemPrompt: "Você é um especialista SRE. Diagnostique o problema, avalie o impacto e forneça itens de ação imediatos.",
      maxTurns: 6,
      allowedTools: ["Bash", "Read", "WebSearch", "mcp__datadog"],
      mcpConfig: "monitoring-tools.json"
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// Uso
const result = await investigateIncident("API de pagamento retornando erros 500", "high");
console.log(result.result);

Revisão de segurança automatizada

import { query } from "@anthropic-ai/claude-code";
import { execSync } from "child_process";

async function auditPR(prNumber: number) {
  // Obter diff do PR
  const prDiff = execSync(`gh pr diff ${prNumber}`, { encoding: 'utf8' });

  const messages = [];
  for await (const message of query({
    prompt: prDiff,
    options: {
      appendSystemPrompt: "Você é um engenheiro de segurança. Revise este PR para vulnerabilidades, padrões inseguros e problemas de conformidade.",
      maxTurns: 3,
      allowedTools: ["Read", "Grep", "WebSearch"]
    }
  })) {
    messages.push(message);
  }

  return messages.find(m => m.type === "result" && message.subtype === "success");
}

// Uso
const report = await auditPR(123);
console.log(JSON.stringify(report, null, 2));

Assistente jurídico multi-turno

import { query } from "@anthropic-ai/claude-code";

async function legalReview() {
  // Iniciar sessão de revisão jurídica
  let sessionId: string;

  for await (const message of query({
    prompt: "Iniciar sessão de revisão jurídica",
    options: { maxTurns: 1 }
  })) {
    if (message.type === "system" && message.subtype === "init") {
      sessionId = message.session_id;
    }
  }

  // Revisão multi-etapa usando a mesma sessão
  const steps = [
    "Revisar contract.pdf para cláusulas de responsabilidade",
    "Verificar conformidade com requisitos GDPR",
    "Gerar resumo executivo de riscos"
  ];

  for (const step of steps) {
    for await (const message of query({
      prompt: step,
      options: { resume: sessionId, maxTurns: 2 }
    })) {
      if (message.type === "result" && message.subtype === "success") {
        console.log(`Etapa: ${step}`);
        console.log(message.result);
      }
    }
  }
}

Esquema de mensagem

Mensagens retornadas da API JSON são estritamente tipadas de acordo com o seguinte esquema:
type SDKMessage =
  // Uma mensagem do assistente
  | {
      type: "assistant";
      uuid: string;
      session_id: string;
      message: Message; // do SDK Anthropic
      parent_tool_use_id: string | null;
    }

  // Uma mensagem do usuário (entrada)
  | {
      type: "user";
      uuid?: string;
      session_id: string;
      message: MessageParam; // do SDK Anthropic
      parent_tool_use_id: string | null;
    }

  // Uma mensagem do usuário (saída/replay com UUID obrigatório)
  | {
      type: "user";
      uuid: string;
      session_id: string;
      message: MessageParam; // do SDK Anthropic
      parent_tool_use_id: string | null;
    }

  // Emitida como a última mensagem em sucesso
  | {
      type: "result";
      subtype: "success";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      result: string;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // Emitida como a última mensagem em erro ou turnos máximos
  | {
      type: "result";
      subtype: "error_max_turns" | "error_during_execution";
      uuid: UUID;
      session_id: string;
      duration_ms: number;
      duration_api_ms: number;
      is_error: boolean;
      num_turns: number;
      total_cost_usd: number;
      usage: Usage;
      permission_denials: SDKPermissionDenial[];
    }

  // Emitida como a primeira mensagem no início de uma conversa
  | {
      type: "system";
      subtype: "init";
      uuid: UUID;
      session_id: string;
      apiKeySource: "user" | "project" | "org" | "temporary";
      cwd: string;
      tools: string[];
      mcp_servers: {
        name: string;
        status: string;
      }[];
      model: string;
      permissionMode: "default" | "acceptEdits" | "bypassPermissions" | "plan";
      slash_commands: string[];
      output_style: string;
    };

  type SDKPermissionDenial = {
    tool_name: string;
    tool_use_id: string;
    tool_input: Record<string, unknown>;
  }

Tipos de suporte adicionais: Os tipos Message, MessageParam e Usage estão disponíveis no SDK TypeScript da Anthropic.

Recursos relacionados