The agent doesn't get to choose which school it writes to
A school office runs on small, boring writes. A student transfers in on the 12th. Attendance gets corrected for a day someone was home sick. A grade moves after a re-test. A withdrawal is recorded, and a leaving certificate has to reflect it.
Put an agent on that work and every one of those writes lands in a child's permanent record, with no one reading over its shoulder.
Drafting a lesson plan is reversible. Writing to a student information system is not. A model can compute a grade well enough; the harder problem is what stands between a plausible-looking model output and a row in a live database that a registrar will rely on three years from now.
Four layers do that work. None of them live in the prompt.
1. Scope every call to one school, in code
The obvious failure is the agent reading or writing the wrong school's data. Multi-tenant systems usually defend this with a filter the application remembers to add. That works until something forgets.
The stronger shape is to make the boundary non-optional: the tenant is injected into every query server-side, after the agent has said what it wants. The agent submits a filter. The server merges the school's identity into that filter and overwrites anything the agent supplied for those fields. There is no phrasing of a query that reaches another school's students, because the agent never gets to be the last writer of the scope.
Two details matter more than they sound:
- The agent names its target explicitly on every single call. No server-side "currently selected school" that a long conversation can drift away from. Nothing to forget between turns.
- Unknown school identifiers are refused, not guessed. A slug that isn't in the registry comes back as an error with a did-you-mean, rather than silently matching nothing. A query that quietly returns zero rows will convince a model the record doesn't exist. A model that believes a student has no attendance history will happily write one.
2. Keep grade computation in versioned code
There's a strong temptation to let the model do the arithmetic: hand it the marks, describe the grading scale, take the letter grade it returns.
Don't. Grade logic is policy. It differs per board, per school, sometimes per subject, and it changes between sessions. It has to be inspectable by a human who is not in the room when it runs, and identical on Tuesday and Thursday.
The shape that holds is a pipeline of small reducers — each one a stored, versioned artifact that takes marks in and passes computed values along. The agent's job is to assemble and edit that pipeline. The pipeline's job is to run the same way every time, whether or not a model is involved. When a parent disputes a grade, you can point at the reducer that produced it and read it. You cannot read a sampling temperature.
This also gives you inheritance for free: a base rule set at the board level, overridden per school where it genuinely differs, rather than forty prompts drifting apart.
3. Gate the writes that have no undo
Most operations in a school system are correctable. A few are not, or are expensive enough that correcting them is a phone call to a parent.
Sort the verbs before you connect anything:
- Reversible — reading a register, computing a projection, drafting a remark. Let the agent run these.
- Correctable — editing attendance, revising a mark. Log heavily, allow.
- Irreversible or externally visible — issuing a transfer certificate, recording a withdrawal, publishing report cards to parents, anything that sends a message home. These need a human approval step that lives outside the model, in front of the action.
The gate has to be structural, not advisory. A rule in a prompt is a suggestion a model can talk itself out of; a policy that refuses the call is not. We wrote about this shape in more detail in why guardrails shouldn't live in the prompt.
Idempotency belongs here too. A dropped network reply that causes a retry should not issue two transfer certificates — the write needs a key that makes the second attempt a no-op.
4. Leave a receipt someone else can read
Application logging depends on a developer having remembered to add the log line. Student records need a receipt the run cannot avoid producing, generated where the action happens rather than where the agent narrates it.
Itemized, per run: which tools were called, against which school, what they changed, which model, how many tokens, what it cost. When a school asks why a grade changed in March, the answer is a query, not an archaeology project.
That trail is also what makes the arrangement reviewable by someone who has authority over the data and no interest in the architecture.
What this rules out
Being honest about the tradeoffs:
- Fully autonomous report-card publication is not on the table, and shouldn't be. The last step stays human.
- Free-text queries against the whole student body are a bad idea even when scoped correctly. Expose specific verbs (attendance for a class and month, results for a session) instead of a general-purpose reader.
- The model is the worst place to put the rules. Every layer above works because it runs whether or not the model cooperates.
None of this is exotic. It's the discipline any regulated system gets, applied to a workload where the subjects are children and the records are kept for years.
OBTO has run production workloads since 2019, across 150+ institutions. In the education deployments, all four layers are prerequisites rather than options.
Frequently asked
Can an AI agent safely access student records?
Yes, with the tenancy boundary enforced server-side rather than by the agent, specific scoped read verbs instead of general database access, and a human approval step on any write that can't be undone. The unsafe version is a general-purpose agent with a database credential.
Should an AI model calculate student grades?
No. Grade computation belongs in versioned, inspectable code that produces the same result every run. An agent is well suited to building and editing that logic; it should not be the thing performing the arithmetic at report-card time.
How do you stop an AI agent from reading the wrong school's data?
Inject the school identity into every query on the server, after the agent submits its filter, so the agent's values for those fields are overwritten. Combine that with rejecting unknown identifiers outright rather than returning an empty result.
What should require human approval in a school system?
Anything irreversible or externally visible: transfer certificates, withdrawals, published report cards, and any message that reaches a parent. Reversible reads and correctable edits can run unattended if they're logged.
What does an audit trail for student data need to include?
Which school was addressed, which tools ran, what changed, and the model and token cost of the run — produced automatically by the runtime rather than by application code that has to remember.