AI Platforms

Agents need boring boundaries

6 min read

The first agent demos are usually too smooth.

The agent reads the request, calls a tool, edits a file, opens a browser, finishes the task, and writes a tidy summary. Everyone nods because the path looks obvious in hindsight. Of course the agent needed the file. Of course it needed the browser. Of course it needed the token. The demo worked.

Production does not care that the demo worked.

The real system has a messier question: what was the agent allowed to touch, and how would we know if it crossed the line?

That is why agents need boring boundaries. Not clever boundaries. Not a policy paragraph hidden in a prompt. Boring ones. Boundaries that can be named in the UI, enforced in code, logged at the application edge, and explained to a human who is trying to decide whether to trust the next action.

scope should be concrete

“Let the agent use my files” is not a scope. It is a warning label.

A useful scope is specific enough that the user and the system can both reason about it:

{
  "files": ["src/content/blog"],
  "network": "localhost-only",
  "shell": ["pnpm markdown:check"],
  "secrets": "none",
  "duration": "this run"
}

That is the kind of grant I want. The agent can do useful work, but the permission is not pretending to be universal. It has a directory, a network rule, a command list, a credential rule, and a lifetime.

The exact shape will vary by product. A coding agent needs workspace boundaries. A browser agent needs origin and account boundaries. A document agent needs file and sharing boundaries. An MCP tool runner needs tool-level grants because every tool is a different kind of side effect.

The important part is that the boundary exists outside the model’s goodwill.

credentials are different

File access is one thing. Credentials are another.

An agent with a token can become a confused deputy very quickly. The user asks for one thing. The agent has authority to do another thing. A tool accepts the request because the credential is valid, not because the action matches the user’s intent.

That is where I want narrow grants and visible delegation. If an agent needs to read a GitHub issue, give it read access to that issue or repository for the run. If it needs to open a pull request, show the diff and ask. If it needs to post a comment, show the exact comment and target before it sends anything.

This is not only about security. It is about debugging.

When something goes wrong, “the agent had my token” is not enough information. I want to know which credential was used, which tool accepted it, which resource was targeted, and which user-facing approval preceded the action.

tool boundaries should match side effects

MCP makes tool access feel nicely composable. That is useful, but it also makes tool boundaries more important because the tool list can grow faster than the user understands.

Not every tool belongs in the same trust bucket.

A search tool is not the same as a write tool. A local file reader is not the same as a shell command. A formatter is not the same as a deploy command. A database read is not the same as a database migration. Putting all of those behind one generic “tools enabled” switch is asking for trouble.

I would rather make the categories boring:

  • read-only context tools
  • local edit tools
  • external write tools
  • shell tools
  • credentialed tools
  • irreversible tools

Then the approval model can be boring too. Read-only tools may run automatically inside scope. Local edits produce a diff. External writes need explicit approval. Irreversible tools require a stronger confirmation or should not be available to the agent at all.

The model does not get to decide that a deploy is “probably fine” because the prompt sounded confident.

time matters

Permissions should expire.

This is one of the easiest rules to skip in prototypes. The agent gets a grant, the grant lives somewhere, and suddenly a future run inherits authority from a past run. That is convenient right up until it is confusing.

I like run-scoped permissions as the default. The user approves a task. The agent gets the minimum access needed for that task. The grant ends when the run ends. If the agent needs access again later, it asks again with current context.

There are cases where longer-lived grants make sense, but they should be named as such. “Always allow this agent to read this folder” is a different product decision than “allow this run to edit this file.” The UI should not blur those together.

approval needs a receipt

An approval without context is mostly a liability.

If the agent asks, “Can I continue?”, the user is approving a mood. If the agent asks, “Can I replace these three paragraphs in foo.mdx and then run pnpm markdown:check?”, the user is approving work.

That approval should leave a receipt:

approved action: edit local file
target: src/content/blog/agents-need-boring-boundaries.mdx
visible evidence: proposed diff
allowed follow-up: markdown check only
expires: end of run

This is the difference between permission as a ceremony and permission as an operating surface. The receipt lets a human replay what happened. It also lets the system reject later actions that were never approved.

boring is the point

I keep using the word boring because the safe version of agent boundaries should not require a philosophical debate every time the model wants to act.

The boundary should be inspectable. The grant should be narrow. The approval should show the side effect. The credential should be scoped. The run should leave evidence. The permission should expire.

None of that makes a good demo. It does make a system easier to trust.

Agents are going to keep getting better at using tools. That makes the boundary problem more important, not less. The more capable the agent is, the less I want the safety model to depend on everyone remembering what the prompt was supposed to mean.

Give the agent useful tools. Give it real context. Let it do work.

Then put boring walls around the work so the rest of us can see where it is allowed to go.

Jeremy London

About Jeremy London

Engineering leader and builder in Denver. I write about AI platforms, agents, security, reliability, homelab infrastructure, and the parts of engineering work that have to survive production.