- Published on
Start an internal AI tool with read-only access
- Authors

- Name
- Mehdi Akiki
Article · Through the layers
The proposed assistant can search accounts, update records, send messages, and run a maintenance command. The first product need is simpler: help support staff find the right account.
Start there.
A narrower first release gives the team a smaller set of behaviours to observe. It also avoids making every early retrieval mistake a possible write mistake.
Offer the capability the workflow needs
Define a search tool with a bounded query and a bounded response. Construct the caller's identity and tenant scope on the server. The model supplies search terms, not the authority to search another account.
This Rust type illustrates that separation:
struct SearchArguments {
query: String,
page_size: u16,
}
The trusted request layer separately constructs a context after authenticating and authorizing the user. A parsed model argument cannot construct that context by naming an actor.
The internal AI tool article covers the broader service. This rollout should choose one dataset and one useful question rather than exposing every connector already available to the backend.
OWASP's excessive-agency guidance identifies unnecessary functionality and permissions as separate sources of risk. Keep both the offered tools and their effective authority small.
Read-only still has consequences
A read can reveal private data, cross a tenant boundary, or consume an expensive provider quota. The absence of a write verb does not make it harmless.
Test a support user who can read one account and must not read another. Include a document that asks the assistant to search outside that scope. The tool gateway should reject the forbidden target regardless of how persuasive the document is.
Bound result fields and size. A search result should not automatically include private notes or full documents when a title and identifier satisfy the workflow. Avoid putting retrieved content into unrestricted logs.
Keep the identity through pagination and any follow-up lookup. An authorized first search must not lead to an unscoped get-by-ID tool on the next step.
Define the evidence for a write tool
After the read workflow is useful, name one proposed write action. State who may perform it, what arguments it accepts, which state it can change, and whether approval is needed.
Require tests for invalid arguments, wrong ownership, duplicate attempts, and a changed target between preview and execution. Give external effects an outcome and recovery contract.
Do not add a generic administrative command because several narrow operations would take longer to define. That shortcut makes the permission boundary much harder to review.
Make the rollout observable
Review failed searches, denied calls, incomplete answers, and cases where the assistant selected the wrong record. Track enough safe metadata to reproduce the failure without retaining every customer's document.
The initial release can be modest and still solve a real support problem. A reliable lookup assistant gives a much better foundation for a later write workflow than a broad assistant whose most interesting behaviour nobody can safely explain.
Follow one read through the gateway
The runnable example uses a capture-only Rust gateway. A fixture identity called Alice can access account A. The server constructs her context from that identity and the requested account. Search arguments contain a query and page size, with unknown fields rejected. They contain no actor or credential override.
The support workflow offers only find and read. Searching returns one bounded identifier. Reading 42 returns account A's fixture invoice. Account B has its own invoice 42, so the result demonstrates scope rather than relying on globally unique identifiers. The selected credential reference is A's reference on both allowed calls.
The test then proposes a refund through the same support context. The gateway refuses it before recording any business effect. It also rejects a foreign or unknown account. Adding a credential field inside the generated arguments, or an actor field around them, fails strict parsing. Revoking Alice's access makes an already constructed context fail at the next gateway call.
The HTTP and policy tests use synthetic model proposals. No language model or production connector is called. They prove the selected enforcement behaviour for these proposals, not the quality of a model's search terms or final answer.
This is a useful first release boundary. The model can be wrong about which tool to request without acquiring a write capability. The remaining risks are still real: an allowed read can return the wrong authorized record, include private fields, or consume quota. Measure those outcomes separately and narrow the result to what the support task needs.
Before adding a write workflow, keep this lookup case as a control. The new capability should have its own approved actors, exact arguments, target checks, and effect assertions. A read-only rollout earns useful operational evidence without pretending that retrieval itself needs no review.