DocsGovern AI agentsProtect your agents

Protect your agents

bash
memnox protect                      # detects Claude Code and Cursor, installs both
memnox protect claude-code          # or name one explicitly
memnox protect cursor

memnox setup already did this. protect is for adding a surface later, or for a machine where setup ran before the editor was installed.

The four surfaces

An agent has to be stopped somewhere, and where depends on what it is running inside. Four mechanisms, all asking the same runtime the same question.

govern.surfacesfour ways in, one gate

Where the agent is caught

Claude Code

PreToolUse hook

The hook exits 2, and Claude Code drops the tool call.

allowblockrequire approval — not available hereredact — not available here

Cursor

agent hooks

preToolUse, beforeShellExecution, beforeMCPExecution, beforeReadFile.

allowblockrequire approvalredact — not available here

Any MCP client: Windsurf, Zed, Codex, …

@memnox/mcp-firewall

Proxies the server, so it sees the call before the server does.

allowblockrequire approvalredact

Custom loops: OpenAI Agents SDK, LangGraph, CrewAI

governTool / governTools

Your own code holds the decision, so it can act on all of it.

allowblockrequire approvalredact

One answer, four shapes

allow
block
require approvalnot everywhere
redactnot everywhere
the verdict is the same everywhere; what the surface can do with it is not

Read the struck-through words. A surface that cannot carry a verdict does not ignore it, it refuses instead. Ask Claude Code's hook for an approval and it denies, because exit 2 is the only "no" the hook has; ask either editor to mask a payload and it denies, because neither can hand back a rewritten call. Refusing is the safe direction, but it is not the behaviour the rule described, so a rule that leans on redact belongs on a surface that can perform it.

Cursor is the closest fit of the two editors: its allow / deny / ask are Memnox's allow, block, and require-approval exactly. Nobody engineered that match, and it is why the integration is honest rather than approximated. Cursor also fires afterFileEdit, which Memnox records but cannot act on: by the time it arrives the edit has already landed.

The MCP firewall

An MCP server does two things for your agent: it offers a list of tools, and it runs the ones the agent picks. The firewall stands between the two.

Your client stops launching the server directly. It launches the firewall, and the firewall launches the server, so every message between them passes through Memnox on the way.

mcp.firewalltwo moments, both guarded
Your MCP clientWindsurf, Zed, Codex, …
list · call
memnox-mcp-firewallasks the runtime, then edits what passes
only what survived
The real MCP servergithub, postgres, filesystem, …
the client believes it is talking to the server; it is talking to the firewall

On the list, a denied tool is removed rather than left there to fail. The agent never learns it existed, so it never proposes it, argues for it, or works around it. A tool that fails when called teaches an agent to try something else; a tool that was never on the menu teaches it nothing.

On the call, the check runs again. A client can call a tool it was never offered, so the listing is not treated as a promise.

Point your client at the firewall instead of the server:

bash
MEMNOX_AGENT_TOKEN=mnx_... memnox-mcp-firewall \
  --name github -- npx -y @modelcontextprotocol/server-github

Part

MEMNOX_AGENT_TOKEN

The credential the firewall uses to reach the runtime. Without it the firewall has nothing to ask, and an unauthenticated gate allows everything, which looks identical to being protected. memnox setup writes a token to ~/.memnox/config.json; this environment variable overrides it.

--name <server-name>

What this server is called in policy rules and in every audit line. Actions arrive as mcp.<tool> and this name is how you tell one wrapped server from another. Defaults to mcp-server, which is worth replacing the moment you wrap a second one.

--

The divider. Everything before it belongs to the firewall; everything after it is the server command, passed through untouched. It is not optional, because the firewall has no other way to know where its own flags stop.

So the last part of that line is exactly what your MCP client used to run. The firewall runs it for you, and sits in front of it.

This is also the surface where redact genuinely works. Because the firewall is holding the call rather than voting on it, it can rewrite the payload: mask the secret, forward the rest. An editor hook has only yes and no, so the same rule there comes out as a refusal.

Custom agent loops

ts
import { MemnoxClient, governTools } from '@memnox/sdk';
 
const memnox = new MemnoxClient({
  baseUrl: 'http://127.0.0.1:7466',
  token: agentToken,
});
 
const tools = governTools(memnox, { readFile, writeFile, runShell }, {
  sessionId: runId,
  environment: 'production',
});

Same signatures, same framework wiring, each call is now decided before it runs.

Or wrap a single dangerous operation:

ts
await memnox.guard(
  { action: 'code.modify', target: 'payment/checkout.ts' },
  async () => { await applyChanges(); },
);

guard runs the callback only if the runtime allows it. check returns the verdict for you to inspect instead.

The token, and why it is on disk

memnox setup writes the agent token to ~/.memnox/config.json, mode 0600.

That is deliberate. A GUI-launched editor inherits no shell environment, so an exported MEMNOX_AGENT_TOKEN never reaches it, and a hook with no credential allows everything, which looks exactly like being protected.

The environment still wins when it is set, which is how CI and the MCP firewall pass a token.

Registering agents

bash
memnox agents register --name ci-deployer --kind custom
memnox agents list
memnox agents suspend <id>
memnox agents rotate <id>

Part

--name <name>

What this agent is called on every audit line. Pick something you would recognise at 3am: ci-deployer, not agent-2.

--kind <kind>

One of claude-code, cursor, openai-agent, mcp, or custom. It is descriptive, not a permission. Defaults to custom.

<id>

The agent id printed by memnox agents list. It is never something you invent. If you are constructing one, you are on the wrong command.

register prints the agent's token once. Copy it then; there is no command that shows it again, only rotate, which issues a new one.

Capabilities

Capabilities are the cheapest control in the product. They are wildcard action patterns checked before policy runs, so an agent registered to read cannot argue its way into a write regardless of what the policy file says. A denial here never consults your rules at all.

They are set when the agent is registered, and the CLI has no flag for them, so this is one of the few places you call the API directly:

bash
curl -X POST http://127.0.0.1:7466/v1/agents \
  -H "Authorization: Bearer $MEMNOX_ADMIN_TOKEN" \
  -H "content-type: application/json" \
  -d '{"name":"ci-deployer","kind":"custom","capabilities":["deploy.*","file.read"]}'

capabilities is an array of patterns, where * stands for any remainder: deploy.* covers deploy.service and deploy.worker, while file.read covers that one action alone. Leave the field out and the agent may attempt anything, which is rarely what you want. The route needs an admin credential, and it returns the new agent's token in the response: the same once-only token register prints.

Register narrowly. A CI agent that only deploys should not carry *.

Fail-open, and why

The hook has to reach the runtime. If the runtime is down, the hook fails open: a dead process never blocks development.

That is the right trade for a laptop and the wrong one for a server. In a deployment where the gate is load-bearing, run the runtime supervised, alert on GET /healthz, and use --default-effect block so an ambiguous state refuses rather than permits.

CI

bash
memnox ci        # exits 1 on a blocking finding in the branch's diff

Run it in the pipeline that already runs your tests. It scans the diff for secrets and personal data, so a leaked credential is caught by a person in review rather than by an agent at runtime.

It is a content scan, not a full policy evaluation. Policy still decides what an agent may do; memnox ci decides whether what was written is safe to commit.