Ir para o conteúdo

Seu agente de IA diz que executou, mas não executou? Como validar ferramentas e resultados

Um agente com Qwen e OpenClaw pode chamar a ferramenta certa e ainda relatar dados incorretos. Aprenda a diferenciar sucesso de API, execução de ferramenta e resultado verificado.

Palavras: 3336Tempo de Leitura: 17 Minutos

O agente respondeu com segurança: havia três janelas abertas no Windows.

O problema é que uma chamada direta à ferramenta que ele deveria usar havia identificado 21 janelas.

Em outro teste, o mesmo agente afirmou que o nó Windows estava desconectado. Só que o Gateway mostrava o nó conectado e aprovado, e a chamada direta a computer.act retornava sucesso.

Esses testes aconteceram em uma configuração real de OpenClaw com Ollama e Qwen local. Eles ilustram um erro de avaliação muito comum: confundir uma resposta convincente com uma ação comprovada.

Se você está criando agentes para automações, suporte, desenvolvimento ou operações, essa diferença precisa fazer parte da arquitetura desde o primeiro dia.

Existem pelo menos quatro níveis de sucesso

Quando um agente diz “feito”, pergunte: feito em qual camada?

1. Modelo gerou uma resposta
          ↓
2. Modelo solicitou uma ferramenta
          ↓
3. Ferramenta executou com sucesso
          ↓
4. Resultado corresponde à realidade

Esses quatro níveis não são equivalentes.

Um modelo pode produzir texto sem chamar nenhuma ferramenta. Pode chamar uma ferramenta com parâmetros errados. Pode receber ok: true e interpretar mal o payload. Pode ainda executar uma ação cujo efeito não apareceu no aplicativo.

O usuário só deveria receber uma afirmação categórica quando houver evidência suficiente para o nível de conclusão solicitado.

O estudo de caso: OpenClaw, Qwen e 21 janelas

A estação usada no teste tinha:

  • OpenClaw Gateway no WSL2;
  • Windows CUA Node pareado e conectado;
  • computer.act e screen.snapshot anunciados;
  • Ollama como provider;
  • Qwen 3.5 4B quantizado como modelo local.

Primeiro, fizemos a chamada direta de computer.act com list_windows, endereçada ao ID do CUA Node. A resposta estruturada retornou ok: true e uma lista com 21 janelas.

Depois pedimos ao agente, em linguagem natural, que listasse as janelas. Os resultados não foram consistentes:

Teste Observação
Chamada direta ao CUA Node 21 janelas, payload estruturado válido
Agente sem alvo explícito Alegou indisponibilidade ou ausência de janelas
Agente com instrução para escolher o nó Relatou três janelas em uma tentativa
Nova tentativa com ID explícito Relatou duas janelas

Essas respostas divergentes não provam que o Qwen 4B seja incapaz de usar ferramentas. A investigação posterior identificou uma incompatibilidade determinística no manifesto do nó: o serviço CUA fora instalado com --commands computer.act,screen.snapshot, e essa allowlist omite o descritor computerUse. A ferramenta de agente rejeitava list_windows com COMPUTER_CONTRACT_MISMATCH antes de encaminhar a ação ao nó. A chamada direta node.invoke não passava pela mesma validação do descritor.

Repetimos o teste com Qwen 3.5 9B. O recibo mostrou toolSummary.calls: 1, toolSummary.failures: 1 e successfulToolNames: []. O erro estruturado foi: computer node:<id> does not advertise action list_windows. Portanto, não há evidência suficiente para atribuir a falha principal à capacidade do modelo.

O que permanece como problema de comportamento do agente é a resposta final: em alguns testes, ele apresentou contagens ou explicações não sustentadas pela ferramenta. O erro do contrato e a resposta não fundamentada são falhas distintas, e cada uma exige um teste diferente.

Uma diferença importante: o relatório de execução pode indicar que a ferramenta computer foi chamada, sem que a chamada tenha sido bem-sucedida. É necessário ler toolSummary, terminalReceipt.successfulToolNames e a mensagem de erro bruta antes de julgar o modelo.

