Agentes de IA em Produção: Como Montar um Sistema de Identidade e Permissões
A maior falha de segurança em agentes de IA hoje não é prompt injection. É dar a eles credenciais emprestadas, permissões permanentes e nenhuma identidade própria — depois torcer para que nada dê errado.
Em 2026, 92% das empresas admitem não ter visibilidade plena das identidades de IA que já rodam nos seus sistemas. Outras 95% duvidam que conseguiriam conter um agente comprometido. O OWASP colocou isso no topo dos riscos: ASI03 — Identity & Privilege Abuse. Não é teoria. É a falha que está explodindo agora.
Este guia é sobre como montar um sistema de identidade e permissões para agentes de IA que funcione no mundo real. Sem prometer "zero trust mágico". Sem exigir um time de segurança enterprise. Você vai sair daqui com:
- Os 3 princípios que toda identidade de agente deve seguir
- Uma arquitetura mínima que pode ser implementada em um dia
- Código Python real para emissão, validação e auditoria de tokens
- Como separar agentes por classe de risco (e por que isso importa mais que parece)
- Um checklist para aplicar antes de colocar qualquer agente em produção
O Problema Real: Agentes Usam Suas Credenciais
Quando você conecta um agente ao Slack, GitHub, banco de dados ou AWS, qual credencial ele usa? Na maioria dos casos, uma das seguintes:
- Uma API key pessoal — a sua, do desenvolvedor.
- Uma service account genérica — usada por vários agentes e scripts.
- Um token de aplicação com permissões amplas — "vai que precisa".
- Uma variável de ambiente compartilhada —
.envno servidor.
Todas essas opções têm o mesmo defeito: o agente não tem identidade própria. Quando ele faz algo — envia uma mensagem, deleta um arquivo, lê um banco de dados — a ação aparece como se tivesse sido feita por você, por um script genérico ou por uma aplicação opaca. Você não consegue responder perguntas básicas:
- Qual agente executou essa ação?
- Em nome de qual usuário?
- Qual tarefa estava sendo executada?
- A permissão era realmente necessária?
Isso não é apenas um problema de auditoria. É um problema de controle. Um agente comprometido herda todas as permissões da credencial que está usando. E como ele não tem identidade própria, você nem consegue revogar o acesso dele sem quebrar tudo o mais.
Regra de ouro: um agente em produção deve ter sua própria identidade, permissões mínimas e tempo de vida limitado. Tudo o que fugir disso é dívida técnica de segurança.
Os 3 Princípios de Identidade para Agentes
Antes de código, os princípios. Eles parecem óbvios, mas são violados em quase todos os setups que eu vejo.
1. Identidade Própria
Cada agente deve ter uma identidade não-humana (NHI — Non-Human Identity) distinta. Não é "o meu usuário", não é "o script", não é "a aplicação". É agente-seo-prod, agente-suporte-tier1, agente-backup-noite.
A identidade precisa carregar metadados:
- Nome e propósito do agente
- Quem é o dono/responsável humano
- Ambiente (dev, staging, prod)
- Capacidades declaradas
- Data de criação e expiração
2. Menor Privilégio
O agente deve ter acesso apenas ao que precisa para cumprir uma tarefa específica. Não mais. E idealmente, a permissão deve ser concedida no momento da tarefa, não de forma permanente.
Isso significa:
- Sem permissões de admin "só para facilitar"
- Sem acesso a todos os canais do Slack — só ao canal relevante
- Sem leitura de todas as tabelas do banco — só às colunas necessárias
- Sem envio de email em nome de qualquer pessoa — só do remetente declarado
3. Tempo de Vida Limitado
Credenciais permanentes são bombas-relógio. Tokens devem expirar. Permissões devem ser escopo de tarefa. Quando a tarefa termina, o acesso termina com ela.
Na prática:
- Tokens com expiração curta (minutos ou horas, não meses)
- Refresh tokens separados e auditados
- Permissões "just-in-time" quando possível
- Revogação imediata em caso de anomalia
Arquitetura Mínima de Identidade para Agentes
Você não precisa de um IAM enterprise para começar. A arquitetura mínima tem quatro componentes:
1. Identity Provider (IdP): onde agentes se registram e se autenticam. Pode ser Auth0, Okta, AWS IAM, Google Workload Identity, ou um emissor JWT simples. O importante é que ele saiba quem é cada agente.
2. Token Scoped: o agente não carrega segredos permanentes. Ele recebe um token de curta duração com escopo explícito para aquela tarefa. Se o token vazar, o dano é limitado no tempo e no escopo.
3. Resource Gateway: uma camada entre o agente e os recursos reais. Ela valida o token, verifica se a permissão solicitada está no escopo, aplica rate limits e registra tudo para auditoria.
4. Recursos: as APIs, bancos de dados, canais de Slack, repositórios GitHub e tudo mais que o agente precisa acessar. Eles nunca devem confiar cegamente no agente — só no token validado.
Insight chave: o Resource Gateway é o segredo. Sem ele, cada recurso precisa implementar sua própria validação de token e permissões. Com ele, você centraliza a política de segurança.
Implementação Prática em Python
Vamos a código. O exemplo abaixo implementa um sistema mínimo de identidade para agentes usando JWT. Não é produção-ready em todos os sentidos, mas é um baseline sólido para começar.
Registro de Agentes
Cada agente precisa ser registrado antes de poder se autenticar. O registro define a classe de risco, as capacidades declaradas e o dono humano.
# agent_registry.py
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from typing import List
class RiskClass(Enum):
LOW = "low" # Apenas leitura, dados públicos
MEDIUM = "medium" # Leitura + escrita em recursos não críticos
HIGH = "high" # Acesso a dados sensíveis ou ações destrutivas
@dataclass
class AgentIdentity:
agent_id: str
name: str
owner: str # Responsável humano
environment: str # dev, staging, prod
risk_class: RiskClass
allowed_scopes: List[str]
allowed_resources: List[str]
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
expires_at: datetime | None = None
active: bool = True
# Exemplo de registro
AGENT_REGISTRY = {
"agent-seo-prod": AgentIdentity(
agent_id="agent-seo-prod",
name="SEO Specialist",
owner="andre@andrecosta.com.br",
environment="prod",
risk_class=RiskClass.LOW,
allowed_scopes=["web:read", "analytics:read", "report:write"],
allowed_resources=["https://api.example.com", "slack://#metricas"],
),
"agent-suporte-tier1": AgentIdentity(
agent_id="agent-suporte-tier1",
name="Suporte Tier 1",
owner="ops@andrecosta.com.br",
environment="prod",
risk_class=RiskClass.MEDIUM,
allowed_scopes=["ticket:read", "ticket:write", "kb:read", "slack:write"],
allowed_resources=["zendesk://tickets", "slack://#suporte"],
),
}
def get_agent(agent_id: str) -> AgentIdentity | None:
return AGENT_REGISTRY.get(agent_id)
Aqui já começa a diferença. O agente tem identidade própria, dono declarado, ambiente, classe de risco e escopos permitidos. Nada disso está na credencial — está no registro central.
Emissão de Token Scoped
O token JWT carrega a identidade do agente e o escopo da tarefa atual. Ele expira em poucos minutos. Não é uma API key permanente.
# token_issuer.py
import jwt
import uuid
from datetime import datetime, timedelta, timezone
from typing import List
SECRET_KEY = "sua-chave-secreta-muito-forte" # Em produção, use um KMS
ALGORITHM = "HS256"
def issue_task_token(
agent_id: str,
task_id: str,
scopes: List[str],
expires_in_minutes: int = 15,
) -> str:
"""Emite um token JWT scoped para uma tarefa específica."""
now = datetime.now(timezone.utc)
expires = now + timedelta(minutes=expires_in_minutes)
payload = {
"sub": agent_id, # subject: identidade do agente
"task_id": task_id, # tarefa específica
"jti": str(uuid.uuid4()), # token único (para revogação)
"scope": " ".join(scopes), # escopos concedidos
"iat": now,
"exp": expires,
"type": "agent_task_token",
}
return jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
# Exemplo de uso
from agent_registry import get_agent, RiskClass
agent = get_agent("agent-seo-prod")
token = issue_task_token(
agent_id=agent.agent_id,
task_id="seo-weekly-audit-2026-06-13",
scopes=["web:read", "analytics:read", "report:write"],
expires_in_minutes=30,
)
print(f"Token emitido para {agent.name}: {token[:40]}...")
Pontos importantes:
subé o ID do agente, não do usuário humano.task_idliga o token a uma tarefa específica.jtipermite revogar um único token sem invalidar o agente.scopedefine o que pode ser feito durante aquela tarefa.expgarante que o token não dure para sempre.
Validação de Token e Permissões
Antes de executar qualquer ação, o Resource Gateway valida o token e verifica se o escopo solicitado está incluído.
# token_validator.py
import jwt
from fastapi import HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from token_issuer import SECRET_KEY, ALGORITHM
from agent_registry import get_agent
security = HTTPBearer()
def validate_token(credentials: HTTPAuthorizationCredentials = Depends(security)) -> dict:
"""Valida o token JWT e retorna o payload."""
token = credentials.credentials
try:
payload = jwt.decode(
token,
SECRET_KEY,
algorithms=[ALGORITHM],
options={"require": ["exp", "sub", "scope", "task_id"]},
)
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail="Token expirado")
except jwt.InvalidTokenError as e:
raise HTTPException(status_code=401, detail=f"Token inválido: {e}")
agent = get_agent(payload["sub"])
if not agent or not agent.active:
raise HTTPException(status_code=403, detail="Agente não registrado ou inativo")
return payload
def require_scope(required_scope: str):
"""Dependency factory para exigir um escopo específico."""
def checker(payload: dict = Depends(validate_token)):
token_scopes = set(payload.get("scope", "").split())
if required_scope not in token_scopes:
raise HTTPException(
status_code=403,
detail=f"Escopo '{required_scope}' não concedido. Escopos: {token_scopes}"
)
return payload
return checker
Uso em uma rota protegida:
# main.py
from fastapi import FastAPI, Depends
from token_validator import validate_token, require_scope
app = FastAPI()
@app.get("/analytics")
def read_analytics(payload: dict = Depends(require_scope("analytics:read"))):
return {"message": "Dados de analytics", "agent": payload["sub"], "task": payload["task_id"]}
@app.post("/report")
def write_report(payload: dict = Depends(require_scope("report:write"))):
return {"message": "Relatório salvo", "agent": payload["sub"]}
O agente só acessa o que o token permite. Se ele tentar analytics:write com um token que só tem analytics:read, é bloqueado imediatamente.
Classe de Risco e Approval Gates
Agentes de alto risco não devem agir sozinhos. O código abaixo mostra como implementar approval gates baseados na classe de risco do agente.
# approval_gate.py
from enum import Enum
from agent_registry import get_agent, RiskClass
class ActionType(Enum):
READ = "read"
WRITE = "write"
DELETE = "delete"
EXTERNAL_SEND = "external_send" # email, slack, mensagem
FINANCIAL = "financial"
def requires_approval(agent_id: str, action: ActionType, resource: str) -> bool:
"""Decide se uma ação precisa de aprovação humana."""
agent = get_agent(agent_id)
if not agent:
return True # Desconhecido = bloqueia
# Alto risco: qualquer ação destrutiva ou externa exige aprovação
if agent.risk_class == RiskClass.HIGH:
return action in {ActionType.WRITE, ActionType.DELETE, ActionType.EXTERNAL_SEND, ActionType.FINANCIAL}
# Médio risco: delete, envio externo e financeiro exigem aprovação
if agent.risk_class == RiskClass.MEDIUM:
return action in {ActionType.DELETE, ActionType.EXTERNAL_SEND, ActionType.FINANCIAL}
# Baixo risco: apenas delete e financeiro exigem aprovação
return action in {ActionType.DELETE, ActionType.FINANCIAL}
# Exemplo
print(requires_approval("agent-seo-prod", ActionType.WRITE, "report")) # False
print(requires_approval("agent-suporte-tier1", ActionType.EXTERNAL_SEND, "slack")) # True
A regra é simples: quanto maior o risco do agente, mais ações precisam de confirmação humana. Isso evita que um agente de baixo risco precise de aprovação para tudo (fricção desnecessária) e que um agente de alto risco execute ações críticas sozinho.
Separação por Classe de Risco
Aqui está como eu separo agentes na prática:
| Classe | Exemplos de Agentes | Permissões Típicas | Controles |
|---|---|---|---|
| Baixo | SEO audit, monitoramento, relatórios | read em dados públicos/anonimizados, write em arquivos de saída |
Token 30 min, pouca aprovação |
| Médio | Suporte tier 1, triagem de leads, atualização de tickets | read/write em recursos não críticos, send em canais específicos |
Token 15 min, aprovação para delete/envio externo |
| Alto | Aprovação de pagamentos, acesso a PII, deploy em produção | Acesso limitado, ações destrutivas | Token 5 min, human-in-the-loop obrigatório, auditoria completa |
A separação por classe de risco é o que permite você ter agentes úteis sem transformar cada um deles em um risco de segurança. Um agente de SEO não precisa das mesmas permissões de um agente que aprova pagamentos.
Auditoria: Se Algo Der Errado, Você Precisa Saber o Quê
Identidade sem auditoria é inútil. Cada ação do agente deve ser registrada com:
- ID do agente
- ID da tarefa
- Token utilizado (
jti) - Ação executada
- Recurso acessado
- Resultado (sucesso/erro/bloqueado)
- Timestamp
# audit_logger.py
import json
import logging
from datetime import datetime, timezone
logger = logging.getLogger("agent_audit")
logging.basicConfig(level=logging.INFO)
def log_action(
agent_id: str,
task_id: str,
action: str,
resource: str,
token_jti: str,
result: str,
details: dict | None = None,
):
"""Registra uma ação de agente para auditoria."""
entry = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"agent_id": agent_id,
"task_id": task_id,
"action": action,
"resource": resource,
"token_jti": token_jti,
"result": result,
"details": details or {},
}
logger.info(json.dumps(entry, ensure_ascii=False))
# Exemplo
log_action(
agent_id="agent-seo-prod",
task_id="seo-weekly-audit-2026-06-13",
action="analytics:read",
resource="https://api.example.com/analytics",
token_jti="abc-123",
result="success",
details={"rows_read": 150},
)
Com logs estruturados, você consegue responder:
- "Qual agente leu esse banco de dados ontem à noite?"
- "Quantas vezes o agente de suporte tentou enviar mensagem fora do horário?"
- "Esse token foi usado para algo além do escopo declarado?"
Integração com Hermes Agent e Claude Code
Se você usa ferramentas como Hermes Agent ou Claude Code, a identidade do agente precisa ser respeitada por elas também.
Hermes Agent
No config.yaml do Hermes, você pode definir permissões granulares por agente:
# ~/.config/hermes/config.yaml
agents:
seo-specialist:
identity:
agent_id: "agent-seo-prod"
owner: "andre@andrecosta.com.br"
environment: "prod"
risk_class: "low"
token:
issuer_url: "https://idp.andrecosta.ia.br/issue"
max_ttl_minutes: 30
scopes: ["web:read", "analytics:read", "report:write"]
tools:
terminal:
allowed_commands: ["curl", "node"]
blocked_commands: ["rm", "sudo", "wget"]
file:
allowed_paths: ["./output/"]
blocked_paths: ["~/.ssh/", "~/.env", "/etc/"]
O Hermes já tem a noção de tools e allowed_paths. O que falta na maioria dos setups é o vincular isso a uma identidade central e a tokens de curta duração.
Claude Code
Claude Code pode ser iniciado com variáveis de ambiente que apontam para tokens scoped:
# Em vez de exportar uma API key permanente:
# export ANTHROPIC_API_KEY=sk-...
# Gere um token scoped para a sessão:
export CLAUDE_SESSION_TOKEN=$(python issue_token.py --agent agent-seo-prod --task "refatoracao-auth")
claude
No final da sessão, o token expira. Se alguém interceptar a variável de ambiente, ela é inútil em poucos minutos.
Checklist Antes de Colocar um Agente em Produção
Use esta lista para cada agente novo:
Identidade
- [ ] O agente tem um
agent_idúnico e descritivo? - [ ] Há um dono humano responsável declarado?
- [ ] O ambiente (dev/staging/prod) está definido?
- [ ] A classe de risco foi avaliada?
Permissões
- [ ] O agente tem apenas os escopos necessários para sua tarefa?
- [ ] Não há permissões de admin ou acesso irrestrito?
- [ ] Os recursos acessíveis estão explicitamente listados?
- [ ] Ações destrutivas ou externas exigem aprovação?
Tokens
- [ ] Tokens têm expiração curta (minutos, não meses)?
- [ ] Cada token está vinculado a uma tarefa específica?
- [ ] Existe mecanismo de revogação por
jti? - [ ] Tokens não estão hardcoded em
.envou no código?
Infraestrutura
- [ ] Existe um Resource Gateway validando tokens e permissões?
- [ ] Rate limiting está configurado por agente?
- [ ] Logs estruturados registram cada ação?
- [ ] Alertas existem para ações de alto risco ou anomalias?
O Que Você Não Precisa Fazer no Primeiro Dia
Não tente implementar tudo de uma vez. Aqui está a ordem que eu recomendo:
- Dia 1: registre todos os agentes existentes no
AGENT_REGISTRY. Apenas isso já dá visibilidade. - Dia 2: substitua API keys permanentes por tokens scoped com expiração curta.
- Dia 3: adicione o Resource Gateway nas APIs mais críticas.
- Dia 4: implemente approval gates para ações destrutivas.
- Semana 2: adicione auditoria completa e alertas.
Você não precisa de SPIFFE/SPIRE, mTLS entre todos os serviços ou um IAM enterprise para começar. Precisa de três coisas: identidade própria, permissões mínimas e tempo de vida curto.
Conclusão
Agentes de IA são usuários não-humanos. E assim como você não daria a senha do seu banco para um estagiário sem controle, você não deve dar credenciais permanentes e irrestritas para um agente.
A boa notícia é que a solução não é mágica. É arquitetura básica de segurança aplicada a um novo tipo de ator: identidade própria, menor privilégio, tokens de curta duração, Resource Gateway e auditoria.
Comece pelo registro. Depois pelos tokens. Depois pelas permissões. Em poucos dias, seus agentes passam de "scripts com poder de fogo" para "colaboradores não-humanos com carteira de identidade".
Próximos passos:
- Liste todos os agentes que você tem rodando hoje
- Defina uma identidade para cada um no registro
- Substitua a primeira API key permanente por um token scoped
- Leia o guia de segurança de agentes de IA para complementar as camadas de defesa
- Aplique o checklist acima antes de colocar qualquer agente novo em produção
Fontes e Referências
- OWASP. "Top 10 for Agentic Applications 2026." genai.owasp.org
- Cloud Security Alliance. "The AI Agent Governance Gap: What CISOs Need Now." cloudsecurityalliance.org
- NIST NCCoE. "Accelerating the Adoption of Software and AI Agent Identity and Authorization." nccoe.nist.gov
- Auth0 / Okta. "Lessons from OWASP Top 10 for Agentic Applications." auth0.com
- PyJWT. "JSON Web Tokens in Python." pyjwt.readthedocs.io
- FastAPI. "Security — OAuth2 with Password (and hashing), Bearer with JWT tokens." fastapi.tiangolo.com
Publicado em andrecosta.ia.br.