// ai · security
marlin
Problem
Service businesses want chat automation — answering reviews, triaging requests, capturing receipts. The usual route hands an LLM API tokens and the authority to act. That’s not automation, that’s a security hole with a chat interface: one injected prompt in a customer email and the model acts in the company’s name.
Approach
marlin makes the boundary deterministic. Five rules form the spine:
- LLM out of the action path. The model produces text only — drafts, classifications, extractions. It holds no tokens, no shell, no network. Deterministic code holds the secrets and executes every privileged action.
- Allowlist over blocklist. “Never do X” as a prompt rule is weak; injection beats instructions. The real guardrail is that the capability doesn’t exist. You can’t be tricked into using a power you don’t have.
- The LLM is never the security boundary. Authorization is deterministic RBAC on Discord roles read from the API — unforgeable.
- Human approval before side effects. The model drafts, an authorized human clicks approve, a deterministic sender executes.
- Untrusted text is data, not command. Every privileged action lands in an append-only audit table.
Short form: the LLM proposes; code disposes. Each tenant runs as its own hardened container — minimal privileges, no Docker socket, outbound connections only.
Decisions
- No memory framework in the MVP. Generic memory layers remember the wrong things and decide for you. Curated, reversible memory behind explicit commands beats automatic collection.
- Threat model made explicit: prompt injection via attacker-controlled review, mail, or chat text yields, at worst, a bad draft — never a breach.
Status & learnings
Built, deployed, first phases ran in production — currently paused. The security model is the actual product: the patterns (LLM out of the action path, allowlist, deterministic RBAC) transfer to any agent system that touches untrusted text.