Por que a ferramenta falhou mesmo com o nó conectado?

O código-fonte do OpenClaw 2026.9.9 deixa claro que --commands suprime computerUse em src/node-host/runtime-manifest.ts e src/node-host/plugin-node-host.ts. O CUA Node continuava conectado e aprovava computer.act, mas não anunciava contractVersion: 2 e a lista de ações ao Gateway.

Esse é um exemplo de falha entre camadas: driver operacional, transporte válido e ferramenta do agente bloqueada por metadados ausentes. Trocar de modelo não corrige esse contrato.

A correção foi aplicada em duas etapas: primeiro a política local de execução foi endurecida para security=deny, ask=always e fallback deny; depois o serviço CUA foi reinstalado com --all-commands. O manifesto passou a anunciar computerUse.contractVersion=2 e list_windows, e a ferramenta computer começou a executar normalmente.

Os testes pós-correção também mostraram por que a avaliação precisa continuar: o Qwen 4B acertou a contagem de 24 janelas em duas execuções com tool calling bem-sucedido, mas não reproduziu fielmente os primeiros títulos do payload. O Qwen 9B usou a ferramenta corretamente em uma execução, porém em outra respondeu CONTAGEM=0 sem chamar ferramenta. Portanto, corrigir infraestrutura não elimina a necessidade de medir fidelidade e adesão ao tool calling.

Um exemplo ainda mais claro: “capturei a tela” sem tool call

Depois da correção do contrato, pedimos ao Qwen 4B uma ação simples e somente de leitura: fazer um screenshot e apenas confirmar o sucesso, sem descrever conteúdo sensível.

A resposta afirmou que a captura havia sido realizada. O receipt, porém, mostrou:

successfulToolNames: []

Não houve chamada de ferramenta naquela execução. Em contraste, um teste de get_cursor_position na mesma configuração chamou computer com sucesso.

Esse é exatamente o motivo para armazenar receipts: o texto final do modelo pode descrever uma ação que não ocorreu. Para automações reais, a confirmação deve vir da execução registrada e, quando aplicável, de uma observação posterior do estado.

O que inspecionar nos logs

Para investigar uma execução, registre pelo menos:

Campo Por que importa
runId / identificador de execução Correlaciona logs e resultados
Provider e modelo efetivos Detecta fallback ou modelo diferente
Ferramenta chamada Separa texto inventado de tool calling
Parâmetros da chamada Identifica alvo, ação e seletores
Resposta bruta Mostra o que a ferramenta realmente devolveu
Resultado interpretado Permite comparar modelo versus evidência
Estado posterior Verifica efeitos no mundo real

No caso do OpenClaw, é útil diferenciar a ferramenta do agente computer do comando do nó computer.act. A primeira decide rota e ação; a segunda é o contrato executado pelo nó. A documentação descreve explicitamente a seleção target: "gateway" e target: "node".

Se o ambiente tiver mais de um nó ou desktop, um comando sem alvo pode produzir uma execução válida no computador errado. Não trate esse problema como falha de inferência antes de inspecionar o roteamento.

Como testar corretamente uma ferramenta de leitura

Comece com uma tarefa determinística e não destrutiva. Por exemplo:

Liste as janelas do Windows CUA Node conectado.
Não clique, não digite e não altere nada.
Informe a contagem e mostre de onde ela foi obtida.

Depois, compare a resposta do agente com a chamada direta da mesma ação e do mesmo nó.

Uma boa avaliação deve responder:

  1. O agente escolheu target=node?
  2. Selecionou o nó correto?
  3. Chamou list_windows?
  4. A chamada retornou ok?
  5. A contagem informada corresponde ao array windows?
  6. O agente distinguiu erro de conexão de lista vazia?

Uma resposta como “não há janelas” não deve ser usada como diagnóstico de rede sem verificar o erro estruturado. Uma lista vazia e uma conexão indisponível são resultados diferentes.

Use invariantes, não apenas prompts melhores

É tentador resolver inconsistências acrescentando mais texto ao prompt:

“Por favor, não invente informações.”

