⏰ Cron — gatilho de tempo
Cron é o mecanismo mais robusto de automação: executa um comando em horário predefinido, independente de qualquer evento externo. Marco recebe o brief financeiro às 6h de segunda porque o sistema lembra — não porque ele pediu.
💻 Exemplos de cron para agentes
# crontab -e
# Brief financeiro toda segunda 6h
0 6 * * 1 /usr/bin/claude --print "Gera brief financeiro semanal" \
--no-interactive >> /tmp/brief-$(date +%Y%m%d).md
# Monitoramento de concorrentes toda sexta 18h
0 18 * * 5 /home/user/.local/bin/run-agent.sh competitive-monitor
# Silver Platter update todo dia 2h
0 2 * * * python3 /workspace/scripts/update-silver-platter.py
# Relatório mensal: 1o dia do mes 7h
0 7 1 * * claude --print "Gera relatorio mensal completo" \
--context /workspace/context/ >> /workspace/reports/monthly-$(date +%Y%m).md
💡 systemd timer vs. crontab
Para 2026, prefira systemd user timers sobre crontab em Linux: logs estruturados via journalctl, retry automático em falha, melhor controle de dependências. crontab é mais simples para começar.
📡 Webhook — gatilho de evento
Quando o gatilho é externo, webhook é mais natural que polling: o sistema externo notifica o agente quando algo acontece. Stripe paga → CFO Bot atualiza o relatório. GitHub merge → Builder roda testes.
💻 Receptor de webhook simples
# webhook-receiver.py (Flask)
from flask import Flask, request
import subprocess, hmac, hashlib
app = Flask(__name__)
@app.route('/webhook/stripe', methods=['POST'])
def stripe_webhook():
# Valida assinatura
sig = request.headers.get('Stripe-Signature')
if not validate_stripe_sig(request.data, sig):
return 'Invalid', 401
event = request.json
if event['type'] == 'payment_intent.succeeded':
amount = event['data']['object']['amount']
# Dispara agente assincronamente
subprocess.Popen([
'claude', '--print',
f'Pagamento de R${amount/100:.2f} recebido. Atualiza relatorio.',
'--no-interactive'
])
return 'OK', 200
Boas práticas de webhook
- Validar assinatura — HMAC-SHA256. Sem isso, qualquer um dispara seu agente.
- Responder 200 rápido — processar em background. Stripe timeout em 30s.
- Idempotência — webhook pode chegar duplicado. Deduplique por event_id.
- Fila — em produção, use fila (Redis, SQS) entre webhook e agente.
📁 File watcher — filesystem como evento
Drop folders são a interface mais natural para processar documentos: usuário solta arquivo em /intake/ e agente processa automaticamente. Sem UI, sem upload manual, sem lembrar de "enviar para o bot".
💻 File watcher com fswatch
#!/bin/bash
# watch-intake.sh — monitora /intake/ e processa novos PDFs
INTAKE_DIR="/workspace/intake"
PROCESSED_DIR="/workspace/processed"
# fswatch dispara script para cada novo arquivo
fswatch -0 --event Created "$INTAKE_DIR" | while IFS= read -r -d "" file; do
# So processa PDFs
if [[ "$file" == *.pdf ]]; then
echo "Processando: $file"
# Chama agente com o arquivo
claude --print "Analisa este PDF e extrai dados chave: $(cat "$file")" \
--no-interactive > "${PROCESSED_DIR}/$(basename "$file" .pdf).md"
# Move para processed
mv "$file" "$PROCESSED_DIR/"
echo "Concluido: $file"
fi
done
💡 Debounce — problema do grande arquivo
Sem debounce, watcher dispara durante a escrita do arquivo — processando arquivo incompleto. Adicione: sleep 2 após detectar criação, ou use inotifywait --event close_write que espera o arquivo ser fechado.
⚙️ systemd user services — daemon agêntico
Para agentes always-on, systemd user service é superior a script em background: reinicia em falha, logs estruturados no journalctl, controle fino de recursos, integração com o sistema.
💻 Unit file para agente watcher
# ~/.config/systemd/user/intake-watcher.service
[Unit]
Description=Agente de processamento de intake
After=network.target
[Service]
Type=simple
ExecStart=/home/user/workspace/scripts/watch-intake.sh
Restart=on-failure
RestartSec=10s
StandardOutput=journal
StandardError=journal
# Limites de recursos
MemoryMax=512M
CPUQuota=50%
[Install]
WantedBy=default.target
# Ativar:
# systemctl --user enable intake-watcher
# systemctl --user start intake-watcher
# journalctl --user -u intake-watcher -f
Vantagens do systemd sobre nohup/screen
- Restart automático — sem monitoramento manual de processo morto.
- Logs persistentes — journalctl com filtros, timestamps, níveis.
- Controle de recursos — MemoryMax evita OOM killer.
- Dependências — After=network.target garante ordem.
🧊 Idempotência — não duplicar trabalho
Cron pode disparar duas vezes (clock drift, restart). Webhook pode chegar duplicado (retry do cliente). Idempotência garante que rodar N vezes produz o mesmo resultado de 1 vez — sem duplicação de trabalho, sem efeitos colaterais extras.
💻 Padrões de idempotência
#!/bin/bash
# Padrao 1: marker file (cron diario)
MARKER="/tmp/brief-$(date +%Y%m%d).done"
if [ -f "$MARKER" ]; then
echo "Brief ja gerado hoje, pulando."
exit 0
fi
# ... gera brief ...
touch "$MARKER"
# Padrao 2: lock file (previne execucao paralela)
LOCKFILE="/tmp/intake-processor.lock"
exec 9>"$LOCKFILE"
if ! flock -n 9; then
echo "Outra instancia rodando, saindo."
exit 1
fi
# ... processa ...
# lock liberado automaticamente ao sair
# Padrao 3: deduplica por ID (webhook)
PROCESSED_IDS_FILE="/var/lib/agent/processed-ids"
EVENT_ID=$(echo "$PAYLOAD" | jq -r '.id')
if grep -q "^$EVENT_ID$" "$PROCESSED_IDS_FILE" 2>/dev/null; then
exit 0 # Ja processado
fi
echo "$EVENT_ID" >> "$PROCESSED_IDS_FILE"
⚠️ Consequências de não implementar
Marco recebe o brief financeiro duplicado às 6h de segunda. Dois relatórios diferentes, com dados ligeiramente distintos (coletados em timestamps diferentes), causam confusão nas reuniões. Parece trivial até acontecer com dados críticos.
📲 Notificações — Telegram, Slack, e-mail
Sistema sem notificação é sistema invisível. O agente precisa de um canal para avisar o humano: quando terminou, quando falhou, quando encontrou algo que exige decisão. A escolha do canal define a urgência.
💻 Notificador multi-canal
#!/bin/bash
# notify.sh - envia para canal correto por urgencia
# Uso: notify.sh "mensagem" [urgencia: low|medium|high]
MESSAGE="$1"
URGENCY="${2:-low}"
case "$URGENCY" in
high)
# Telegram para urgente (chega no celular)
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" \
-d "chat_id=$TELEGRAM_CHAT_ID&text=URGENTE: $MESSAGE"
;;
medium)
# Slack para medium
curl -s -X POST "$SLACK_WEBHOOK" \
-d "{\"text\": \"$MESSAGE\"}"
;;
low)
# E-mail para baixa urgencia
echo "$MESSAGE" | mail -s "Agentic OS Update" "$NOTIFY_EMAIL"
;;
esac
💡 Rate limiting de notificações
Sistema que notifica demais treina o humano a ignorar. Defina: máximo N notificações por hora por canal. Use digest para agregar mensagens de baixa urgência. Reserve alta urgência para situações que realmente precisam de resposta imediata.
📋 Resumo do Módulo
Próximo Módulo:
5.6 — Segurança aplicada pela arquitetura