JournalEngineering

Field guide / 6 min read

A least-privilege checklist for AI agent tools

A practical way to give AI agents useful tools without handing every run the keys to production.

Aug 22, 20266 min readBy ISH Team
A least-privilege checklist for AI agent tools
Advertisement

A least-privilege checklist for AI agent tools

Agent tools are easy to demo and easy to over-permission. A model that can read a support ticket, query an internal service, edit a repository, and refund a customer may look like one helpful assistant. In production, those are four different risk profiles.

The useful question is not whether an agent is trustworthy in the abstract. It is what a particular run can do, with which identity, against which resource, and how easily a bad action can be undone. That framing turns a vague safety problem into a design review.

Tool calling needs this review whether you expose functions directly, use remote MCP servers, or connect a coding agent to local services. OpenAI's guidance on agent systems recommends rating tools by factors such as read versus write access, reversibility, permissions, and financial impact. The MCP specification similarly treats tools as arbitrary code execution and calls for explicit user consent before a host invokes one. OpenAI's practical guide to building agents and the MCP security guidance are good starting points.

Start with the smallest useful tool

Avoid a single manage_customer or run_sql tool when the agent only needs one narrow capability. Split it into operations with a clear purpose, such as get_customer_summary, create_draft_reply, or find_orders_for_account. A narrow tool is easier for the model to choose, easier for a reviewer to understand, and easier to constrain at the service boundary.

The tool schema should express the same limits. If a request is scoped to a project, accept a project ID and validate that the caller can access it. Do not accept an arbitrary URL if a resource ID will do. Do not pass a model-generated shell fragment to a general-purpose command runner.

A safe tool definition is not a security boundary by itself. The service behind the tool must enforce authorization, validate inputs, and record the authenticated actor. Model instructions can reduce mistakes, but they should not be the only thing stopping a write to the wrong account.

Give each run a real identity

A common shortcut is to give every agent call one powerful service token. It simplifies the first integration and makes later investigation much harder. If all calls look the same, logs cannot tell you whether a user, a background job, or a malicious prompt caused an action.

Prefer an identity that carries the user and workspace context into the tool layer. Then issue credentials with the smallest scope and lifetime that the task needs. For a remote MCP service, the current authorization specification requires OAuth 2.1 protections and uses protected-resource metadata so clients can discover the right authorization server. It also says clients must use resource indicators when requesting tokens, and servers must validate that a presented token was issued for them. Those details prevent a token for one resource from becoming a general pass to another. See the MCP authorization specification and RFC 8707 on resource indicators.

For local tools, the mechanics differ, but the rule remains: do not silently borrow a developer's broad environment credentials when a scoped credential can be issued. Keep secrets out of prompts, tool arguments, model-visible traces, and error messages.

Separate reading, drafting, and committing

Read-only tools are not harmless. They can expose private data, which may then affect a later tool choice. Still, read, draft, and commit should usually be different stages.

For example, an agent that helps with a release can inspect open pull requests and prepare a changelog without permission to merge. A separate merge tool can require a branch name, a repository allowlist, passing checks, and an approval from the person responsible for the release. The model can propose the action; the service decides whether it is allowed.

This pattern also makes user review useful. A confirmation dialog that says "merge the release branch into main" is clear. A dialog that says "allow agent access" is not. Show the resource, operation, meaningful arguments, and consequence. The MCP specification asks hosts to obtain explicit consent before tool invocation and to help users understand what a tool does.

Put approval where the risk is

Approval is most valuable before an action that is external, irreversible, expensive, or broad in scope. Sending email, deleting data, rotating a credential, publishing a package, and issuing a refund are typical examples. Requiring approval for every search result teaches people to click through prompts. Requiring it for the final write focuses attention on the decision that matters.

A simple policy table can keep the behavior predictable:

Tool classDefault policyExample
Read, low sensitivityAllow with scoped identityLook up a public issue
Read, sensitiveAllow only with a user and workspace scopeRetrieve an account record
Reversible writeCreate a draft or require approvalPrepare a reply or pull request
Irreversible or financial writeRequire approval and server-side checksRefund an order or delete a record

If you use the OpenAI API, function calling lets you control tool choice, including disabling tools, allowing the model to choose, requiring a call, or forcing a named tool. That is useful for reducing the set of actions available in a given step. It does not replace checking the call on your server. OpenAI's function-calling guide documents the tool-choice controls and the JSON-schema contract.

Treat tool output as untrusted input

An agent may retrieve a web page, file, issue comment, or database field that contains instructions aimed at changing its behavior. The content can be useful evidence and still be unsafe to follow. Keep untrusted content clearly separated from developer instructions, and do not let it grant new permissions or alter approval policy.

The MCP specification makes the same point from the tool side: descriptions and annotations should be considered untrusted unless they come from a trusted server. That applies to more than MCP. A tool description is not proof that the tool only reads data, and a response that says "run this command next" is not an authorization decision.

Log the decision, not just the request

When something goes wrong, a raw model transcript rarely answers the operational question. Record the tool name, resource scope, authenticated principal, arguments after validation, policy decision, approval ID when there was one, result, and a correlation ID for the run. Redact secrets and sensitive values before storing logs.

Those records make it possible to answer practical questions: Was the tool called outside its intended workspace? Did a user approve the action? Was a policy rule skipped? They also make tool design easier to improve because failures are attached to real operations instead of a general impression that the agent behaved badly.

A short pre-production review

Before turning on a new agent tool, ask:

  1. What is the narrowest operation the agent needs?
  2. Which user, workspace, and resource does this run act for?
  3. Can the server enforce those limits without trusting the model?
  4. Is the action reversible, and if not, where is approval required?
  5. Could retrieved content change the agent's permissions or instructions?
  6. What will the audit record show after a successful or failed call?

The same checklist works for a small internal helper and a public API integration. Start narrow, keep writes deliberate, and let the backend enforce the rule the interface promises. If you are wiring a coding agent to an API, our ISH API setup guide for Codex CLI shows the connection pattern. The permission model should come before the first production token.

Sources

#AI agents#tool calling#MCP#security#developer workflow
Advertisement

Keep reading

Related stories

Browse the archive