Lição 5 de 6 · 15 min · Verificado em 10 de Outubro de 2026
Projecto final: um sistema que trabalha sozinho, com travões
No fim desta lição vais conseguir:
- Construir um agente que todas as manhãs compara uma página com a da véspera e escreve um resumo
- Pôr quatro travões: caixa própria, tecto de gasto, registo e botão de paragem
- Agendar e desagendar o agente com o cron ou com o schtasks
- Testar cada travão antes de deixar o sistema a correr sozinho
A junta de freguesia publica avisos numa página: cortes de água, horário do barco, obras na estrada. O Sr. Manuel quer saber todas as manhãs se há novidades, sem abrir a página e comparar de cabeça com a de ontem.
Hoje constróis esse vigia, com uma página de teste tua, que mudas à mão para simular os avisos.
Antes de começar: o que é «pronto»
O projecto está pronto quando:
- existe a pasta
experiencias/vigiacom Git e uma página de teste; - o vigia guarda uma cópia por dia e compara-a com a anterior;
- quando há mudanças, um agente escreve um resumo em
resumos/; - cada execução deixa uma linha no registo, com o que fez e o custo estimado;
- os quatro travões foram testados um a um;
- o vigia correu agendado e depois tiraste o agendamento.
Os quatro travões:
- Caixa própria: só trabalha na sua pasta, com o agente sem ferramentas e sem rede além da chamada ao modelo.
- Tecto de gasto: um por execução e outro por mês; cada execução só pode gastar o que sobra do mês, e duas execuções não correm ao mesmo tempo.
- Registo: uma linha por dia com o que fez e quanto custou.
- Botão de paragem: se existir um ficheiro
PARAR, a próxima execução não arranca. Uma execução já a meio pára-se pelo processo.
Cuidado
O vigia não envia emails nem mensagens. Se um dia quiseres um aviso no telemóvel, o agente escreve o rascunho e uma pessoa decide se sai.
Isto é como está a 6 de Outubro de 2026; se o ecrã for diferente, procura o botão com o mesmo nome. Guias: Agent SDK, crontab, schtasks.
Passo 1: a pasta e a página de teste
Cria experiencias/vigia, corre git init e abre o agente lá dentro:
Cria pagina/index.html: uma página simples de «Avisos da Junta» com três avisos inventados,
cada um com data e uma frase. Cria também um .gitignore com .env, .venv/ e historico/.
Não instales nada.
Confirma: a página abre no browser e o .gitignore tem as três linhas.
Se não deu: se a página não abre, confirma que se chama index.html e está dentro de pagina/.
Passo 2: o vigia sem modelo
Primeiro, a parte previsível, só com código:
Cria vigia.py, em Python, sem pacotes extra. Por esta ordem:
1. Se existir o ficheiro PARAR, escreve no registo «parado» e sai.
2. Se existir o ficheiro A_CORRER, escreve «já a correr» e sai; senão cria-o e apaga-o no fim, aconteça o que acontecer.
3. Lê config.json (tecto_execucao_usd, tecto_mes_usd, max_voltas). Soma os custos do mês em registo.csv,
incluindo as linhas de erro. O que sobra é tecto_mes_usd menos essa soma; se for zero ou menos,
escreve «tecto do mês» e sai. O tecto desta execução é o menor entre tecto_execucao_usd e o que sobra;
escreve-o no registo.
4. Copia pagina/index.html para historico/AAAA-MM-DD.html.
5. Compara com a cópia anterior. Sem cópia anterior ou sem diferenças: escreve isso no registo e sai.
6. Com diferenças, por agora, só imprime o diff.
Cada linha de registo.csv tem: data, hora, o que fez, custo estimado.
Aceita --data AAAA-MM-DD para eu testar dias diferentes. Cria config.json com valores baixos que eu ajusto.
Mostra-me o plano antes de escrever.
Confirma: corre python vigia.py --data 2026-10-01, muda um aviso na página, corre com --data 2026-10-02. A segunda vez imprime o diff.
Se não deu: se a segunda corrida diz «sem diferenças», confirma que gravaste a página antes de correr.
Passo 3: o agente que resume
Agora ligas o modelo, só para o que o código não sabe fazer: explicar as mudanças em português.
Instala claude-agent-sdk num ambiente virtual .venv. No passo 6 do vigia.py, chama o Agent SDK
com o diff no pedido e estas opções: cwd igual à pasta do vigia, permission_mode="dontAsk",
disallowed_tools=["*"], max_turns=max_voltas e max_budget_usd igual ao tecto desta execução (o menor entre
tecto_execucao_usd e o que sobra do mês). Pede um resumo curto em português europeu, sem inventar nada.
O vigia.py grava o resumo em resumos/AAAA-MM-DD.md e o total_cost_usd no registo.
O próprio script lê a chave do .env e nunca a mostra.
Se o SDK parar com erro, regista o motivo e o custo que vier na resposta e sai. Se não vier custo nenhum,
regista «custo desconhecido» e cria o ficheiro PARAR, para eu rever antes da próxima execução.
Acrescenta --simular ok|tecto|indisponivel, que não chama o modelo: devolve um resumo fixo com custo 0,01,
um fim por error_max_budget_usd com custo, ou um erro de ligação sem custo.
A chave fica no .env, como na lição 1/06. O "*" tira ao agente todas as ferramentas: recebe o diff, devolve texto, e quem grava é o teu código. Sem isto, no modo dontAsk ainda podia ler ficheiros da pasta, incluindo o .env.
Se não deu: «Invalid API key» quer dizer que o script não está a ler o .env; confirma o nome ANTHROPIC_API_KEY.
Dica
O custo no registo é uma estimativa, e os tectos do SDK também são aproximados: contam custos estimados e são verificados entre voltas. O travão de verdade é o limite de gasto na consola do fornecedor (lição 1/06). Corre uma vez, vê o custo no registo e ajusta os tectos do config.json.
Passo 4: testar os travões
Primeiro pede a previsão:
Sem mudar código, diz-me o que o vigia.py faz e que linha escreve no registo em cada caso:
existe PARAR; o tecto do mês foi atingido; a página não mudou.
Depois prova:
- Cria o ficheiro
PARARe corre. O registo diz «parado», sem custo. - Apaga o
PARAR, põe otecto_mes_usdabaixo do que já gastaste e corre. O registo diz «tecto do mês». - Repõe o valor e corre num dia sem mudanças. Não há chamada ao modelo nem custo.
- Num dia com mudanças, corre com
--simular tecto. O registo mostra o fim porerror_max_budget_usde o custo. - Põe o
tecto_execucao_usdacima do que sobra do mês e corre com--simular ok. O registo mostra o tecto desta execução igual ao que sobra. - Corre com
--simular indisponivel. O registo diz «custo desconhecido» e oPARARaparece; apaga-o. - Lança duas execuções ao mesmo tempo com
--simular ok. Uma corre; a outra escreve «já a correr».
Se não deu: se o resultado não bate com a previsão, mostra ao agente a linha do registo e pede que corrija só esse ponto.
Passo 5: agendar
Mostra-me como correr o vigia todos os dias às 7h00 com o .venv desta pasta: no Linux ou no macOS,
uma linha de crontab; no Windows, um correr.bat e o comando schtasks. Não agendes nada: faço eu.
No Linux ou no macOS, corre crontab -e e junta a linha, com o teu caminho:
0 7 * * * cd /caminho/para/experiencias/vigia && .venv/bin/python vigia.py >> cron.log 2>&1
Os cinco campos são minuto, hora, dia, mês e dia da semana. O crontab -l mostra o que está agendado. O cron arranca com um ambiente mínimo, por isso o script tem de ler o .env sozinho.
No Windows, com o correr.bat que o agente escreveu:
schtasks /create /tn vigia /tr "C:\caminho\experiencias\vigia\correr.bat" /sc daily /st 07:00
schtasks /query /tn vigia
Dica
Para desagendar: no cron, crontab -e e apaga só essa linha; no Windows, schtasks /delete /tn vigia /f. Não uses crontab -r para isto: apaga todas as linhas, não só a do vigia.
Se não deu: se nada acontece às 7h00, vê o cron.log; o erro mais comum é um caminho errado.
Exercício
Como sei que ficou bem há uma cópia por dia em historico/, um resumo só nos dias com mudanças, uma linha por dia no registo com o custo, e o crontab -l (ou o schtasks /query) já não mostra o vigia.
Se não deu
- Resumos com coisas que não estão na página: reforça no pedido «resume só o que está no diff» e confirma que o diff vai no pedido.
- O registo tem duas linhas no mesmo dia: o vigia correu duas vezes; vê o
crontab -l. - O custo do mês não bate com a consola: o do registo é uma estimativa; manda a consola.
O que levas deste projecto
Um sistema que trabalha sozinho e que sabes travar: o código faz o previsível, o agente só o que precisa de linguagem, tudo fica registado e nada sai sem uma pessoa.
Vídeos
Ciclos de agentes na prática com Claude Code e Codex: um ciclo gestor que lê o backlog e um ciclo trabalhador, com skills, verificação e limites (guardrails) no fim.
Testa o que aprendeste
Correcções a esta lição (1)
- : Depois de uma segunda revisão externa: cada execução só pode gastar o que sobra do mês, as linhas de erro contam para a soma, um custo desconhecido cria o `PARAR`, e duas execuções não correm ao mesmo tempo; o `PARAR` impede as próximas execuções, não interrompe uma a meio (pára-se o processo); os testes ganharam quatro casos simulados, sem chamadas pagas.