O que é Adicionar Orçamento ao Loop?
Adicionar Orçamento ao Loop (Add Loop Budget) é uma refatoração de IA para sistemas com LLM, do grupo Movendo controle. Limitar passos, tempo e dinheiro de cada execução e definir o que acontece no limite.
Você conheceu o agente de faturas na aula passada. Ele abre o portal do fornecedor, clica em próxima página e lê a lista. Uma noite o botão continua visível e não carrega nada. Sem limite, o loop clica milhares de vezes, e o único alarme é a fatura.
O smell contou essa história. Esta refatoração coloca o freio. E você vai ver que o freio é só metade. A outra metade é o que o agente diz quando para.
Dê a toda execução um orçamento explícito, de passos, tempo e custo. Confira antes de cada turno. E defina o que o agente entrega quando o orçamento acaba.
Antes, a única saída é o modelo parar. Tarefa, modelo, ferramenta, e de novo. Até o modelo dizer que terminou.
Depois, o seu código tem uma segunda saída. A tarefa chega com um orçamento definido pela sua política, não pelo modelo.
Antes de cada turno, o código confere os passos, o tempo decorrido e o custo acumulado.
O modelo é chamado como sempre, e a resposta final continua sendo uma saída legítima. As ferramentas rodam, e o custo delas também conta, quando existe.
A tarefa termina dentro do orçamento.
Ou termina no limite, com o que foi encontrado até ali, e o motivo da parada.
No código, é uma mudança pequena. While true vira: enquanto o orçamento permitir. Com 25 passos, 5 minutos e 80 centavos.
Depois de cada chamada, o orçamento é cobrado com o consumo que a API informou.
E quando acaba, o agente encerra, com o motivo.
Com os mesmos números ilustrativos da última vez. Uma execução normal, dez turnos, uns cinquenta e dois mil tokens.
Uma execução presa sem limite, duzentos turnos, uns oito milhões e seiscentos mil.
E a mesma execução presa, com limite de vinte e cinco, uns duzentos mil. A curva nunca chega aos milhões.
E aqui está o encerramento no portal quebrado. Não uma exceção vazia. Li a primeira página, faturas um a vinte de trezentas e quarenta. Próxima página voltou ok, e a lista não mudou, três vezes. Parei por repetição. Faltam as páginas dois a dezessete.
A operação termina o trabalho na mão. E o trace vira um caso de eval.
Um loop de agente tem duas fontes de término. A decisão do modelo, e a decisão do código. Sem orçamento, só a primeira existe. E ela falha justamente nos casos ruins. Uma ferramenta que não progride, uma tarefa impossível, um conteúdo que confunde. O orçamento coloca uma decisão determinística bem ao lado da probabilística.
O encerramento é a metade que costuma faltar. Um limite que só lança exceção troca um custo alto por uma tarefa perdida. Um limite com encerramento entrega algo útil. Li catorze dos vinte arquivos, a causa provável é esta, ainda preciso confirmar aquela.
E o orçamento transforma mau comportamento em dado. Toda execução que bate no limite é um caso para entender. O limite revela o problema. Ele não existe para você esconder o problema subindo o número.
Uma pergunta para você. Entre as execuções de sucesso, 95% terminam em até catorze passos. O time quer um limite de dezesseis, para cortar cedo. O que você espera ver no eval?
O custo no máximo cai. E a taxa de conclusão das tarefas saudáveis cai junto. Cinco por cento das execuções de sucesso já passam de catorze passos, e algumas passam de dezesseis. Você cortaria os sucessos de hoje para economizar demais na execução presa de amanhã.
Um ponto de partida comum é duas a três vezes esse percentil 95. O limite deve pegar as execuções presas, não as longas.
Agora, o passo a passo. Passo zero, medir. Rode o eval do agente e tire dos traces a distribuição de passos, tempo e custo por tarefa.
Escolha os limites a partir desses dados. Se o percentil 95 é catorze passos, e o máximo saudável é dezenove, um limite de vinte e cinco dá folga. Um de duzentos, não.
Confira antes de cada chamada, não depois. Inclua o custo de ferramentas pagas, como busca ou navegador. E use o consumo que a API devolve, não uma tabela de preços desatualizada.
E cobre os subagentes do orçamento do pai. Passe para baixo o que sobrou. Não dê um orçamento novo para cada filho.
Escreva o encerramento. Uma última chamada curta, sem ferramentas, que resume o que foi feito e o que falta. Ou uma mensagem fixa com o estado. E o texto precisa dizer que parou no limite.
Registre o motivo da parada no trace. Passos, tempo, custo, repetição, ou concluído.
Coloque detecção de repetição. A mesma ferramenta, com os mesmos argumentos, três vezes seguidas, também encerra o loop.
E meça de novo. A taxa de conclusão não pode cair. O custo nos piores casos deve cair. E as tarefas que pararam no limite viram casos de eval.
Alguns riscos. Um limite baixo demais começa a derrubar tarefas longas legítimas. Você vê isso na taxa de conclusão.
Uma estimativa de custo errada. Se a conta usa preços velhos, ou ignora tokens de cache, o limite de dinheiro não protege.
Um encerramento que mente. Uma resposta parcial escrita como se estivesse completa engana o usuário.
Um orçamento contado só em passos. Um passo que resume um arquivo de duzentos mil tokens custa mais que dez passos curtos somados. Limite tokens ou dinheiro também.
E um orçamento novo para cada filho. Cada subagente ganha vinte passos novos, sem limite de profundidade, e o loop volta, agora como uma árvore.
Esse último se esconde bem. Olhe este loop. Ele tem limite de vinte passos. Então parece seguro.
Mas toda chamada de delegar abre um loop novo de vinte passos, sem limite de profundidade e sem orçamento compartilhado. Com três delegações por passo, o total explode. Além disso, o resultado do subagente é jogado fora. E terminar com uma exceção de timeout não deixa estado nenhum.
A correção é passar o mesmo orçamento para todo filho, e tirar a ferramenta de delegar depois de dois níveis. Depois, acrescentar o resultado de cada filho às observações do pai e terminar com um encerramento, não com uma exceção.
Mais uma armadilha. Um time escreve o encerramento como uma última chamada ao modelo, com ferramentas, pedindo para terminar a tarefa com o que tem. Com ferramentas, esse turno extra é o loop de novo, sem o limite que você acabou de bater. E o texto que sai finge ser um sucesso. Encerramento é curto, não tem ferramenta e admite o limite.
Então, a ideia para levar. Passos, tempo e dinheiro, escolhidos a partir dos seus dados, conferidos antes de cada chamada, compartilhados pela árvore inteira. E quando o orçamento acaba, o agente diz o que fez, o que falta e por que parou. É assim que uma fatura surpresa vira um caso de eval.
Na próxima aula, vamos olhar o padrão completo para onde essa refatoração aponta: stop conditions, inclusive quando um agente deve desistir, ou pedir ajuda. Até lá.
Add Loop Budget
Adicionar Orçamento ao Loop (Add Loop Budget) é uma refatoração de IA para sistemas com LLM, do grupo Movendo controle. Limitar passos, tempo e dinheiro de cada execução e definir o que acontece no limite.
O agente roda até o modelo decidir parar, sem limite de passos, tempo ou dinheiro. É o smell Loop Sem Fim, e as variações Subagentes em Cascata e Custo Sem Teto.
O agente de boletos abre o portal do fornecedor, clica em “Próxima página” e lê a lista. Numa noite o botão continua visível e não carrega nada. Sem teto, o loop faz milhares de cliques. O único alarme é o da fatura. O smell conta essa história; esta refatoração põe o freio. O padrão de destino é Condições de Parada.
Dê a cada execução um orçamento explícito de passos, tempo e custo, checado antes de cada volta, e defina o que o agente entrega quando o orçamento acaba.
def run_agent(task):
messages = [task]
- while True:
+ budget = Budget(max_steps=25, max_seconds=300, max_usd=0.80)
+ while budget.allows():
reply = call_model(messages, tools=TOOLS)
+ budget.charge(reply.usage)
if reply.stop_reason != "tool_use":
return reply.text
messages += run_tools(reply)
+ return wrap_up(messages, reason=budget.exhausted_reason())
Antes: a única saída é o modelo parar.
flowchart TD
T(["1. Tarefa"]):::io --> M(["2. Modelo"]):::llm
M --> D{"3. Terminou?"}
D -->|não| F["4. Ferramenta"]:::tool
F --> M
D -->|sim| R(["5. Resposta"]):::io
Depois: o código tem uma segunda saída, com comportamento definido.
flowchart TD
T(["1. Tarefa"]):::io --> B{"2. Cabe no orçamento?"}
B -->|sim| M(["3. Modelo"]):::llm
M --> D{"4. Terminou?"}
D -->|não| F["5. Ferramenta"]:::tool
F --> B
D -->|sim| R(["6. Resposta"]):::io
B -->|não| W(["7. Fechamento: parcial ou pedido de ajuda"]):::io
Os números abaixo são ilustrativos. System prompt e ferramentas: 3.000 tokens. Cada volta acrescenta uns 400 tokens de chamada e resultado.
| Execução | Voltas | Tokens enviados no total (aprox.) |
|---|---|---|
| Normal | 10 | 52 mil |
| Presa, sem teto | 200 | 8,6 milhões |
| Presa, teto 25 | 25 | cerca de 200 mil |
Vinte vezes mais voltas custam muito mais que vinte vezes o preço, porque cada volta reenvia o histórico. O teto de 25 não deixa a curva chegar na casa dos milhões.
O fechamento, no portal quebrado, não é uma exceção vazia. É: “Li a primeira página (faturas 1 a 20 de 340). O botão Próxima página respondeu ok e a lista não mudou, três vezes. Parei por repetição. Faltam as páginas 2 a 17.” Ops termina o trabalho; o trace vira caso de eval.
O OpenAI Agents SDK oferece max_turns. O LangGraph oferece recursion_limit. O texto “Building effective agents” da Anthropic (dezembro de 2024) recomenda um número máximo de iterações. Essas peças são o teto de passos. Tempo, dinheiro, repetição e fechamento honesto você escreve.
Um loop de agente tem duas fontes de término: a decisão do modelo e a decisão do código. Sem orçamento, só a primeira existe, e ela falha exatamente nos casos ruins: ferramenta que não progride, tarefa impossível, conteúdo que confunde. O orçamento põe uma decisão determinística ao lado da probabilística.
O fechamento (passo 7) é a metade que costuma faltar. Um teto que só lança exceção troca um custo alto por uma tarefa perdida. Um teto com fechamento entrega algo útil: “li 14 dos 20 arquivos, a causa provável é X, faltou confirmar Y”.
Por fim, o orçamento transforma comportamento ruim em dado. Toda execução que bate no teto é um caso para entender e, muitas vezes, um caso novo para o eval. O teto revela o problema; não existe para escondê-lo subindo o número.
usage que a API devolve, não uma tabela de preços desatualizada.stop.reason = steps | time | cost | repeat | done.stop.reason = steps.usage que a API devolve em cada resposta.Este loop tem um teto, mas ainda é um Loop Sem Fim na prática. Encontre o motivo antes de abrir a solução.
def run(task, depth=0):
for _ in range(20):
reply = call_model(task, tools=[search, delegate])
if reply.done:
return reply.text
for call in reply.tool_calls:
if call.name == "delegate":
run(call.args["subtask"], depth + 1)
else:
execute(call)
raise TimeoutError()
Cada chamada a delegate abre um novo loop de 20 passos, sem limite de profundidade e sem orçamento compartilhado. Com três delegações por passo, o total explode. Além disso, o resultado do subagente é descartado e o fim por TimeoutError não deixa estado.
def run(task, budget, depth=0):
while budget.allows():
reply = call_model(task, tools=[search, delegate] if depth < 2 else [search])
budget.charge(reply.usage)
if reply.done:
return reply.text
for call in reply.tool_calls:
if call.name == "delegate":
result = run(call.args["subtask"], budget, depth + 1) # mesmo orçamento
task.add_observation(call, result)
else:
task.add_observation(call, execute(call))
return wrap_up(task, reason=budget.exhausted_reason())Responda as 6 perguntas para concluir a aula. Só assistir não conclui: a checagem é o que conta para a trilha e para o certificado.
Adicionar Orçamento ao Loop (Add Loop Budget) é uma refatoração de IA para sistemas com LLM, do grupo Movendo controle. Limitar passos, tempo e dinheiro de cada execução e definir o que acontece no limite.
Trata Loop Sem Fim, Subagentes em Cascata e Custo Sem Teto.
Ao padrão de projeto Condições de Parada e Orçamento de Custo.