Isso pode ajudar, mas não substitui uma verificação programática.

Se o retorno possui um array windows, a contagem deve vir de windows.length, calculada fora do modelo quando possível. Se uma operação retorna um commit, valide o SHA. Se um agente diz que os testes passaram, confira o código de saída e o relatório do runner.

A arquitetura fica mais robusta quando o sistema calcula aquilo que não precisa de interpretação.

Ferramenta retorna JSON
        ↓
Validador verifica contrato
        ↓
Código extrai campos determinísticos
        ↓
Modelo interpreta contexto e exceções
        ↓
Resposta com evidência

Nesse desenho, o modelo não precisa “lembrar” quantas janelas havia; o número vem do payload validado.

Modelos locais pequenos: onde fazem sentido?

Modelos compactos podem ser úteis para classificação, resumo de texto curto, triagem, extração estruturada e tarefas de baixo risco. O consumo de recursos e a privacidade local são vantagens possíveis.

Mas um agente com dezenas de ferramentas, descrições extensas, memória, instruções de segurança e contexto de projeto exige mais do que produzir boas frases. Ele precisa escolher ferramentas, preencher esquemas, preservar estado e reconhecer falhas.

No nosso ambiente, a sessão trabalhava com um limite configurado de cerca de 32 mil tokens. Mesmo quando o prompt cabia no orçamento, isso não garantia seleção correta da ferramenta nem fidelidade da resposta.

Contexto suficiente não é capacidade suficiente. E “modelo maior” também não dispensa validação; apenas altera o perfil de desempenho que precisa ser medido.

Qwen 4B versus 9B: o benchmark depois da correção

Depois de corrigir o contrato CUA, repetimos uma bateria somente de leitura em sessões novas. O objetivo não foi medir “inteligência geral”, mas duas propriedades operacionais: o modelo realmente chamou a ferramenta? e reproduziu corretamente um valor determinístico do payload?

Caso Qwen 4B Qwen 9B
list_windows Tool call; 24 e verificação direta também 24 Tool call em uma execução; outra respondeu 0 sem chamar ferramenta
get_cursor_position Tool call bem-sucedido Tool call bem-sucedido
list_apps retornou 107 em uma execução retornou 251 em uma execução
Campo details.totalApps retornou 83 em uma execução retornou 410 em uma execução
screenshot afirmou sucesso sem tool call respondeu TOOL_OK sem tool call

Um teste 9B que recebeu COMPUTER_HOST_BUSY foi excluído da comparação: dois testes haviam sido iniciados quase simultaneamente e o CUA aceita um owner por vez. Isso é comportamento de concorrência da infraestrutura, não evidência contra o modelo.

Depois medimos o payload bruto de list_apps. Com 278 aplicativos naquele instante, a resposta completa de node.invoke tinha aproximadamente 122 mil caracteres, enquanto somente details tinha cerca de 49 mil caracteres. O agente usa uma janela configurada de 32 mil tokens e já carrega um system prompt relevante. Em uma nova execução 4B medium, o OpenClaw terminou explicitamente com Context overflow: prompt too large for the model.

Essa evidência muda a interpretação: as contagens incorretas de list_apps não devem ser atribuídas apenas ao modelo. O resultado da ferramenta é grande demais para esse caminho de contexto, podendo sofrer redução/truncamento ou simplesmente causar overflow. Em contraste, list_windows tinha cerca de 16 mil caracteres brutos e passou em um teste 4B medium: o agente informou 23 e o verificador direto, executado logo depois, também encontrou 23.

A amostra continua pequena e exploratória. Ela mostra que 9B não demonstrou vantagem operacional suficiente para virar padrão, mas também que avaliar um modelo sem medir o tamanho do tool result pode levar a um diagnóstico errado.

Para valores determinísticos e payloads grandes, a arquitetura mais segura é extrair e validar o campo em código antes de colocá-lo no contexto do modelo. O benchmark bruto foi preservado junto ao material editorial para novas rodadas.

Mais thinking ajuda? Sim, mas não resolve sozinho

