Skip to content

Trust, security & evaluation

An agent can be useful and still be unsafe. A repository can contain prompt injection, a skill can smuggle in an instruction, an MCP server can expose a destructive tool, and a headless run can repeat a mistake without anyone present to stop it.

The practical question is not “is this agent trusted?” It is: which inputs can influence it, which actions can it take, and which layer can still stop a bad action?

Every control lives at a layer, and the layer decides what the control can promise. Anything made of text - prompts, rules, skill bodies - can only ask the model to behave. Controls placed in the action path can refuse an action regardless of what the model decided. Controls around the process can contain damage even when both the model and the gate are fooled. That is the whole logic of the ladder: the further a control sits from the model’s output, the less it depends on the model’s cooperation.

LayerWhat it doesWhat it cannot promise
Prompt, rules, and skillsTells the model what to doThe model will follow it or resist hostile context
Model-selected skill or agentPackages a role, procedure, or tool surfaceThe selected component is benign or current
Approval policyPuts a human or preconfigured policy in the action pathA person will read every approval, especially in CI
Hook or runtime gateBlocks, rewrites, or audits supported lifecycle eventsUnsupported paths or actions outside the runtime are covered
OS sandboxLimits filesystem, process, and network reachThe task result is correct or secrets are available safely
Repository or server-side enforcementProtects branches, deploys, credentials, and external systemsLocal work before the request reaches the boundary

This is why “plan mode,” “auto,” and “deny” need qualification. They are product labels, not universal security guarantees. The label is not the boundary; the layer is. See Permissions & sandboxing, Hooks, and Plan mode for the tool-specific boundaries.

Before enabling a new capability, ask what can arrive through each channel:

  • Repository content: source files, issues, fixtures, generated files, and comments can contain instructions aimed at the model rather than the developer - a fixture comment reading “ignore the failing assertion” is an attack on the reader of the file, not on the test runner.
  • Tool output: search results, logs, webpages, and MCP resources can carry untrusted text. Treat tool descriptions and annotations as data, not policy.
  • Installed components: skills, plugins, extensions, and MCP servers are executable supply-chain dependencies. Review their source, pin versions where possible, and remove unused access.
  • Credentials and reach: give a workflow only the tokens, directories, network access, and worktree it needs. A read-only task should not inherit deployment credentials.
  • Unattended execution: headless and background runs need preconfigured approval, sandbox, hook, timeout, output-validation, and rollback policies because no person may be present at the moment of action.

The model’s context is the attack surface: every channel that can write into it is an input path.

The MCP security principles and authorization specification are useful reference points: servers can perform arbitrary actions on connected systems, and consent must remain explicit and under host control.

Evaluate the workflow, not just the prompt

Section titled “Evaluate the workflow, not just the prompt”

An agent configuration is a small software system, and “the model says it succeeded” is not a test result. Watch one toy run at real scale: a nightly job that drafts release notes from the merged PRs.

The obvious check is to read the output. It reads well, every sentence is plausible, the run ends green, and the summary explains exactly what it did and why. Plant that verdict: reads well, ship it.

Now grade artifacts instead. The postconditions are dumb on purpose: every PR number since the last tag appears in the file, no entry survives a revert, exit code zero. PR #4821 was squash-merged with a rewritten title, so the draft misses it; #4799 was reverted an hour after merging, but its entry is still there. Both misses are invisible in prose that reads well and fatal in a diff against git log. Deterministic checks catch what a readable summary hides.

That toy is the loop, generalized:

  1. Define a task with a fixture, an acceptance test, and explicit forbidden outcomes.
  2. Run it in a disposable worktree with the smallest useful tool and credential set.
  3. Capture the trace: model, rules, skills, tool calls, approvals, files changed, duration, and cost.
  4. Grade the result against deterministic postconditions before reading the model’s explanation.
  5. Repeat on representative failures and adversarial inputs, then compare against the previous configuration.

Track at least:

MetricWhy it matters
Task success rateDid the workflow satisfy the acceptance test?
Intervention rateHow often did a human need to rescue or redirect it?
Rework / regression rateDid the “successful” change create follow-up work or break tests?
Cost and latencyIs the workflow economical enough to run at its intended frequency?
Unsafe-action rateDid it attempt a forbidden or out-of-scope action?
Context/retrieval failuresDid it miss the right file, rule, skill, or tool before generation began?

Keep the task set small and versioned. A five-case regression suite that runs on every rules, skill, hook, model, or plugin change is more useful than a large benchmark nobody reruns.

The postcondition is the ladder again: a check that sits at a layer text cannot argue with. Everything else in the loop exists so that check has something deterministic to grade.

Before installing or enabling a component:

  • What does it read, write, execute, and send over the network?
  • Which product surfaces support it, and is it preview or stable?
  • Can its permissions be narrowed or its version pinned?
  • What happens if the model follows hostile text returned by the component?
  • What deterministic check catches a bad result?
  • Can the run be stopped, inspected, reverted, and attributed?

If the answers are unclear, keep the component out of unattended workflows until they are documented and tested.

Showing: Claude Code pick a tab to change

Claude Code separates model guidance from runtime controls. CLAUDE.md, skills, MCP descriptions, and repository content influence the model, but permission rules decide whether a tool call may proceed. Project and user settings can allow, ask, or deny tools and command patterns. PreToolUse hooks can inspect a request before the permission prompt and block it, while deny rules still win over an attempted allow. The native sandbox adds filesystem and network limits for Bash; it complements permissions rather than replacing them.

For a safer evaluation loop, run the task in a disposable worktree, keep credentials out of the environment, and record the model, settings, hooks, tool calls, approvals, diff, and test results. Assert deterministic postconditions after the run. A green model explanation is not evidence that the task is correct. As of 2026-08-07.

QuestionClaude CodeCodexOpenCodeCursorCopilotPi
What influences the agent?Project context, tools, hooks, MCP, skillsInstructions, tools, profiles, MCPInstructions, agent config, tools, pluginsRules, prompts, tools, extensionsInstructions, tools, agents, MCPContext files, trusted project resources, extensions
What gates actions?Allow/ask/deny rules and hooksApproval policy and sandbox modePer-tool and per-agent permissionsApproval, permissions, and sandbox controlsApproval settings, permissions, hooksExternal containment and extension/tool policy
What is the hard boundary?OS sandbox, workspace, or managed policySandbox/worktree/container boundaryThe host or external sandboxHost/CLI sandbox and repository controlsHosted runner or local sandboxNo native sandbox; use a container or VM
What should evaluation assert?Tests, hooks, trace, diffTests, approval trace, output, diffTests, tool policy, outputTests, diff, policy outcomeTests, hook logs, outputTests, container logs, diff
  • Trust is not a single toggle. A trusted repository, a trusted tool, and a trusted action are different decisions.
  • Evaluation is not “the model says it succeeded.” It is a testable postcondition plus evidence from the run.
  • Sandboxing limits impact; it does not prove correctness. Pair it with acceptance tests and output validation.

The ladder runs both directions. Climbing it costs setup and maintenance: a sandbox to configure, hooks to write, approvals that slow the loop down, a regression suite to keep versioned. That cost is the sequel, and it is paid per workflow, not once. Start with the smallest unattended run you actually have - a headless job, a scheduled sweep - and give it one input boundary, one action gate, and one deterministic postcondition. That trio is the preflight at the lowest layer; everything above is the same trio, stronger.