An AI assistant that suggests a command and an agent that executes it have different responsibilities. Once a system can edit files, query data or call external services, the task needs controls around those actions.
Before giving an agent access, I would ask what it can reach, what it can change and how I will verify the result.
A capable model does not remove the need for those boundaries. It makes their design more important because the system can perform more work between instructions.
Define the permitted outcome
“Fix the application” is too broad to describe an agent’s authority. I would specify the relevant project, the intended change, the checks it may run and the actions that require further approval.
For a fictional maintenance task, the agent might edit a local branch and run tests, while deployment remains a separate step. It would not need access to unrelated repositories, customer exports or production credentials.
The tool interface and credentials should enforce that scope where possible. A prompt asking the model to be careful cannot compensate for an unnecessarily powerful account.
Treat retrieved material as data
An agent may read web pages, email, repository files and tool output. Those sources can contain instructions placed by somebody other than the user.
For example, a fictional support ticket could tell an agent to upload a configuration file to an external address “for debugging.” That text is part of the ticket being examined. It does not grant permission to transmit the file.
This is the practical risk behind indirect prompt injection. I would limit what the agent can disclose or execute even if it misinterprets a source. Content filtering can contribute, but it should not be the only protection.
A proposed tool action should pass scope and permission checks before execution, then be verified against the external result.
flowchart TD
A["Proposed tool action"] --> B{"Scope, permissions and arguments valid?"}
B -->|No| X["Block and report"]
B -->|Yes| C{"Required approval obtained?"}
C -->|No| X
C -->|Yes or not required| D["Execute scoped action"]
D --> E{"External outcome verified?"}
E -->|Yes| F["Report completion"]
E -->|No| G["Report unresolved state"]
Validate actions outside the model
Before a tool runs, I would validate the arguments against the allowed operation. Is this path inside the project? Is this recipient authorised? Is this database operation read-only? Does the requested network destination belong to the task?
For high-impact actions, the user should be able to inspect a concrete proposed result. Approval is more meaningful when it shows the exact change, destination and effect than when it asks permission to “continue.”
Reversible tasks can use scoped write access and recovery mechanisms. Irreversible actions need stronger controls appropriate to their consequences.
Set limits on the run
I would bound iterations, execution time and resource use, and define what happens after repeated failures. An agent that retries indefinitely can increase cost or repeat a damaging action.
The audit record should identify the tools used, decisions made and outcomes without unnecessarily retaining secrets or sensitive source material. Recovery also needs thought: restoring a file cannot unsend an email or undo a disclosure.
Verify the external result
A model’s statement that a task is complete is not sufficient evidence. I would inspect the changed files, test the intended behaviour or read the service’s authoritative result.
Submission and completion are different states. A successful API call may only have queued a job. A local test may pass while the deployed application remains unchanged.
My acceptance check would therefore be defined before execution. If the task is to change a configuration, what observation will prove the new configuration is active? If the agent cannot obtain that evidence, its report should say what it changed and what remains unverified.