Registro imutável de ações dos agentes
Registros somente para acréscimo, assinaturas criptográficas e trilhas de auditoria que evidenciam adulterações.
Registro imutável de ações dos agentes é uma aula grátis de AI Agents no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Agents, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Agents inclui 4 aulas no total.
Por que os agentes precisam de registros imutáveis
Os agentes executam ações de forma autônoma — muitas vezes sem que uma pessoa revise cada etapa. Quando algo dá errado, é necessário responder: o que o agente fez, quando, em nome de quem e por quê?
Um registro imutável e capaz de evidenciar adulterações torna impossível alterar retroativamente a trilha de auditoria.
Esquema de uma entrada de registro
Cada entrada de registro captura: marca temporal, identidade do agente, identidade do usuário, tipo de ação, parâmetros, resultado e um resumo criptográfico que a vincula à entrada anterior. Essa estrutura permite tanto a pesquisa quanto a detecção de adulterações.
from dataclasses import dataclass
from typing import Any
@dataclass
class AuditEntry:
timestamp: float # Unix time (UTC)
agent_id: str
user_id: str
action_type: str
parameters: dict
result: dict
session_id: str
prev_hash: str # hash of previous entry
entry_hash: str = '' # computed after construction
if __name__ == '__main__':
entry = AuditEntry(
timestamp=1717000000.0, agent_id='agent-1', user_id='user-42',
action_type='send_email', parameters={'to': 'a@b.com'},
result={'status': 'sent'}, session_id='sess-1', prev_hash='0' * 64
)
print('Audit entry created:')
print(' agent_id:', entry.agent_id)
print(' action_type:', entry.action_type)
print(' prev_hash:', entry.prev_hash)
Encadeamento de resumos criptográficos para detectar adulterações
O resumo criptográfico de cada entrada é calculado a partir do conteúdo dela mais o resumo criptográfico da entrada anterior. Se alguma entrada for modificada posteriormente, seu resumo criptográfico mudará, invalidando todos os resumos criptográficos seguintes. Assim, a adulteração pode ser detectada.
import hashlib, json, time
def compute_entry_hash(entry: dict, prev_hash: str) -> str:
content = json.dumps(entry, sort_keys=True, default=str)
payload = f'{prev_hash}:{content}'
return hashlib.sha256(payload.encode()).hexdigest()
def create_log_entry(agent_id: str, user_id: str, action_type: str,
parameters: dict, result: dict,
session_id: str, prev_hash: str) -> dict:
entry = {
'timestamp': time.time(),
'agent_id': agent_id,
'user_id': user_id,
'action_type': action_type,
'parameters': parameters,
'result': result,
'session_id': session_id,
'prev_hash': prev_hash
}
entry['entry_hash'] = compute_entry_hash(
{k: v for k, v in entry.items() if k != 'entry_hash'},
prev_hash
)
return entry
if __name__ == '__main__':
entry = create_log_entry('agent-1', 'user-42', 'send_email',
{'to': 'a@b.com'}, {'status': 'sent'},
'sess-1', prev_hash='0' * 64)
print('New log entry hash:', entry['entry_hash'])
print('Chained from prev_hash:', entry['prev_hash'])
Registro em processo somente para acréscimo
A implementação mais simples é uma lista na memória com um método que permite somente acrescentar itens. Nenhum método de exclusão ou atualização é exposto. Em produção, isso é apoiado por um banco de dados ou armazenamento de objetos.
class AppendOnlyLog:
def __init__(self):
self._entries: list[dict] = []
self._last_hash = 'GENESIS'
def append(self, agent_id: str, user_id: str, action_type: str,
parameters: dict, result: dict, session_id: str) -> dict:
entry = create_log_entry(
agent_id, user_id, action_type,
parameters, result, session_id,
self._last_hash
)
self._entries.append(entry)
self._last_hash = entry['entry_hash']
return entry
def verify_integrity(self) -> bool:
running_hash = 'GENESIS'
for e in self._entries:
expected = compute_entry_hash(
{k: v for k, v in e.items() if k != 'entry_hash'},
running_hash
)
if expected != e['entry_hash']:
return False
running_hash = e['entry_hash']
return True
@property
def entries(self):
return list(self._entries) # return copy, not referenceGravando no PostgreSQL com semântica de acréscimo
Em produção, grave os registros em uma tabela de banco de dados que não conceda permissões UPDATE ou DELETE ao usuário da aplicação. Revogue esses privilégios no nível do banco de dados para obter um comportamento realmente somente para acréscimo.
import psycopg2, json
# Table DDL (run once):
# CREATE TABLE agent_audit_log (
# id BIGSERIAL PRIMARY KEY,
# timestamp DOUBLE PRECISION NOT NULL,
# agent_id TEXT NOT NULL,
# user_id TEXT NOT NULL,
# action_type TEXT NOT NULL,
# parameters JSONB NOT NULL,
# result JSONB NOT NULL,
# session_id TEXT NOT NULL,
# prev_hash TEXT NOT NULL,
# entry_hash TEXT NOT NULL UNIQUE
# );
# REVOKE UPDATE, DELETE ON agent_audit_log FROM app_user;
def write_to_db(conn, entry: dict):
with conn.cursor() as cur:
cur.execute(
'INSERT INTO agent_audit_log '
'(timestamp,agent_id,user_id,action_type,parameters,result,session_id,prev_hash,entry_hash) '
'VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)',
(entry['timestamp'], entry['agent_id'], entry['user_id'],
entry['action_type'], json.dumps(entry['parameters']),
json.dumps(entry['result']), entry['session_id'],
entry['prev_hash'], entry['entry_hash'])
)
conn.commit()Gravando no S3 com bloqueio de objetos (WORM)
O bloqueio de objetos do AWS S3 no modo COMPLIANCE impede que qualquer usuário — inclusive o usuário raiz da conta — exclua ou substitua objetos durante o período de retenção. Esse é um armazenamento de gravação única verdadeiro para registros de auditoria.
import boto3, json, time
s3 = boto3.client('s3', region_name='us-east-1')
BUCKET = 'your-audit-log-bucket-worm'
def write_to_s3_worm(entry: dict):
key = f'audit/{entry["agent_id"]}/{int(entry["timestamp"])}/{entry["entry_hash"][:16]}.json'
s3.put_object(
Bucket=BUCKET,
Key=key,
Body=json.dumps(entry).encode(),
ContentType='application/json',
ObjectLockMode='COMPLIANCE',
ObjectLockRetainUntilDate='2030-01-01T00:00:00Z' # 4+ year retention
)
return keyConsultando o registro de auditoria
O registro de auditoria não serve apenas para conformidade — ele também é útil operacionalmente. Consulte-o para depurar o comportamento do agente, reconstruir uma sessão ou responder à pergunta “por que o agente fez X?”.
def query_session(log: AppendOnlyLog, session_id: str) -> list[dict]:
return [
e for e in log.entries
if e['session_id'] == session_id
]
def query_user_actions(log: AppendOnlyLog, user_id: str,
action_type: str = None) -> list[dict]:
entries = [e for e in log.entries if e['user_id'] == user_id]
if action_type:
entries = [e for e in entries if e['action_type'] == action_type]
return sorted(entries, key=lambda e: e['timestamp'])
def count_actions_by_type(log: AppendOnlyLog) -> dict:
from collections import Counter
return dict(Counter(e['action_type'] for e in log.entries))Limpando dados confidenciais antes do registro
Os registros de auditoria devem capturar o que o agente fez, sem expor dados confidenciais. Remova PII (senhas, chaves de API e números de cartão de crédito) dos parâmetros e resultados antes de gravá-los.
import re
SENSITIVE_KEYS = {'password', 'api_key', 'secret', 'token', 'credit_card', 'ssn'}
def sanitize(obj, depth: int = 0) -> dict | list | str:
if depth > 5:
return '[MAX_DEPTH]'
if isinstance(obj, dict):
return {
k: '[REDACTED]' if k.lower() in SENSITIVE_KEYS
else sanitize(v, depth + 1)
for k, v in obj.items()
}
elif isinstance(obj, list):
return [sanitize(i, depth + 1) for i in obj]
elif isinstance(obj, str):
# Redact anything that looks like an API key
return re.sub(r'(sk-|Bearer\s)[A-Za-z0-9_-]{16,}', '[REDACTED]', obj)
return obj
if __name__ == '__main__':
record = {'user': 'alice', 'password': 'hunter2', 'note': 'call me at sk-abcdefghijklmnopqrstuv'}
print('Sanitized record:', sanitize(record))
Rotação e arquivamento de registros
Os registros ativos crescem indefinidamente. Faça a rotação deles: mova para o armazenamento frio as entradas com mais de 90 dias (por exemplo, S3 Glacier) e compacte-as. Mantenha a cadeia intacta preservando o último resumo criptográfico de cada segmento rotacionado.
import time, json, gzip
def rotate_log(log: AppendOnlyLog, max_age_days: int = 90) -> dict:
cutoff = time.time() - max_age_days * 86400
archive = [e for e in log.entries if e['timestamp'] < cutoff]
remaining = [e for e in log.entries if e['timestamp'] >= cutoff]
if not archive:
return {'archived': 0, 'remaining': len(remaining)}
# Compress archive
archive_bytes = gzip.compress(json.dumps(archive).encode())
archive_file = f'/tmp/audit_archive_{int(time.time())}.json.gz'
with open(archive_file, 'wb') as f:
f.write(archive_bytes)
# Update in-memory log
log._entries = remaining
return {'archived': len(archive), 'remaining': len(remaining), 'file': archive_file}Alertas sobre padrões suspeitos
Monitore o registro de auditoria em tempo real em busca de padrões incomuns: uma explosão de ações de alto risco, ações fora do horário comercial ou a repetição da mesma ação mais de N vezes em um curto intervalo.
import time
from collections import defaultdict
HIGH_RISK_ACTIONS = {'delete_user', 'send_mass_email',
'transfer_funds', 'export_all_data'}
BURST_LIMIT = 5
BURST_WINDOW = 60 # seconds
action_timestamps: dict[str, list] = defaultdict(list)
def check_suspicious(entry: dict) -> list[str]:
alerts = []
action = entry['action_type']
if action in HIGH_RISK_ACTIONS:
alerts.append(f'HIGH_RISK_ACTION: {action} by {entry["agent_id"]}')
now = time.time()
action_timestamps[action].append(now)
recent = [t for t in action_timestamps[action] if now - t < BURST_WINDOW]
action_timestamps[action] = recent
if len(recent) > BURST_LIMIT:
alerts.append(f'ACTION_BURST: {action} called {len(recent)}x in {BURST_WINDOW}s')
return alerts
if __name__ == '__main__':
entry = {'action_type': 'delete_user', 'agent_id': 'agent-9'}
for _ in range(6):
alerts = check_suspicious(entry)
print('Alerts on 6th call:', alerts)
Verificando a integridade do registro sob demanda
Execute uma verificação de integridade como parte do seu fluxo de monitoramento. Emita um alerta imediatamente se alguma falha de verificação for detectada — isso indica um erro no código de registro ou uma tentativa ativa de adulteração.
def verify_and_alert(log: AppendOnlyLog) -> dict:
is_valid = log.verify_integrity()
total = len(log.entries)
result = {
'total_entries': total,
'integrity_ok': is_valid
}
if not is_valid:
import logging
alert_logger = logging.getLogger('agent.integrity_alert')
alert_logger.critical(
'AUDIT LOG INTEGRITY FAILURE: tampered or corrupted entries detected. '
'Total entries: %d. Initiating incident response.', total
)
result['alert_sent'] = True
return result
# Run periodically via cron or monitoring hook
# verify_and_alert(global_audit_log)O que o encadeamento de resumos criptográficos detecta em um registro de auditoria?
O encadeamento de resumos criptográficos é o mecanismo criptográfico que confere ao registro de auditoria a propriedade de permitir a detecção de adulterações. Entender o que ele detecta é fundamental para projetar registros de auditoria.
Recapitulação do registro imutável de ações
Os registros imutáveis de agentes usam: encadeamento de resumos criptográficos para detectar adulterações, armazenamento somente para acréscimo (revogue UPDATE/DELETE no nível do banco de dados), armazenamento de objetos WORM (bloqueio de objetos do S3) para retenção regulatória, limpeza de PII antes da gravação e alertas de anomalias em tempo real sobre padrões de ações suspeitos.
Perguntas Frequentes
A aula “Registro imutável de ações dos agentes” é grátis?
Sim — o texto completo de “Registro imutável de ações dos agentes” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Agents, atualize para CoddyKit PRO. O curso de AI Agents inclui 4 aulas no total.
O que vou aprender em “Registro imutável de ações dos agentes”?
Registros somente para acréscimo, assinaturas criptográficas e trilhas de auditoria que evidenciam adulterações. Você pratica AI Agents com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Agents?
Nenhuma experiência prévia é necessária. AI Agents no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Registro imutável de ações dos agentes”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Agents?
Sim. Cada aula de AI Agents inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Registro imutável de ações dos agentes
- Aplicação de políticas às ações dos agentes
- Conformidade regulatória: GDPR e SOC2
- Portões de aprovação com participação humana