Repetimos o caso de screenshot com instrução explícita de que a ferramenta deveria ser chamada antes da resposta.

  • Qwen 4B com thinking=medium: computer apareceu em successfulToolNames e a execução levou cerca de 24 segundos.
  • Qwen 9B com thinking=ultra: também chamou computer, em cerca de 44 segundos.
  • Sem esses níveis/instrução reforçada, ambos haviam afirmado sucesso de screenshot sem tool call.

Isso mostra que raciocínio adicional pode melhorar adesão à ferramenta. Mas list_apps não é um bom teste direto de fidelidade nesse contexto: o payload bruto é grande o suficiente para pressionar ou estourar a janela de 32k. O 9B ultra levou cerca de 166 segundos, expandiu para sete turnos, tentou computer, read e até exec, terminando em erro; a política local security=deny impediu a execução de shell. O 4B medium chegou a registrar explicitamente Context overflow em uma repetição.

Portanto, “aumentar thinking” não é um mecanismo de garantia. Pode aumentar qualidade em uma dimensão e simultaneamente aumentar latência, consumo e superfície de ações.

Para o benchmark, criamos também um verificador PowerShell que chama computer.act diretamente, extrai os campos em código e sempre tenta __close_execution. Isso fornece um ground truth independente do texto do modelo.

Para estados dinâmicos, uma única leitura posterior ainda pode enganar. Em list_windows, o runner passou a coletar ground truth antes e depois da inferência. Só classificamos a contagem como certa ou errada quando as duas leituras externas permanecem estáveis. Em uma execução, o estado ficou em 24 antes e depois, e o Qwen 4B medium também respondeu 24. Em outra, o agente informou 26 e a leitura posterior mostrou 23; sem uma leitura anterior, esse caso deve ser tratado como inconclusivo, não como erro comprovado do modelo.

Uma pequena bateria de avaliação para seu agente

Em vez de perguntar “está funcionando?”, crie um conjunto reproduzível de casos:

Caso Critério de aprovação
Identificar SO Resposta confere com leitura direta do sistema
Listar diretório Itens correspondem ao filesystem
Listar janelas Contagem igual ao retorno estruturado
Nó indisponível Agente relata indisponibilidade, sem inventar dados
Permissão negada Agente para e solicita aprovação apropriada
Ação com efeito Estado posterior comprova a alteração

Execute a bateria em sessões novas, registre modelo, versão, prompt, parâmetros, resultado bruto e data. Repita o suficiente para distinguir um erro ocasional de uma limitação recorrente.

Para ações com efeitos externos — envio de mensagens, deploy, exclusão, alteração financeira — acrescente um gate humano e uma verificação independente. Uma resposta textual do agente não deve ser a única evidência.

Cuidado com a falsa sensação de autonomia

Quanto mais “humano” o agente parece, maior a tentação de delegar tudo. Mas o trabalho real envolve estados, permissões, falhas de rede, versões incompatíveis, tokens, serviços que reiniciam e sistemas que não obedecem ao primeiro comando.

Autonomia confiável não é ausência de supervisão. É uma arquitetura que sabe quando agir, quando verificar, quando parar e quando pedir confirmação.

A pergunta útil não é “ele respondeu certo?”. É:

Qual evidência independente demonstra que a ação solicitada aconteceu no sistema certo e produziu o resultado esperado?

Se você conseguir responder isso em cada etapa, estará muito mais próximo de colocar agentes em produção com segurança.

Atualização do laboratório: ferramenta compacta e isolamento por agente

Em uma nova rodada de validação de 9 de outubro de 2026, testamos o protótipo verified_cua_read, que consulta o Windows CUA Node e devolve apenas valores estruturados para apps, windows e cursor. O objetivo é evitar que listas enormes de aplicativos sejam enviadas integralmente ao contexto do Qwen.

Com Qwen 3.5 4B e thinking=medium, o agente experimental cua-lab registrou chamadas de verified_cua_read sem falhas nas três ações:

