Lesson 2 · ClaudeTag

Scoping a prism-ops Channel

Turn the four-clause contract into a real, least-privilege Access bundle for your own system.

~7 min · builds on Lesson 1 + channel-scoped memory

You know the contract — objective, tools, instructions, budget — and you know each channel has its own walled memory. Now we use both to design a prism-ops ClaudeTag: a Claude that lives in one Slack channel, watches Prism, and is structurally unable to do the dangerous things you haven't authorised.

Honest caveat ClaudeTag Access bundles are configured through the admin UI, not a file. The YAML below is a thinking tool — "scoping as code" — so the decisions are explicit and reviewable. It maps 1:1 onto what you'd click in claude.ai/admin-settings/claude-tag.[ref]

1. The bundle skeleton

An Access bundle is "a named set of credentials, repository grants, plugins, and instructions."[ref §6] Here is the shape, before we fill it in:

access_bundle: prism-ops
channel: #prism-ops          # memory + scope live here, nowhere else
tools:        [ ... ]        # least-privilege allowlist  (the "tools" clause)
repos:        [ ... ]        # e.g. MT5EA  (grant only what's needed)
instructions: |              # the per-channel system prompt  (the "instructions" clause)
    ...
spend_cap:    $___ / month   # the "budget" clause

2. The hard part: which tools?

Your prism MCP server exposes ~24 tools. Least-privilege says: this is a team-visible monitoring channel, so grant the read tools freely and treat anything that touches live money as a separate decision. Make your call on these before you reveal:

Tool(s)CallWhy
account_status, system_health, open_positions, daily_pnl, dd_state, recent_trades, ea_log, effective_configGRANTRead-only. The whole point of an ambient prism-ops channel — let the team and Claude see state.
run_backtest, query_live_dbGATERead-ish but expensive / DB-heavy. Allow, but the instructions must cap cost and forbid long-running DB maintenance (your past mcp-ssh timeout incident).
close_all_positions, resume_globalWITHHOLDMutates live money. Not in a team channel's bundle. If you ever want them, they go in a locked private channel with human confirmation — never auto.
kill_globalGATE — your callThe interesting edge: destructive, but it's the safety control. Grant it only if instructions force "confirm with a human before firing, then report" — otherwise withhold. This is the "never delegate risk-control to coder" rule, applied to a Slack bot.

The lesson: read vs mutate is the first cut; "is it a risk control?" is the second. Same instinct as your routing policy, now expressed as a tool allowlist.

Why does kill_global deserve more thought than close_all_positions?

Both mutate live state, but kill_global is the brake — withholding it entirely can be less safe in an incident. So it's a deliberate "gate with human confirm," not an automatic withhold. Neither is read-only.

3. The instructions = your system prompt

This is where your global rules become the bundle's standing behaviour. Lift them straight from how you already run agents:

instructions: |
  You are prism-ops, monitoring the live FTMO account (read account
  number from accounts.json, never hardcode).
  - ROOT CAUSE FIRST: never propose marking rows failed / blacklisting
    symbols before diagnosing. State hypothesis, verify with logs, then fix.
  - VERIFY BEFORE CLAIMS: never say a service is up without a real check.
  - DATA FRESHNESS: never act on a bar older than 90s (M1).
  - DESTRUCTIVE = CONFIRM: never fire kill_global / restart anything
    without explicit human approval in this channel.
  - DEPLOY = REVIEW: any code change gets a reviewer pass first.
  - Report status updates prefixed with a UTC timestamp.
The payoff That block is the bridge to your mission. It's the same standing-rules text you'd put at the top of a subagent prompt — ClaudeTag just attaches it to a channel and a memory instead of a single run. Write it once, scope it well, and the agent stops needing babysitting.

4. The budget clause

For a monitoring channel that mostly reads state, the right spend posture is:

Over-cap work is declined entirely (not half-done), which is the safe failure you want. A modest cap on a read-heavy channel bounds blast radius; reserve Unlimited for nothing that touches live money. Caps ARE configurable ($100–$1M or custom).

5. Your win: the finished bundle

access_bundle: prism-ops
channel: #prism-ops
tools:  [account_status, system_health, open_positions, daily_pnl,
         dd_state, recent_trades, ea_log, effective_config,
         run_backtest, query_live_db]      # kill_global only if gated
repos:  [MT5EA]                              # read; deploys go via reviewer
instructions: |  (the standing-rules block above)
spend_cap: $250 / month

You just wrote a complete delegation contract for a real channel — and every clause traces back to a rule you already follow. That's the transfer: good agent prompts are scoped Access bundles, whether or not they live in Slack.

Read this next ~5 min: Set up Claude Tag — admin docs, especially the Access-bundle and per-channel-credentials sections.
Ask your teacher Bring me one of your real subagent prompts (scout, trading-medic, the guardian) and I'll convert it into this four-clause bundle form live — or we can pressure-test the kill_global decision properly. Lesson 3 could cover ambient mode: turning prism-ops into a guardian that speaks first.