An AI assistant that can write to a database fails in a few specific ways. It writes before anyone has agreed. It reports a change as done when the write never ran. Or it gets three steps into a five-step change and stops, leaving records that contradict each other.
InventDB handles those failures in the server rather than in the model's instructions. An AI changes data by one of two routes. The assistant built into InventDB SOAR proposes a multi-step change as a change set, which a person applies with one click and the server applies as one transaction. An external agent connected over MCP stages record changes as proposals that only a commit applies, and the audit log records every commit. This article covers both routes, and is exact about what the audit log records and what it does not.
A change set: every step on one card
Take a lease turnover. The outgoing lease ends, the old tenant is marked as moved out, a new tenant record is created, a new lease points at it, and the signed lease PDF is filed on the new lease. When a person asks the InventDB SOAR assistant for that, the assistant writes nothing. It produces a change set, an ordered list of steps that the interface shows as one confirmation card. Each step names an operation (insert, update, delete or attach), a namespace and type, the target record and the fields:
POST /ai/change-set/apply
{
"title": "Lease turnover for P-5001",
"steps": [
{ "op": "update", "namespace": "pms", "typeName": "leases",
"recordId": "L-7039", "matchField": "Lease_ID",
"fields": { "status": "ended" } },
{ "op": "insert", "namespace": "pms", "typeName": "tenants",
"fields": { "name": "Dana Cole", "email": "dana@example.com" } }
]
}
A target can be the record's storage _id or a business key; when it is not an _id, the server looks it up in the column that matchField names. An update carries only the fields that change. The interface sends this request when the person presses Apply, and not before.
What Apply does, in order
- Authorize every step first. Before anything opens, the server checks the person's grant for each step: write for inserts, updates and attachments, delete for deletes. System namespaces are reserved for administrators. One refusal rejects the whole set with a 403, and nothing is written.
- Open one transaction. The data steps run in order inside it. An insert that supplies an
_idalready in use is refused. An update reads the current record, merges the supplied fields over it and stamps the update time. The engine checks the person's row rules on every step: an insert against the new record, an update against both the stored record and the result, a delete against the stored record. - Stop at the first failure. If any data step fails, the transaction rolls back and the response is a 400 that names the failing step. No step is applied.
- Commit. Concurrency control is optimistic. The transaction noted the version of every record it read, and if another writer changed one of them before the commit, the commit fails with a 409 and nothing is applied.
- Attach files. Attachment steps run after the commit, because files are stored outside the record transaction. The bytes come from a file the person uploaded in the conversation or, in InventDB SOAR with Gmail connected, from an attachment on an email. A failed attachment does not undo the committed records; the response reports it per step so the card can offer a retry.
The response lists a result for every step, with the record id each one produced, and the transaction id. The card shows those results, so what the person sees is what the server did rather than what the model said it did.
Agents over MCP: propose, then commit
An agent such as Claude Desktop or Cursor connects to the instance's MCP server and signs in as a person. Its record-change tools work in two steps. propose_insert, propose_update and propose_delete write nothing: each returns a proposal id and a preview, with the record before and after for an update, along with the results of any validation rules on the type. A rule with severity error blocks the proposal outright.
A proposal is held in memory for five minutes and belongs to the person who made it. commit checks the person's grant and the validation rules again, since either may have changed, applies the change and writes an audit entry. cancel drops the proposal. Each proposal covers one record; there is no MCP tool that applies changes to several records in one transaction.
The server guarantees that a proposal changes nothing and that a commit is checked again. Whether a person reads the preview before the agent calls commit depends on the client and its setting for confirming tool calls. Our article on the MCP server describes the tools and the sign-in in detail.
What the audit log records
The audit log is a system type inside the instance. Each entry holds an id, a timestamp, the person, the origin (mcp), the operation, the namespace, type and record id, the record before and after, the proposal it came from and, for an undo, the entry it reversed. The log covers changes made through the MCP tools, and only those:
| Change | In the audit log |
|---|---|
| MCP commit of an insert, update or delete proposal | Yes, with the record before and after; a delete keeps the full removed record |
MCP undo | Yes, as a new entry linked to the one it reverses |
| Rows inserted by the MCP bulk insert tools | Yes, one entry per row |
| Validation rules saved, enabled, disabled or deleted over MCP | Yes |
| Report templates created or updated over MCP | Yes |
| Change sets applied from the InventDB SOAR card | No |
| Writes through the REST record, bulk and transaction routes | No |
| Reads through any interface, and sign-ins | No |
An agent reads the log back with the audit_log tool, filtered by namespace, type, operation or record id: 50 entries by default and up to 500. A person who is not an administrator sees only their own entries. undo takes an entry id and reverses that change: an insert is deleted, an update restores the earlier record, and a delete restores the removed one. Only the person who made the change, or an administrator, can undo it, and the grant is checked again first.
Writes outside the audit log still carry their author on the record. The engine sets _createdBy on every new record from the verified caller, and a client cannot set it, so records inserted by a change set name the person who pressed Apply.
Two properties to know. Audit entries are ordinary records, encrypted at rest like the rest of the data, rather than a write-once ledger. And each entry is written after its change on a best-effort basis: if writing the entry fails, the change it describes still stands.
Where the guarantees stop
- Not every assistant write is a change set. In InventDB SOAR, editing or deleting a single record opens a form that the person confirms, and the same edit across many rows opens a review card that applies each record separately, so it is not one transaction. A single new record that a person asks for can be written directly, after the server checks their write grant on the type.
- Attachments sit outside the transaction. They run after the commit and can fail after the records are stored.
- The audit log covers MCP tool changes. Change sets and REST writes are not in it, as the table shows.
- A commit is a tool call. The server cannot tell whether a person read the preview before it.
- One MCP tool writes without a proposal.
bulk_inserttakes at most 20 records and writes them at once, checking each against the validation rules and recording every row in the audit log. - Proposals live in memory. They expire after five minutes, and a restart of the instance drops them.
Using it
In InventDB SOAR, ask the assistant for a change that spans several records, check the card and press Apply; the card then shows a result for each step. The apply endpoint itself calls no model, so it is also available on InventDB Serverless to an application or external agent that builds its own change sets.
Over MCP, an agent can review its own history and reverse a mistake:
{ "name": "audit_log", "arguments": { "namespace": "pms", "type": "leases", "limit": 5 } }
{ "name": "undo", "arguments": { "audit_entry_id": "audit_7e2c..." } }
The MCP setup guide shows how to connect a client. To give an agent less than you have, sign it in as a user with a narrower role; its proposals, commits and audit entries then belong to that user.