Agent Scopes - Keeping AI Solutions Right-Sized
2026-03-09

You send an AI agent off to add a feature. You come back to find it's rewritten half the codebase and overcomplicated the solution beyond recognition. How often has this happened to you?
The problem is scope creep without guardrails. Agents optimise for completion, not constraint. They add features, rewrite patterns, refactor code "for consistency" — all in service of the task, but none of it authorised. We need a way to define boundaries that agents understand and respect.
Borrowing from OAuth
OAuth scopes define boundaries — what an access token can do, which resources it can touch, what operations it can perform. The principle of least privilege keeps tokens constrained to what they need and nothing more.
What if we applied the same concept to AI agents?
In OAuth, authorisation is absolute. With AI agents, instructions aren't guarantees — there's no compiler preventing an agent from rewriting your database layer. But what if we established scopes anyway? Define expected changes. Set boundaries. Give the agent a framework for working within constraints and a mechanism for flagging when it hits a wall. Scopes might not enforce compliance, but they could signal intent. Once complete, they'd provide a baseline for evaluating whether the agent stayed roughly within bounds or wandered off on its own tangent.
Designed scope versus agent scope
Consider a to-do app API with PATCH /v1/tasks/{taskId} for updating task fields — title, dueDate, notes. You need to add the ability to mark tasks as complete. This is a genuine 50-50 decision:
- Option A: Use existing endpoint with
{ "completed": true }(completion is just state) - Option B: Add
POST /v1/tasks/{taskId}/complete(completion is an explicit action with side effects like settingcompletedAt)
Both are valid. The choice depends on your requirements.
Without scopes
Prompt: "Add the ability to mark tasks as complete"
Agent decides to add a new endpoint because "it's more RESTful". Creates POST /v1/tasks/{taskId}/complete. Adds route definitions, OpenAPI docs, controller logic. Updates client SDK to include the new endpoint. Implements similar endpoints for archive, snooze, and pin "for consistency".
You return to find four new action endpoints when a simple field update would have worked.
With scopes
Prompt: "Add the ability to mark tasks as complete. Granted: +edit:endpoint. Denied: -add:endpoint, -add:api-client"
Agent can modify existing endpoint logic but cannot create new endpoints or API client methods. Adds completed field handling to existing PATCH /v1/tasks/{taskId}.
You return to find exactly what you expected: one field added to the existing endpoint.
The scope constraint guided the agent towards the simpler solution and prevented architectural decisions you didn't authorise.
Surfacing hidden complexity
Now consider a scenario where complexity isn't a design choice but genuinely hidden: adding dark mode to an existing web application. Seems straightforward — just swap some colour variables, right?
Prompt: "Add dark mode to the application. Granted: edit:component, add:store. Denied: add:asset, edit:asset"
Agent implements CSS variable system for colours. Creates state store for theme management with localStorage and system preference detection. Updates component styles successfully.
Then hits a constraint:
I've implemented core dark mode theming with a toggle and persistent state. However, I found issues I cannot fix with current scopes:
- Logo and icons need dark variants (requires
add:assetoredit:asset)- Several images have white backgrounds that clash with dark mode (requires
add:assetfor alternatives)- Chart library colours are hardcoded and need configuration (might need
add:componentfor wrapper)Should I request additional scopes, or would you prefer to handle these separately?
You can now decide whether to expand the scope, phase the rollout, or keep dark mode as a CSS-only feature initially.
In this scenario, scopes would have surfaced the hidden complexity early — that you can't actually add dark mode without touching assets and hardcoded values. Whether that's a feature or a bug depends on your context. But at least you'd know what you're signing up for before the work sprawls.
A scope taxonomy
Examples of what scopes might look like across different layers:
API Layer
add:endpoint- Create new API endpointsedit:endpoint- Modify existing endpoint logicremove:endpoint- Delete API endpoints
Service Layer
add:service- Create new service classes or business logicedit:service- Modify service methods and logicremove:service- Remove unused services
Database Layer
add:migration- Create new database migrationsedit:migration- Modify pending migrationsremove:migration- Remove pending migrations
Routing
add:route- Add new application routesedit:route- Modify route paths, guards, or metadataremove:route- Remove routes from the application
Components
add:component- Create new UI componentsedit:component- Modify component logic and stylingremove:component- Delete unused components
State Management
add:store- Create new state stores or slicesedit:store- Modify state logic, actions, or selectorsremove:store- Remove unused state management code
Assets
add:asset- Add new static assetsedit:asset- Replace or optimise existing assetsremove:asset- Remove unused assets
These are generic examples. In practice, we might augment these with custom scopes tailored to a project's architecture — edit:payment-service, add:notification-template, edit:analytics-event — whatever reflects your core components and boundaries.
How this differs from OAuth
With OAuth scopes, absence implies denial. Authorisation checks look for the presence of a scope.
With agent scopes, you have two options: explicitly grant or deny each permission upfront, or establish a contract where unmentioned scopes are implicitly denied. The latter initially sounds cleaner — define which scopes are granted, everything else is off limits. You need a clear definition of what each scope means, along with the complete scope taxonomy for the project — This could be included as part of an agent skill or project-level configuration. But agents will likely handle explicit denial better in practice — a clear "you cannot do X" in the prompt will like result in a better adherence to the concept.
Syntactic sugar with purpose
Agent scopes are really just syntactic sugar for checkboxes that ultimately end up in the prompt. Nothing technically prevents an agent from ignoring them. But they serve a purpose beyond enforcement: they act as a reminder to provide scoping in your initial prompt. A structured way to think about boundaries before you hit "run".
Beyond the prompt
Scopes could serve purposes beyond just constraining the agent itself. Merge requests could be checked against the declared scopes — did the agent stay within bounds? Scope violations could flag commits for prioritised human review. As the volume of AI-assisted code changes accelerates, we'll need triage mechanisms. Scope adherence is a natural filter: changes within declared bounds might bypass review queues, while scope violations trigger immediate attention.
Cost control
Scopes could impact the economics of AI-assisted development. Limiting scopes might reduce token usage by preventing agents from wandering into unnecessary context. Smaller scope could mean smaller search space, which could lead to more efficient execution. An agent constrained to edit:component might not need to load and reason about database schemas, API contracts, or migration files.
Increased autonomy
When you trust that an agent will stay within defined boundaries, you could grant it more autonomy. You might be more likely to let an agent run unsupervised overnight if you know it's constrained to edit:tests and edit:component rather than having free rein across the entire codebase. The paradox could be that more constraints enable more freedom.
Forcing incremental change
Scopes could force agents to be efficient with their changes rather than continuously reinventing large parts of the codebase. Without constraints, agents often lean towards ground-up rewrites — it's easier to build from scratch than to understand and modify existing patterns. By enforcing surgical, scoped changes, you might push the agent to work incrementally, to understand what's already there, and to make minimal modifications.
Better brownfield development
This constraint-driven approach might actually make AI more effective in brownfield projects. Without constraints, agents often default to rewriting large sections of well-proven codebases By limiting scope to specific capabilities like edit:component or add:endpoint, you force the agent to work within the established architecture rather than replacing it. The agent must learn to make surgical changes that fit the existing system instead of reimagining entire subsystems from scratch.
The result could be code that evolves deliberately rather than exploding unpredictably.
This is just an idea — one I'm still experimenting with and refining. But I think we're going to need something like it as we grant agents more autonomy. Scopes might not be perfect. But they might be better than the alternative: sending agents out with no guardrails and hoping they do what you had initially pictured.
