What would an AI agent do with my paperwork? Put the permissions in the API
"The bill for the new robot arm is in my inbox. What happens next?" When a technical founder asks this about an agent system, the real question underneath is a different one: what is this thing allowed to do, and who enforces it? The common answer is a paragraph in a system prompt ("never change the books without asking"). A prompt is an instruction, not a boundary. A PDF can carry text that argues with it, and a model can misread it. The boundary belongs in the code and the API, where a model cannot talk its way past it.
Here is a layout that does that, followed by one week of paperwork traced through it.
A coordinator that holds no data tools. The entry point is a coordinator agent whose only job is routing. In Google's Agent Development Kit, a coordinator is declared with a list of sub-agents, and the framework gives the coordinator a way to hand the turn to any of them. Give the coordinator nothing else: no database reads, no ledger tools. It cannot answer a question from data it should not see, because it cannot see any. Its prompt stays short and is about one thing, which makes routing mistakes easier to find and test.
Specialists with narrow tools. Each specialist owns a slice of the domain (the accounting questions, the maintenance history, reading a new document) and gets only the tools that slice needs. The coordinator hands the turn to a specialist. A specialist can pass it sideways to another specialist whose slice the request belongs to, but never back up to the coordinator, and the user's next message starts again at the coordinator. That second rule matters more than it looks: if a specialist could keep the conversation, every later turn would skip the coordinator's routing and refusals. It also rules out the coordinator-specialist ping-pong that burns tokens and blurs which agent owns an answer.
Read-only by credential, not by promise. Every chat turn runs on a short-lived token the server issues with a read scope. The agent service verifies it (signature, issuer, audience, expiry, and a single-use ID so it cannot be replayed), and the application server accepts a read-scoped token only on GET, HEAD and OPTIONS requests. Those are among the methods RFC 9110 defines as safe, meaning the client does not request "any state change on the origin server." So even a specialist that has been talked into trying a POST gets refused by the server. The prompt does not need to win that argument; the HTTP layer already did.
One narrow write path, with a signed identity. Some writes are legitimately the agents' job, because they are evidence rather than decisions: saving what was read from a document, and correcting the details of a fault report the intake pipeline filed. For those, the tool mints a child token with a single narrow write scope, and the server accepts that scope on exactly two routes. The child token also carries the acting specialist's name as a signed claim, which the server records on the action it logs. Because the identity is inside the signature, a header or a request body cannot forge it. Two more rules sit on that path. Under the narrow scope, if the request relays a "this document can be auto-approved" decision, the server downgrades it to human review, so a chat turn can never push a document straight to approved. And everything that is a decision (creating a machine, recording a repair, retiring a unit, reversing or adjusting an entry) is done by a person in the application. Asked to do one of those, the assistant names the screen.
Math in code, not in the model. Depreciation is not something an agent computes. The ledger's own code works it out, straight-line, from the cost and useful life a person saved, and posts it on the 1st, dated the month just ended. Money is held as integer cents and calculated with decimal arithmetic, never floating point. A model can explain a number; it never produces one that lands in the books.
An append-only log, and provenance on every entry. Every change records who or what made it, and the audit tables reject deletes and any rewrite of a logged row at the database level. A posted entry is never edited; it is corrected with a reversal or an adjustment, each with a reason. Each posting records its machine, who or what made it and, for an agent's change, the action behind it; the record itself links back to the documents it was created from. The W3C's PROV primer gives a good vocabulary for designing this: entities (the invoice, the asset record), activities (reading, posting) and agents (the specialist, the person), joined by relations such as "was derived from" and "was attributed to". You do not need to implement the standard to borrow its questions.
Now one week, through those layers.
On Monday an $18,000 invoice arrives for a robot arm delivered and set up on October 2, 2026. The document specialist reads the invoice and a phone photo of the arm's plate into structured fields: serial, model, vendor, price, dates. Saving that reading is one of the two narrow writes, logged under the specialist's name. The document then goes through the intake checks, and a person reviews it and clicks to create the asset, choosing a five-year useful life. From there the ledger takes over: $18,000 over 60 months is $300 a month, computed in code and posted on the 1st. The record links back to the invoice and the photo it was created from.
On Wednesday a $640 bill arrives for a motor on an older unit. A person records it as a repair, an expense on that unit's record. If the bill had said "replaced entire frame", whether it should add to the machine's cost is a call for a person and the accountant, made outside the model.
On Thursday a technician sends a photo of a cracked frame and a note: "scrapping this." Once a reviewer confirms which unit the photo shows, the fault report goes on its record straight away; that is evidence. Retiring it is a decision: a person records the fate (sold, disposed, lost, stolen or donated) and the date.
On Friday the founder asks the assistant what the arm will cost per month on paper. The coordinator routes the question to the accounting specialist, which reads the record with a GET and answers $300 from the ledger's own figure. Asked to retire the cracked unit from chat, it cannot, and says where in the application a person does that.
Three questions test any agent system, or any bookkeeper: where did this number come from, who or what made this change, and can it be undone without rewriting history? This layout answers each one from the data, not from a promise.
What to do on Monday. List every tool your agents can call. Next to each, write the credential it uses and the HTTP methods the server will accept from that credential, as enforced by the server, not as described in the prompt. Any tool whose credential allows a write that is a business decision is your first fix. Then check two things in your logs: can a request body set which agent made a change, and can any code path UPDATE or DELETE an audit row? If either answer is yes, an agent's mistake can be made to look like someone else's, or made to disappear.
General information, not tax advice. Your accountant knows your situation.
Sources:
Agent Development Kit, "Collaborative workflows"
IETF, RFC 9110 "HTTP Semantics", section 9.2.1 Safe Methods, 2022
W3C, "PROV-Primer: An Introduction to the PROV Data Model", Working Group Note, 2013
