Agents precisam de fluxo de controle, não de mais prompts
(bsuh.bearblog.dev)- Agentes que lidam com tarefas complexas de forma confiável precisam não de cadeias de prompts mais sofisticadas, mas de um fluxo de controle determinístico codificado no software
- Se você depende de expressões como MANDATORY ou DO NOT SKIP no prompt, isso significa que já chegou ao limite do prompting
- Imagine uma linguagem de programação em que frases funcionam como sugestões e funções alucinam ao retornar “Success”; à medida que a complexidade cresce, torna-se impossível raciocinar sobre o sistema e a confiabilidade desmorona
- O software escala por meio da composicionalidade recursiva formada por bibliotecas, módulos e funções, e isso permite raciocínio local porque oferece comportamento previsível
- Cadeias de prompts são úteis para tarefas restritas, mas não têm as mesmas propriedades, pois são não determinísticas, fracamente especificadas e difíceis de verificar
Estrutura necessária para a confiabilidade de agentes
- Para garantir confiabilidade, é preciso tirar a lógica das explicações em linguagem natural e levá-la para o runtime
- A estrutura necessária é um scaffold determinístico que trata o LLM não como o sistema inteiro, mas como um componente
- Esse scaffold deve incluir transições de estado explícitas e checkpoints de validação
- Orquestração determinística por si só não basta; sistemas que podem falhar silenciosamente precisam de detecção agressiva de erros
- Sem validação programática, as opções se reduzem a três
-
Babá (Babysitter)
- Uma pessoa precisa continuar no loop para detectar erros antes que eles se propaguem
-
Auditor (Auditor)
- É preciso verificar minuciosamente todo o resultado depois que a execução termina
-
Oração (Prayer)
- Passa-se a depender de aceitar o resultado pelo feeling
-
1 comentários
Comentários do Hacker News
Concordo 1000%. Está cada vez mais difícil acreditar no tamborilar da Anthropic de “construa mirando no desempenho dos modelos do futuro, eles vão melhorar em breve”
Criei um agente de QA que vasculhava 200 arquivos Markdown de requisitos em uma sessão de navegador, e era um bom sistema que aumentou bastante a eficiência da equipe. Mas quando deixei para o modelo um fluxo de controle de alto nível, tipo “olhe os arquivos de requisitos deste diretório e, para cada arquivo, crie itens de tarefa para verificar se o app atende àqueles requisitos”, tudo começava a desmoronar por volta de 30 arquivos
Ele deixava arquivos de fora, ou testava alguns grupos de arquivos três vezes, fazendo uma tarefa de 3 minutos levar 10, ou ainda retestava sem motivo os 4 arquivos anteriores por causa de um erro em um único arquivo. No Opus 4.6 e no GPT 5.4, e também em testes rápidos com Opus 4.7 e GPT 5.5, a capacidade de orquestrar workflows era inconsistente
No fim, criei um harness determinístico muito simples em volta do modelo, chamando o modelo para cada caso de teste, salvando os resultados em um array e depois gravando em arquivo, e a confiabilidade do sistema melhorou absurdamente. Mas plataformas de agentes gerenciados como Cursor Cloud Agents ou Anthropic parecem obcecadas demais com a ideia de que “o agente tem que executar tudo”, e não parecem enxergar o valor de inserir um pouco de determinismo nos pontos certos
Porque isso joga água fria na alegação de que essa tecnologia vai substituir pessoas inteiras, workflows inteiros ou projetos inteiros. Ainda acho que ela pode aumentar muito a produtividade e ter um efeito desastroso no mercado de contratação e nos salários de desenvolvedores, mas não parece que a versão atual dessa tecnologia vá chegar no nível que eles anunciam. Se tivessem posicionado isso como “uma ferramenta muito útil que reduz boa parte do trabalho chato de uma equipe humana de desenvolvimento”, os desenvolvedores iam querer, mas executivos iam querer menos, e os investidores provavelmente não deixariam passar
Além disso, etapas minuciosas e fortemente controladas combinam muito melhor com modelos menores, mais baratos e especializados do que com modelos enormes capazes de escrever, num instante, 5 volumes de fanfic de CSI
Alguns benchmarks não deixam o modelo tentar várias vezes o mesmo problema e depois ignoram a taxa de falha, adotando só o resultado caso tenha acertado pelo menos uma vez?
apply_patchcomcheck_compilationerun_unit_tests. O nome da ferramenta continua sendoapply_patch, mas agora, se o patch dá certo, ela também retorna informações adicionais sobre build e testesA taxa de sucesso do agente subiu de algo como 80% para um nível que, até agora, parece quase determinístico. Agora eu nem preciso explicar no prompt o processo de compilação e de testes unitários; basta que ele rode com certas dependências e devolva o resultado
Também sinto que isso vai contra a moda do momento. Faz muito tempo que uso tokens pré-pagos e harnesses customizados, e simplesmente funciona bem. Dá para ignorar a maior parte das notícias. Em problemas explicitamente visados, ferramentas estilo Copilot já não servem para muita coisa e, em algumas codebases, mesmo usando o mesmo modelo base GPT 5.4, a diferença de desempenho é de outra ordem de grandeza
Todo mundo deixa esse padrão passar batido nas skills. Se você coloca código ao lado de
SKILL.md, consegue garantir certos comportamentos, mas por algum motivo todo mundo está viciado em escrever prompts. Nem precisa criar uma CLI; um simplesskill.pycom a tarefa dentro já basta. Você ainda pode ter um helper chamandoclaude -pSeria engraçado se, daqui a alguns anos, as pessoas ainda usassem LLMs, mas no fim só conseguissem usá-los por meio de um vocabulário e gramática controlados que precisassem aprender. Igual a 15 anos atrás, quando todo mundo migrou para NoSQL e logo em seguida recriou schemas dentro de JSON
Acho que parte do problema talvez seja que estamos aplicando LLMs da forma errada desde o começo. Como já apareceu em outros lugares, talvez o prompt do agente devesse ser: escreva código que execute a tarefa de uma maneira o mais repetível, verificável e determinística possível
A validação da saída do agente também deveria estar incluída. O objetivo geral é tirar o LLM de tarefas que um programa consegue fazer com mais eficiência e muitas vezes com mais precisão
É ruim colocar IA em produção fazendo algo diretamente por chamada de API. Na minha visão, o único uso que a IA deve ter num app é para leitura, classificação e coisas assim. É como substituir o “R” de um app CRUD antigo
Usar esse mesmo endpoint de “R” baseado em IA para preencher automaticamente formulários de “C”, “U” e “D” conforme o prompt é aceitável, mas ele não deve alterar nada para o cliente antes de revisão humana. Apps CRUD continuam sendo apps CRUD e continuarão sendo; o que surgiu foi só um endpoint de “R” muito inteligente que sugere ações ou faz autocomplete de formulários para clientes, ferramentas internas, pipelines do Jenkins etc. Ele pode sugerir ações, mas não executá-las diretamente
llm -> prompt -> result, depoisllm -> prompt + prompt encoded as skill -> result, e depoisllm -> prompt + deterministic code encoded as skill -> resultFazer o prompt gerar código logo no início pode encurtar o caminho até código determinístico, mas ainda assim você está colocando código determinístico dentro de um wrapper não determinístico. Para ter sucesso em tarefas de longo prazo, muitas vezes é preciso uma camada de determinismo que está faltando
É preciso colocar código determinístico fora da fronteira não determinística, por meio de um loop de agente ou framework. Aí você fica com algo como
fluxo de agente determinístico -> tomada de decisão não determinística -> ferramenta determinística, com o julgamento não determinístico espremido entre camadas determinísticas. Em experimentos, isso foi um padrão muito forte, e fica ainda mais forte quando o agente cria seu próprio determinismo com ferramentas como auto-researcherAgora usamos uma pequena linguagem específica de domínio e uma única ferramenta, e o agente fornece como entrada um script escrito nessa linguagem. Isso lida com casos de uso mais dinâmicos, e erros de sintaxe são facilmente pegos pelo parser e devolvidos ao agente
A equipe de controle de hardware entregava a especificação em documentos e planilhas, e a equipe mobile olhava aquilo, codava a biblioteca de interface e depois validava com o servidor. Eu converti os documentos para TSV e enviei partes ao Claude para que ele escrevesse um parser TSV que preservasse nuances da especificação escrita por humanos
Foram necessárias mais de 150 iterações para cobrir todos os casos de borda e gerar resultados intermediários em JSON. Depois, o Claude ajudou a escrever um gerador de código que adicionava código de cola customizado sobre o Apollo para gerar o código consumido pelo app mobile
Todo esse pipeline roda como parte do Github Actions, e só chama o Claude quando o validador da biblioteca falha. Quando falha, há um arquivo md incluído na solicitação pedindo que ele descubra o que deu errado, proponha uma solução e crie um PR. Depois disso, uma pessoa revisa, ajusta e faz o merge. O custo total em créditos até aqui foi inferior a 350 dólares
Concordo com a intenção, mas acho que a conclusão precisa mudar. Quando você bate no limite dos prompts, em vez de tentar usar o LLM para executar a tarefa em tempo de execução, deveria usar o LLM para escrever o software que executará a tarefa
Em tempo de execução, o papel do LLM tende a se reduzir a ajudar o usuário a escolher entradas que se encaixem em um sistema de software com regras de negócio rígidas já embutidas
Na primeira semana, os prompts só cresciam e o desempenho só piorava. Na segunda, foquei em definir com precisão objetos como notas, tarefas, projetos e pessoas, e em definir métodos que executassem operações bem definidas sobre esses objetos. Como você apontou, a superfície do agente encolhe para uma camada de tradução que converte linguagem natural em comandos e argumentos que passam por validadores de entrada
Um LLM assim talvez tivesse ido melhor no teste do strawberry
Fiz o Claude escrever por conta própria alguns scripts shell para lidar com casos comuns no meu workflow, como rodar testes. Agora, em vez de ficar rodando em círculos por 30 minutos, ele executa essas ferramentas e conclui a configuração
Sempre que ele pede permissão para rodar um shell esquisito de uso único ou uma one-liner estranha em Python para fazer alguma coisa, eu me pergunto se não deveria fazer com que ele usasse uma ferramenta que pudesse ser aprovada automaticamente
É por isso que muitas vezes falo em “IA de próxima geração”. Não estou falando apenas de LLMs. LLMs são bem legais e, mesmo sem mais avanços fundamentais, ainda devem continuar gerando valor ao serem usados e otimizados de maneiras mais interessantes
Mas certas partes parecem precisar, de alguma forma, de uma melhoria fundamental de próxima geração. O fato de um LLM tornar difuso um “nunca faça X” e, depois de muito contexto, acabar tratando isso como “por favor faça X” parece algo próximo do núcleo do modo como funciona. É fácil esquecer isso no entusiasmo inicial de descobrir o que ainda conseguimos fazer, mas LLMs não são tudo o que procuramos em IA
Tem que existir uma estrutura que trate “nunca faça X” como um humano trataria. Também precisa existir uma estrutura com uma hierarquia de memória parecida com a humana, em vez de uma simples “janela de contexto”. Duas pessoas mantendo uma conversa longa o suficiente, mesmo que no começo estivessem falando com a mesma IA, acabariam tendo duas IAs realmente diferentes, e não só duas janelas de contexto diferentes
Claro, ninguém sabe como isso vai parecer. Só não há motivo para achar que LLMs sejam a resposta final da IA
Discordo, vindo de um ciclo completo de imposição por prompt → fluxo determinístico → imposição por prompt
O motivo de “não pule” falhar é que o agente está com trabalho demais e outras coisas no contexto acabam desviando a atenção dessa instrução
Mas ninguém disse que o agente encarregado de impor regras precisa ser o mesmo agente que constrói. Dá para codificar algum nível de lógica inteligente de decisão em um fluxo de controle determinístico, mas se você o tornar rígido demais ele não funciona bem, e se o tornar complexo demais, talvez usar agentes acabe saindo mais barato em custo de configuração e manutenção
Basicamente, o que você precisa são três tipos de agentes: um supervisor que gerencia o loop e aciona o que for apropriado quando há problema, um orquestrador que delega ao agente certo e impõe guardrails onde necessário, e trabalhadores que executam as unidades de trabalho
Na minha visão, todos os harnesses estão errados nesse aspecto, e alguns estão muito errados
Por exemplo, comandos slash são um recurso equivocado. Você não deveria precisar esperar o chatbot terminar um turno para conferir o estado da janela de contexto ou quanto dinheiro foi gasto nesta sessão. O controle deveria ser ortogonal ao loop de chat
Coisas que não têm nada a ver com controlar entrada e saída do gerador de texto estão amarradas ao comportamento de chat só porque “é um chat, então vamos tocar isso como se fosse um bot de IRC”
Hoje existem muitos agentes com LLM, mas quase nenhum separa de forma correta controle, loop do agente e camada de apresentação. Alguns pelo menos têm modo headless, e isso já é bom
/statusfunciona bem até no meio de um turnoNos outros não
Também é mais prático para navegar entre conversas e ver atualizações. Às vezes uso Claude Code ou opencode no terminal, mas a experiência é muito pior comparada ao app desktop do Codex
A frase “imagine uma linguagem de programação em que sentenças são sugestões e funções alucinam e retornam ‘Success’. Fica impossível raciocinar, e a confiabilidade desmorona à medida que a complexidade cresce” é essencialmente mais próxima de programação declarativa
A maior parte da programação tradicional é imperativa, familiar aos desenvolvedores. Você dá um conjunto exato de instruções e espera que sejam seguidas como foram escritas. Agentes estão muito mais próximos do declarativo do que do imperativo: você dá o resultado desejado e eles trabalham para alcançá-lo
Claro, em sistemas declarativos como SQL, o resultado costuma ser bem consistente e bem definido, mas ainda assim você está confiando no engine interno para decidir como processar aquilo. Pensar em agentes como algo declarativo me ajudou muito mais do que tentar projetar um sistema de “controle” estilo Rube Goldberg. Se não bater, você valida, informa que está errado e tenta de novo ou escolhe outra abordagem
Se você realmente precisa de algo imperativo, então escreva de forma imperativa. Ou mande o agente escrever assim. Isso parece mais uma tentativa de usar uma ferramenta inadequada para a tarefa
Pode parecer declarativo, mas isso só acontece dentro de uma ilusão. Na prática, não estamos descrevendo objetivos para a IA e deixando que ela os interprete; temos um documento de história em que um personagem substituto de humano conversa com um personagem-computador, e nós, no mundo real, esperamos que o LLM cole uma narrativa mais coesa por trás disso e daí extraia algo útil
Não é uma distinção meramente acadêmica. Entender que existe uma história ajuda a criar modelos melhores para compreender a relação entre entrada e saída e montar estratégias. Por exemplo, ajuda a entender riscos como prompt injection e também dá orientação sobre que dados de treinamento incluir ou excluir
Aí você esbarra em problemas parecidos com os dos LLMs: falhas silenciosas, repetição e contradições, a menos que tome muito cuidado. A essência pode ser o mesmo problema de suposição de mundo fechado. Nos LLMs, isso aparece como alucinação em vez de admitir que não sabe
E, como você disse, se instruir um LLM não determinístico de forma declarativa para “me leve a esse estado final”, a chance de ele sair dos trilhos é ainda maior
Mas a própria consulta não muda de uma execução para outra como acontece com um LLM
Tenho pensado bastante nesse problema. Isso também pode se conectar à discussão sobre especialização. Quanto mais especializado o modelo fica, mais parece perder capacidades de base, e talvez mirar em um pouquinho de abstração permita obter vantagens dos dois lados
É um exemplo bem específico, mas dá o que pensar
Resumo de 20 minutos do podcast: https://pub-6333550e348d4a5abe6f40ae47d2925c.r2.dev/EP008.ht...
Artigo: https://arxiv.org/abs/2605.00225
Isso já era visível na época do Auto-GPT, em 2023. As pessoas deixavam o GPT “dirigir”, mas na maioria dos casos o que realmente precisavam eram dez linhas de Python e talvez algumas chamadas de função
llm()A alternativa era executar essas dez linhas de Python da forma mais cara, lenta e menos confiável possível. Claro que isso foi popular
Por exemplo, a maioria usava agentes para pesquisa na internet. Eles ficavam rodando por horas, se distraíam ou esqueciam o que estavam fazendo
Enquanto isso, com
import duckduckgoeimport llm, você pode escrever dez linhas de código que fazem a mesma coisa em 20 segundos, de forma realmente determinística e custando 50 vezes menosOs modelos atuais são muito melhores, e hoje eles já melhoraram o suficiente para que algo como Auto-GPT pareça viável. Mas continuar executando um fluxo de controle mal especificado da maneira mais cara possível ainda é uma péssima ideia