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.

Layer What it does What it cannot promise
Prompt, rules, and skills Tells the model what to do The model will follow it or resist hostile context
Model-selected skill or agent Packages a role, procedure, or tool surface The selected component is benign or current
Approval policy Puts a human or preconfigured policy in the action path A person will read every approval, especially in CI
Hook or runtime gate Blocks, rewrites, or audits supported lifecycle events Unsupported paths or actions outside the runtime are covered
OS sandbox Limits filesystem, process, and network reach The task result is correct or secrets are available safely
Repository or server-side enforcement Protects branches, deploys, credentials, and external systems Local 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:

Metric Why it matters
Task success rate Did the workflow satisfy the acceptance test?
Intervention rate How often did a human need to rescue or redirect it?
Rework / regression rate Did the “successful” change create follow-up work or break tests?
Cost and latency Is the workflow economical enough to run at its intended frequency?
Unsafe-action rate Did it attempt a forbidden or out-of-scope action?
Context/retrieval failures Did 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-10.

Question Claude Code Codex OpenCode Cursor Copilot Pi
What influences the agent? Project context, tools, hooks, MCP, skills Instructions, tools, profiles, MCP Instructions, agent config, tools, plugins Rules, prompts, tools, extensions Instructions, tools, agents, MCP Context files, trusted project resources, extensions
What gates actions? Allow/ask/deny rules and hooks Approval policy and sandbox mode Per-tool and per-agent permissions Approval, permissions, and sandbox controls Approval settings, permissions, hooks External containment and extension/tool policy
What is the hard boundary? OS sandbox, workspace, or managed policy Sandbox/worktree/container boundary The host or external sandbox Host/CLI sandbox and repository controls Local sandbox (/sandbox enable), cloud sandbox, or the cloud agent’s Actions runner No native sandbox; use a container or VM
What should evaluation assert? Tests, hooks, trace, diff Tests, approval trace, output, diff Tests, tool policy, output Tests, diff, policy outcome Tests, hook logs, output Tests, 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.