Suppose you ask an agent to preview a configuration change. It says it will read the current settings, prepare a patch and wait for approval. The connected tool still has production write credentials.
You have a request for restraint. You do not yet have a read-only workflow.
Shadow mode should let you inspect a proposed change before giving the agent authority to perform it. That requires a boundary outside the conversation. A prompt that says “do not write” cannot revoke a credential, block a shell command or stop a tool from starting a downstream job.
Separate planning access from execution access
For this workflow, shadow mode means a planning pass with business mutations blocked. It may read approved inputs and save its proposal to a designated staging area. That staging write is an explicit exception, not permission to edit the repository or call production APIs.
This is an operating pattern, not a claim about a particular Claude Code setting. Implement it with the controls your tool path actually supports: a restricted identity at the receiving service, a tool gateway that rejects mutations, or a sandbox with production credentials and network paths removed. Several controls may be necessary if the agent has more than one way to reach the same system.
Do not leave a general shell or alternate HTTP client holding the credentials that the MCP gateway refuses to use. The agent’s effective authority includes those routes too.
A plan records proposals, not every considered action
Ask for the target, proposed payload, relevant input versions and order of operations. Review whether the proposed scope matches the task. A planned fallback that reaches a different account deserves attention before anyone approves execution.
But the plan is generated output. It cannot prove that the agent listed every action it considered, and it cannot guarantee what a later run will do. A tidy plan may omit a denied call that matters to the reviewer.
Compare the proposal with independently collected tool events. Record attempted calls and policy decisions as well as successful results. Keep sensitive arguments out of ordinary logs; retain restricted evidence only where the review needs it.
For the next boundary, validate the proposal at the receiving system. A generated plan should not become an executable instruction merely because it is valid JSON.
Prove preview cannot write
Start in an isolated test environment. Exercise the path that the agent will actually use, including the identity, adapter and receiving service. A mocked rejection proves little about a production credential that bypasses it.
| Test | Expected result | Evidence to keep |
|---|---|---|
| Read an approved fixture | The read succeeds | Request identity, target and returned version |
| Attempt a forbidden update | The enforcement point rejects it before mutation | Denial event and an independent state check |
| Call a nominal read that triggers work | The route is blocked or replaced with an inert fixture | Queue, webhook and downstream state checks |
| Execute the reviewed proposal | Preview credentials still fail; separately approved execution follows its own policy | Approval record and receiving-system receipt |
The permitted read is a positive control. Without it, “everything was denied” may mean the adapter is broken rather than correctly restricted. The write-refusal test guide includes a runnable teaching fixture for that distinction.
A method named get_report is not necessarily harmless. In a hypothetical service, fetching a report could also refresh a cache, enqueue an export or send a notification. Classify the route by its effects, not its name or HTTP verb. Decide which incidental writes, such as access logging, are acceptable and which business effects must be absent.
Check those effects at the receiving system. An agent saying “I did not write” is not the observation you need. A single immediate check may also miss queued work: use the service’s documented completion or drain signal and record the observation window. If you cannot account for a downstream effect, leave that route unavailable during preview.
Use a preview boundary review record
Download the preview boundary worksheet and fill it in for one workflow. It is a blank review artifact, not executable policy or proof that your environment is safe.
The record asks who owns the boundary, which identities can reach it, what the permitted control did and where the reviewer checked for side effects. Attach actual evidence references. An unchecked box should remain an open question rather than becoming a claim in the approval packet.
Keep the proposal and the test record together. A reviewer should be able to distinguish “the plan looks reasonable” from “the configured preview identity was tested against a forbidden mutation.”
Give execution its own approval
Do not promote the preview session by quietly attaching stronger credentials. Start a separately authorized execution step with a narrow identity and the reviewed proposal as input.
Bind approval to the target and exact payload, plus the input versions that matter to the decision. A changed account, widened scope or stale configuration should require review again. Enforce that comparison at the point of action; copying an approval ID into a prompt does not enforce it.
A planning pass costs time and tokens. Use it where reviewing the proposed action is worth that cost, especially when recovery is difficult. Repeated clean previews may support a decision to automate a narrow task class, but they do not justify removing its runtime permission checks.
If you are building this review process around Claude Code, explore the Claude Code production-agents book. It is the next step for readers who need a broader operating approach to permissions and review, beyond a single preview worksheet.