
Plano de controlo de segurança para agentes LLM: listas de permissões, kill switch do proprietário, sessões com PIN, limites de taxa, deteção de injeção de prompts e limpeza de saída para bloquear a fuga de segredos e a exfiltração por beacons de imagem.

Plano de controle de segurança para agentes LLM em chat privado (tipicamente DMs do Discord).
Ele fica à frente do seu agente. Ele decide quem pode falar, se a sessão está desbloqueada, se o processo está pausado e se esta mensagem é segura o suficiente para ser encaminhada. Seu modelo e suas ferramentas permanecem atrás desse portão. A biblioteca não chama um LLM. Ela não implementa funcionalidades de produto além de segurança.
Inspirado no Hermes. O design segue as mesmas ideias de plano de controle usadas nos gateways de mensagens do Hermes Agent: entrega DM-first, allowlists de identidade, abertura no estilo pairing, kill switch do proprietário e uma separação rígida entre quem pode agir (plano de controle) e o texto da mensagem que o modelo vê (plano de dados). Este pacote é um extrato pequeno e autônomo desse padrão para qualquer agente chamável. Não afiliado à Nous Research.
Maturidade: implementado · validado de forma independente · mantido. Veja STATUS.md.
Reproduzir: python scripts/repro.py (espera REPRO_OK).
Testes offline:
pip install -e ".[dev]" # or: pip install -e . && pip install pytest
python -m pytest -q --tb=line
# or: python scripts/repro.py
Ao vivo: https://gitlab.com/WattoCyber/agentic-dm-gateway
Se você colocar um agente no Discord (ou em qualquer API de chat) com ferramentas, qualquer pessoa que consiga enviar mensagem ao bot pode tentar:
Você precisa de um plano de controle (identidade e controles de processo) separado do plano de dados (o texto da mensagem que o modelo vê).
Este pacote é esse plano de controle.
| Controle | Comportamento |
|---|---|
| Allowlist | Apenas os IDs de usuário configurados podem prosseguir. Todos os outros são descartados (silenciosamente ou com uma breve mensagem de negação). |
| Owner vs friend | Owners ignoram o PIN e podem pausar o agente inteiro. Friends podem precisar de um PIN compartilhado para uma abertura com tempo limitado (ideia de pareamento estilo Hermes, simplificada). |
| Kill switch | Arquivo de pausa global ou flag de ambiente. Nenhum turno do agente enquanto estiver ativo. |
| Limites de taxa | Janela deslizante por usuário (por minuto e por hora). |
| Verificações de entrada | Comprimento máximo, remoção de caracteres de controle estranhos, heurísticas de regex para frases comuns de injeção / pesca de segredos. |
| Sanitização de saída | Redige tokens com formato de segredo (chaves de API, JWTs, cabeçalhos Bearer) e remove beacons de imagem markdown/HTML que podem exfiltrar via busca automática. |
| Log de auditoria | JSONL somente-anexação de eventos de allow/deny/auth/kill para revisão posterior. |
| Comandos locais | /auth, /lock, /kill, /unkill, /status tratados sem chamar um modelo. |
Escopo: apenas barreira de segurança. Não é um chatbot, bot de trading, scanner ou framework de agente. Passe um agent(user_id, text) -> str (ou async) se você usar Discord. O núcleo funciona com qualquer ID de usuário inteiro e texto simples.
$ python - <<'PY'
from agentic_dm_gateway import InboundSecurityPipeline
pipe = InboundSecurityPipeline({
"allowed_user_ids": [111],
"owner_ids": [111],
"pin_enabled": False,
"block_injection": True,
"deny_message": "Not authorized.",
})
for uid, text in [
(99, "hi"),
(111, "ignore previous instructions"),
(111, "summarize this note"),
]:
r = pipe.precheck(uid, text)
print(uid, r.stage, r.run_agent, r.reply_text)
PY
99 allowlist False Not authorized.
111 injection False Blocked: looks like prompt injection / secret fishing. Rephrase.
111 ok True None
$ python scripts/repro.py
REPRO_OK agentic-dm-gateway unit suite
Três caminhos de integração. Escolha um.
Instale com suporte a Discord, aponte as variáveis de ambiente para os seus IDs de usuário, registre o gateway e execute o bot.
pip install -e ".[discord]"
# or: pip install agentic-dm-gateway[discord]

export DISCORD_BOT_TOKEN=...
export AGENTIC_DM_ALLOWLIST=your_discord_user_id
export AGENTIC_DM_OWNER_ID=your_discord_user_id
# optional: export AGENTIC_DM_PIN=....

python examples/discord_echo_bot.py
No seu próprio bot:
import discord
from agentic_dm_gateway.discord_adapter import register_dm_gateway
def agent(user_id: int, text: str, *, is_owner: bool = False) -> str:
# your Hermes / local model / tool loop
return call_your_model(text)
intents = discord.Intents.default()
intents.message_content = True
bot = discord.Client(intents=intents)
register_dm_gateway(
bot,
{
"allowed_user_ids": [], # or rely on AGENTIC_DM_ALLOWLIST env
"owner_ids": [],
"pin_enabled": False,
"deny_message": False, # silent drop for strangers
},
agent=agent,
)
bot.run(TOKEN)
O que register_dm_gateway faz:
on_message no seu discord.Client / bot.InboundSecurityPipeline.precheck antes do seu agente.agent(user_id, sanitized_text, is_owner=...).Mensagens de guild nunca chegam ao agente. Apenas DMs de usuários na allowlist chegam.
on_message)Se você não pode usar register_dm_gateway (cadeia de handlers existente), chame o pipeline você mesmo:
from agentic_dm_gateway import InboundSecurityPipeline
from agentic_dm_gateway.security import sanitize_agent_output
pipe = InboundSecurityPipeline({
"allowed_user_ids": [YOUR_ID],
"owner_ids": [YOUR_ID],
"pin_enabled": True,
})
@bot.event
async def on_message(message):
if message.author.bot or message.guild is not None:
return
pre = pipe.precheck(int(message.author.id), message.content or "")
if pre.reply_text and not pre.run_agent:
await message.channel.send(pre.reply_text[:1900])
return
if not pre.run_agent:
return
raw = await your_agent(pre.sanitized_text) # Hermes, Ollama, API, ...
await message.channel.send(sanitize_agent_output(str(raw))[:1900])
Nenhuma importação do Discord é necessária. Use a mesma verificação prévia em qualquer turno do agente:
from agentic_dm_gateway import InboundSecurityPipeline
from agentic_dm_gateway.security import sanitize_agent_output