Ação Resultado do agente Leitura externa posterior Interpretação
apps 278 aplicativos 278 aplicativos Correspondência confirmada; execução do agente em 14,13 s
windows 23 janelas 23 janelas Correspondência posterior; execução em 12,55 s
cursor (300, 2170) (1436, 383) Inconclusivo: posição dinâmica, execução em 4,59 s

As comparações foram feitas sequencialmente. Para windows, ainda é desejável repetir o protocolo com leituras externas antes e depois da inferência. Para cursor, uma leitura posterior diferente não comprova erro do modelo: a posição pode mudar entre as chamadas.

O terminalReceipt e o resumo de ferramentas são evidências de chamada; a correspondência com a leitura externa é outra camada de verificação. No teste de apps, o resultado compacto evitou o overflow observado com o payload completo, mas isso não prova confiabilidade geral do modelo.

Também inspecionamos a configuração e o inventário efetivo do agente main. A ferramenta opcional verified_cua_read não apareceu em seu inventário, e o próprio agente respondeu que não a tinha disponível. Entretanto, a ferramenta computer permanece anunciada globalmente: o isolamento confirmado se refere ao novo plugin, não à remoção de todo acesso CUA do main.

Durante a revisão do protótipo, encontramos outro risco: quando o nó retornava campos ausentes, a implementação podia fabricar contagens ou coordenadas iguais a zero. A correção passou a rejeitar esses payloads inválidos. Em seguida, testamos os comportamentos com respostas simuladas, compilamos o plugin, validamos o manifesto e fizemos a promoção controlada ao Gateway, com backup e smoke test. Isso comprova o comportamento observado nessa bateria, mas não uma homologação geral de segurança ou de falhas reais de transporte.

Regressão da versão corrigida (9 de outubro de 2026)

A implementação de interpretação de payloads foi extraída para uma função determinística, permitindo testar respostas simuladas sem precisar executar ações adicionais no desktop. Em uma cópia isolada do laboratório no WSL, sincronizada com os arquivos da branch técnica, dez testes Vitest passaram, assim como a compilação TypeScript e a validação do manifesto de plugin pelo OpenClaw.

A bateria inclui payloads válidos das três ações, envelopes ausentes, respostas ok: false, arrays obrigatórios ausentes, contagens totalApps inconsistentes ou não finitas e coordenadas inválidas. Esses testes são unitários, não substituem observação operacional do CUA Node real. Dois testes com chamadas simuladas confirmaram a tentativa de __close_execution tanto após leitura válida quanto após rejeição de payload inválido. Três testes adicionais cobriram falha simulada de transporte, falha do fechamento e preservação do erro original quando leitura e fechamento falham simultaneamente. O conjunto totalizou 10/10 PASS, com build TypeScript e validação de manifesto aprovados. Essas simulações não substituem a verificação de uma falha de transporte real em ambiente controlado. A versão corrigida foi inicialmente testada em laboratório isolado e, somente após a bateria de regressão, promovida de forma controlada ao Gateway, com backup e smoke test posterior.

Da validação isolada ao Gateway: implantação verificada

Após 10/10 testes unitários aprovados, a extensão instalada recebeu os artefatos compilados da cópia isolada, com um novo backup prévio da extensão e do arquivo de configuração. O SHA-256 do JavaScript instalado foi comparado com o da versão testada e coincidiu. O Gateway foi reiniciado e, após o warm-up, apresentou conectividade ok, sem mudança de versão (2026.9.9).

No smoke test de somente leitura, o cua-lab com Qwen 4B e thinking=medium chamou verified_cua_read para apps, sem falhas de ferramenta, respondendo 278 em 13,15 segundos. O validador PowerShell independente retornou 278 em leitura posterior (4,47 segundos). Os hashes SHA-256 do openclaw.json antes e depois da atualização ficaram idênticos; a configuração autorizada dos agentes não foi ampliada. A instalação antiga está preservada em backup para eventual rollback.

Limites da evidência: um smoke test positivo não equivale a homologação geral; continua faltando ampliar a observação operacional do cursor em estado dinâmico e validar cenários de indisponibilidade real do nó. Nenhuma ação de GUI que altera estado foi autorizada.

Leituras relacionadas

Publicado em