Se trabalhas com agentes de codificação em ferramentas como o Open Code, usando modelos como o Qwen ou parecidos, já deves ter reparado na facilidade com que a janela de contexto desaparece.

Basta pedires uma alteração simples de duas linhas numa função para o sistema:

  • Ler o ficheiro de 1.000 linhas na íntegra.

  • Processar o histórico todo de novo.

  • Reescrever o ficheiro inteiro do início ao fim só para mudar um if.

Resultado? Milhares de tokens gastos em poucos minutos, latência desnecessária e, pior, o modelo começa a perder o fio à meada (lost in the middle) devido ao tamanho do histórico.

Para resolver isto, tive de mudar a forma como a arquitetura lida com o código. Em vez de tratar o LLM como um programador que precisa de reler o livro todo para mudar uma página, passei a usar uma abordagem modular baseada em referências e edições cirúrgicas.

O Problema: A Leitura e Reescrita Integral

O comportamento padrão da maior parte dos agentes é ingénuo. Pedes uma correção e o fluxo é este:

[Ficheiro Completo (2000 linhas)] ──> [LLM processa tudo] ──>
[LLM reescreve 2000 linhas]

Isto era o meu inicio e acontecia porque a LLM dava-me o bloco de código a corrigir, mas eu não sabia onde o aplicar, então pedia para me dar o ficheiro na integra.

Isto consome tokens em duas frentes: input (leitura do ficheiro gigante) e output (reescrita desnecessária de código que não mudou).

A Solução: Agente de Memória e Edição por Blocos

A lógica para poupar 80% dos tokens assenta em não deixar o agente executor tocar no ficheiro completo. Em vez disso, introduz-se uma camada intermédia (um agente de contexto ou uma estrutura de indexação).

1. O Agente Guardião de Referências

Em vez de passar o código bruto para a IA, mantém-se um registo (uma espécie de mapa de inventário) do projeto. Este agente sabe exatamente em que linhas ou blocos residem as funções, as interfaces e os contratos do código.

2. Edições Cirúrgicas (Patching em vez de Overwrite)

Quando é necessária uma alteração:

  • O utilizador pede a modificação.

  • O agente de consulta vai ao mapa de referências e extrai apenas o bloco relevante (100 a 200 linhas).

  • O executor recebe esse bloco isolado, sabe onde mexer no meio do ficheiro, substitui o bloco e não necessita de ler ou reescrever o resto.

  • O output do modelo é apenas o diff/patch (as linhas a alterar), e não o ficheiro todo.

[Pedido] ──> [Agente de Referências extrai Bloco X (150 linhas)]
──> [LLM gera Diff de 10 linhas] ──> [Aplicação local do Patch]

Na Prática: Como Estruturar Isto no Workflow

A. Trocar Ficheiros por "Esqueletos" (AST- arvore sintática )

Para o agente perceber o contexto global do projeto, não precisa de ler a implementação das funções. Basta-lhe a assinatura. Extrair a árvore sintática (AST) do ficheiro e passar apenas o "esqueleto" (nomes de funções, parâmetros e tipos) reduz o input em cerca de 90%.

{

  "target_file": "src/services/auth.py",

  "block_id": "validate_token",

  "action": "replace_lines",

  "lines": [45, 52],

  "code": "new_implementation_here"

}

O Resultado

Ao deixar de tratar o código como um texto contínuo e passar a tratá-lo como blocos endereçáveis:

  • Consumo de Input: Cai drasticamente porque o modelo só lê o contexto estritamente necessário (o "esqueleto" + o bloco a alterar).

  • Consumo de Output: Cai para uma fração, já que o modelo responde apenas com as linhas alteradas e não com a reescrita total do ficheiro.

  • Velocidade: A resposta é quase instantânea, pois gerar 15 linhas de diff demora uma fração do tempo de gerar 1.000 linhas de código.

No fim do dia, o ideal não é ter uma janela de contexto maior, mas sim ter a inteligência de não a encher com lixo ou ruido desnecessários.

Continue lendo