Pular para o conteúdo

Conclusão da Unidade 2

Na Unidade 1 o Alfred consultava uma base que nós mesmos inventamos. Agora ele consulta 23.152.022 processos do TJRJ, e os números que ele devolve abrem no sistema do Tribunal.

Entre uma coisa e outra, o agente não mudou.

O que mudou, exatamente

Vale reler a tabela da introdução agora que a unidade acabou, porque ela é o argumento inteiro do curso:

Unidade 1 Unidade 2
Modelo qwen2:7b no Ollama local igual
Framework smolagents, CodeAgent igual
Ciclo Thought → Action → Observation igual
Estrutura das Tools Duas: listar assunto, buscar processo igual
Controle de sigilo Constante no código, nunca argumento igual
Origem do dado SQLite sintético API Pública do DataJud
Linguagem de consulta SQL parametrizado Elasticsearch Query DSL
Dependências novas nenhuma (urllib da biblioteca padrão)

Três linhas de oito. Foi isso que separou um exercício de um agente que consulta o acervo nacional.

Esse é o ponto a levar para fora do curso: agente não é o dado. Quem entendeu o ciclo, entendeu-o para qualquer origem — e trocar a origem é trabalho de Tool, não de agente.

O que você tem agora

Um cliente de 30 linhas (cnj.py) que fala com o CNJ sem instalar nada, e que preserva o corpo do erro em vez de reduzi-lo a "HTTP 400". Foi essa decisão que transformou uma agregação quebrada numa aula sobre .keyword.

Duas Tools contra dado real (tools_cnj.py), com quatro cuidados que nenhuma delas precisa hoje e todas vão precisar amanhã: teto de sigilo, guarda antes da rede, limite de resultados e máscara aplicada no código.

Query DSL suficiente para o trabalho real: term contra match, bool/filter, range, sort, aggs, track_total_hits. E a noção de por que assuntos.nome e assuntos.nome.keyword são dois campos diferentes com o mesmo conteúdo.

Uma medição que vale como argumento em qualquer conversa sobre o tema: 100% do índice público do TJRJ é nivelSigilo 0, provado por dois caminhos independentes. Quem perguntar "esse agente aí vai ler processo sigiloso?" recebe um número, não uma opinião.

A lição desta unidade

A Unidade 1 terminou com duas frases sobre modelos. Esta termina com uma sobre Tools:

Num Code Agent, a Tool devolve objeto Python — e o erro de tipo não avisa.

Vale desdobrar, porque foi caro. Nas quatro execuções que este curso guardou, três deram errado:

  1. A Tool devolvia json.dumps([...]). O modelo escreveu for assunto in listar_assuntos(...), o laço percorreu caracteres, e cerca de 78 requisições foram ao CNJ perguntar por assuntos chamados '{', '"', 'a'. Nenhuma exceção. Tempo de execução normal. Resultado vazio com aparência de resultado.

  2. Corrigido o tipo, a Tool passou a devolver dict. O modelo escreveu processos.extend(processos_assunto), e extend sobre um dicionário percorre as chaves. A lista final ficou ['assunto', 'quantidade_pedida', 'encontrados', ...]. De novo: nenhuma exceção.

  3. Corrigidos os tipos, as Tools passaram a funcionar — e o agente não parou. Obteve os seis processos no Step 3 e continuou andando até o max_steps, gastando 175 segundos e 20 mil tokens no último passo para responder, em inglês, o que já tinha em mãos há três passos.

O padrão dos dois primeiros é o mesmo, e é ele que interessa: em Python quase tudo é iterável, e iterar a coisa errada raramente dá erro — dá um resultado. Num script comum você percebe na hora. Num agente, esse resultado vira Observation, entra no contexto e o modelo escreve o passo seguinte em cima dele.

Daí a regra prática que fecha a unidade: antes de acusar o modelo, confira o tipo que a sua Tool devolve. Nos dois episódios o raciocínio do qwen2:7b estava correto; o contrato da Tool é que estava mal escrito.

E o terceiro episódio acrescenta a outra metade: o CodeAgent só termina quando o código gerado chama final_answer. Modelos pequenos não chamam sozinhos com confiabilidade. Duas frases no pedido — chame final_answer, responda em português — levaram a mesma tarefa de 6 passos para 4, e do inglês para os dados estruturados que se pediu. Prompt orienta; max_steps garante.

O que ficou de fora, de propósito

O DataJud tem um campo que esta unidade nem tocou: movimentos[] — a lista completa de andamentos de cada processo, com código da TPU, nome e data e hora.

É o campo mais rico da API e o mais pesado. Um processo movimentado traz centenas de andamentos — o mais pesado que encontramos tem 613 —, e jogar isso inteiro numa Observation estoura o num_ctx do modelo em um único passo.

Fica como o primeiro exercício de quem quiser ir além agora:

Escreva uma terceira Tool, ultimos_movimentos(numero_processo, quantidade=5), que busque um processo pelo número, ordene movimentos por dataHora e devolva só os últimos, cada um com nome e data já formatada.

Repare que o enunciado inteiro é sobre reduzir. É esse o ofício de quem escreve Tools para agente — e é o assunto da unidade seguinte.

O que vem pela frente

Unidade 3 — a Tool sai do script. Duas metades ligadas. Primeiro movimentos[] a sério: o problema geral de que ele é um exemplo é como fazer um agente trabalhar com mais texto do que cabe na janela. Depois, essas Tools deixam de morar dentro do seu programa e passam a ser um servidor MCP — o mesmo protocolo que o Claude e outros clientes falam, rodando na sua máquina, servindo o seu agente local.

Unidade 4 — o seu Agent. Você escolhe um tema da sua competência, adapta as Tools e testa localmente. É o projeto final, e é a razão de tudo até aqui.

Nota

E há um caminho que este curso não percorre, mas para o qual ele preparou você por inteiro.

A API do CNJ tem metadado público. O sistema do Tribunal tem tudo — nome das partes, peças, sentença — e tem os três níveis de sigilo, sem ninguém tendo filtrado antes.

Todo o código desta unidade vai para lá quase sem mudança: as duas Tools continuam duas, o teto de sigilo continua constante, a máscara continua no código. Muda a função consultar — de POST para SELECT — e muda o fato de que, do outro lado, a sua credencial é nominal e deixa rastro.

O capítulo Sigilo na origem foi escrito pensando nesse dia. Vale relê-lo antes de escrever a primeira consulta contra o banco do Tribunal.


Uma última observação sobre o que foi feito aqui.

Nenhum dado saiu da sua máquina além da consulta — um nome de assunto e um pedido de ordenação. O modelo é local, a chave é pública, a resposta é metadado público, e o conteúdo dos autos continua onde sempre esteve: no sistema do Tribunal, atrás da sua credencial.

Um agente que devolve ponteiros e deixa o acesso acontecer onde há trilha de auditoria não é uma limitação que aceitamos. É o desenho certo — e é o que torna possível mostrar isso a um colega sem precisar pedir desculpa por nada.

Até a Unidade 3.