AI Engineering

Design agent tools with narrow permissions and clear contracts

Kamruz
Kamruz
Oct 14, 2026
5 min read
Design agent tools with narrow permissions and clear contracts

An agent receives a tool named runDatabaseQuery that accepts arbitrary SQL. The product only needs to look up a customer's open tickets, but the tool can read unrelated tables and modify records. Prompt instructions ask the agent to be careful, yet the interface grants far more authority than the journey requires.

Tool design should expose specific capabilities rather than a general escape hatch. This article uses an illustrative customer-support assistant that can read tickets and prepare a status update. The application remains responsible for identity, permissions, validation, and execution regardless of what the model proposes.

Start from the authorized user journey

List the actions the product needs. A support agent may need to retrieve one ticket, list a bounded set of recent tickets, and draft a reply. Sending the reply, closing the ticket, or issuing a refund may require separate capabilities and approval rules.

For each action, identify the actor, resource, and consequence. “Read tickets” is incomplete without an account scope. “Update status” is incomplete without allowed transitions. These relationships become the tool's server-side contract.

Do not expose a generic shell, database query, or HTTP client simply because it is convenient. General tools can be appropriate in deliberately privileged engineering environments, but a customer product should justify their breadth. Most product journeys can use narrower operations with clearer validation.

Define arguments the model can understand

Use descriptive names and explicit schemas. A ticket lookup might accept a ticket identifier and return the permitted public fields. It should not accept an arbitrary tenant identifier as authority when the server already knows the authenticated scope.

Keep optional arguments meaningful. A tool with many loosely related flags becomes difficult for both model and engineer to reason about. Split operations when they have different permissions or side effects rather than hiding them behind a mode string.

Describe errors and prerequisites. The model should know whether a missing ticket, denied access, or invalid status transition requires clarification, a fallback, or stopping. A clear contract reduces repeated calls and prevents an ordinary denial from being treated as a transient provider problem.

Enforce identity and scope on the server

Attach trusted identity outside model-generated arguments. Resolve account membership and permissions from the authenticated application context. Recheck ownership for the target resource before executing the action.

Treat tool arguments like any other untrusted request input. Validate types, bounds, enumerations, and cross-field relationships. A model-generated identifier can be malformed or refer to another account. The fact that an agent produced it does not make it safe.

Limit result fields as well as input scope. Storage records may contain internal notes, credentials, or provider metadata. Return an explicit projection appropriate to the user journey. A narrowly named tool can still leak data if it serializes the entire database record.

Make side effects explicit and retry-safe

Separate read tools from write tools in naming and documentation. A lookup should not unexpectedly create a record. An update should describe its consequence and return the actual outcome.

For retryable writes, define operation identity and idempotency where needed. If a connection fails after sending a reply, the agent may retry because it did not receive confirmation. The server must avoid sending a duplicate when the product requires one logical operation.

Use explicit state transitions. Closing an already closed ticket might be harmless, while reopening it or changing ownership may not be. The tool should reject invalid transitions according to application policy instead of leaving the model to invent workflow rules.

Bound outputs and resource use

Cap list sizes, document lengths, and execution time. A tool that returns every ticket can overwhelm context and expose unnecessary information. Pagination or focused search can provide a manageable subset.

Return structured outcomes with stable identifiers. The model should not need to infer success from a prose sentence. Include enough information to continue the authorized journey, while leaving internal diagnostics in safe logs.

Think about rate and concurrency limits. Even read-only tools can create expensive queries or external charges. Bound repeated calls and monitor rejected or excessive requests. The permission model includes resource consumption as well as data access.

Use AI assistance to test the interface

Give a coding assistant the tool schema and product journey. Ask it to propose malformed inputs, unauthorized targets, ambiguous calls, and retry scenarios. Require it to identify which rule should reject each case.

An illustrative request is: “Evaluate this ticket tool as an untrusted API. Find arguments that could cross account scope, produce duplicate replies, or request unbounded results. Propose narrower contracts without changing the product journey.” This turns tool review into a concrete interface exercise.

Run deterministic server tests for these cases. Also evaluate whether the model selects the correct tool and supplies usable arguments for ordinary tasks. Security enforcement and model usability are separate checks; a secure but incomprehensible interface can still cause product failures.

Review capabilities as the agent evolves

Adding a tool changes what a model mistake can do. Review new capabilities against the user journey, permissions, approval requirements, and audit trail. Do not assume an existing system prompt makes a new write action safe.

Record the executed tool, trusted actor, resource, and outcome using safe metadata. For consequential actions, preserve the approved proposal and bind execution to it. The guide on human approval explains why approval must refer to an exact action.

A good tool interface makes allowed work easy and disallowed work impossible at the server boundary. It also makes failures understandable and verification affordable. The model can decide how to use the available capabilities within the product flow, while application code determines what those capabilities are permitted to accomplish.

Keep tool descriptions aligned with implemented behavior. If documentation says a reply is only drafted but the server sends it immediately, the model and user will both reason from a false contract. Review descriptions, schemas, handler code, and tests together. Version a tool when its meaning changes materially, and avoid reusing a familiar name for a more powerful action. This makes capability growth visible and reduces the chance that a previously harmless workflow acquires unexpected consequences.

Separate tool errors from model instructions in returned data. A provider error string or ticket body can contain arbitrary text; returning it directly as guidance can recreate the authority problem at another boundary. Use structured error categories and bounded human-readable details, while retaining safe diagnostics outside the model context. The agent can then decide whether to clarify, retry, or stop based on the documented contract. It should not receive an unfiltered remote response that appears to redefine what the next tool call is allowed to do.

Sources

Anthropic: Writing effective tools for agents discusses schemas, responses, and tool evaluation.

Anthropic: Building effective agents discusses clear tool interfaces and bounded workflows.

About the Author

Kamruz

Kamruz

Full Stack Developer

A passionate developer who loves creating modern web applications and sharing knowledge with the community.

More About Me

Related Articles