Who this is for
Owners who would love agents handling invoices, leads and the daily to-do list, and who will not hand their inbox to anything that can send, delete or pay on its own. And builders who want to install that for them.
The agent-team guides you have seen give each agent a role and a nice prompt. A prompt is a request. This guide adds the part that makes it safe to run: a fence that decides every tool call before it happens.
What you get at the end
- Roles as separate headless Claude Code runs, each with its own charter, tool list and folders.
guard.py, a PreToolUse hook: default deny, writes only inside the role's folders, and hard rules that beat any policy (no recursive delete, no git push, no outbound POST, no mail commands, no keychain, no SQL deletes, no MCP action named send, delete, pay, publish, reply, forward, invite or share).- A JSONL audit log with one line per tool call, allowed or blocked.
- A daily run that ends with three lines from every agent: DONE, NEEDS HUMAN, BLOCKED.
What it costs
- The owner's Claude plan, on a Mac they own. No API keys.
- Python 3. The fence is stdlib only, about 150 lines you can read in ten minutes.
- An afternoon to write the first policy with the owner. That conversation is the real product.
Build it
- Copy the
fenced-agent-crewskill into~/.claude/skills/and make a crew folder, for example~/crew. - Copy
templates/policy.example.jsonto~/crew/policy.json. Setworkspace. Keep three roles to start: billing, sales, chief. - Sit with the owner and ask one question per role: "what must wait for you?" Write the answer into the role's
about. Those actions never go inallow_hard. - Give each role the fewest tools that do the job. Sales gets web search and its own drafts folder. Billing gets the invoice exports and a drafts folder. Chief reads everyone's drafts and writes one brief.
- Run one role by hand:
scripts/run_role.sh billing "Find unbilled work in exports/ and draft reminders" policy.json. - Open
logs/audit/and read every blocked line with the owner. Each one is either a policy that is too tight or an agent that tried something it should not. Loosen only with their yes. - Schedule the daily run with what they already have (a Claude Desktop scheduled task works) and put the chief's brief where they read things: email draft, Notion page, or a text file on the desktop.
Prompts to copy
Write the first policy with the owner:
Help me write policy.json for a fenced agent crew at {business}.
Ask me one role at a time: what it should produce each day, what it needs to
read, and what it must never do without me. Default to fewer tools. Put every
"never without me" action in the role's about line, never in allow_hard.
Show me the JSON and the reasons for each tool before saving.
Review a week of audit logs:
Read logs/audit/*.jsonl for the last 7 days. Group the blocked calls by role
and reason. For each group, say whether the policy is too tight (the agent
needed it to do its job) or the agent overreached (it tried something outside
its charter). Recommend at most 3 policy changes. Do not edit policy.json.
Sell it
This is an Ops Install: one painful back-office process turned into a fenced crew on the client's own machine. Our sheet prices installs at $3,500 and custom builds at $6,000, with a monthly plan from $150 to $400 to tune the policy, read the audit log and add roles. Sell the fence first; the agents are the easy part.
Hi {name}, quick idea for {business}.
I set up AI assistants that do the back-office work (chasing invoices, sorting
leads, a daily to-do brief) on your own computer. They draft; you send. A fence
blocks them from sending, deleting or paying anything, and every action is
logged so you can see exactly what they did. Worth a 20 minute look?
Where it breaks
- The fence sees tool calls, not intent. A role that can write into a folder another program runs from has indirect power. Keep write paths to drafts and logs.
- Bash allowlists are glob matches on the whole command, so a pattern ending in
*also matches chained commands. The hard rules still stop the dangerous ones; give Bash only to roles that need it. - MCP tool names differ by connector. Read the names the client's connectors expose before trusting the send and delete word list.
- The audit log is only useful if someone reads it. Put a weekly review on the plan, or sell the monthly plan that includes it.
Receipts
HQ runs its own back office this way: six business agents (chief, ops, billing, sales, analyst, librarian) on one Mac, each behind a guard hook, with every Notion write appended to a dated audit file. Billing and sales draft; nothing has ever been sent by an agent. The fence in this skill is a stdlib cut-down of that guard.
Prove it: python3 -m unittest discover -s tests inside the skill runs 9 tests, including a * bash allowlist that still cannot run rm -rf, git push or a keychain read, path escapes with ../, and fail-closed on a missing policy or bad input.