Agents draft, humans approve: what an AI audit trail should actually contain
3 min read
By BudAlly
Published Updated
Every AI operations product for dispensaries now says "a human approves." Good. The next question is what the human saw, what the system knew, and whether you can produce both for an inspector a year later.
The trail is a compliance record, not a log
A price change, a campaign send, a bill submission, a Metrc adjustment — each is a regulated or financially material action. If software drafted it and a person clicked, the record of that click has to stand up the way a signed form does. Application logs don't; they're for engineers. A trail that is exportable, complete and human-readable does.
The eight fields
| Field | What it holds | Why it matters |
|---|---|---|
| 1. Proposal identity | ID, type (price change, bill, campaign…), tenant, store, created-at | Everything else hangs off it |
| 2. Sources with taint and as-of | Each input: system (Metrc, POS:Dutchie, LICENSED:Headset, OWN_CHECK, upload), timestamp | "Where did this number come from, and how old was it" |
| 3. Rules applied, by ID and version | e.g. RI-NY-06 v9 → BLOCKED; SF-ALL-04 v3 → pass | The regulatory check is reproducible; an inspector can read the citation |
| 4. Evidence and confidence | The matched manifest line, the cohort sizes, the OTD math; a confidence score with its method | The approver saw what the system saw |
| 5. Precondition hash | Fingerprint of inputs at draft time | Stale drafts become Superseded, not executed |
| 6. Reviewer and approver | Names, roles, timestamps; maker ≠ checker where required | Who decided |
| 7. Execution credential and result | Executed under whose POS/Metrc key; the external record ID returned | The action is attributable to a person, not to a vendor service account |
| 8. Verification | The post-execution read-back: did the price actually change in the POS? | Closes the loop |
The two states that matter
Superseded. A proposal whose preconditions changed before approval cannot be approved; it offers a re-run. Without this state, a price drafted on Friday against Friday's cost executes Monday against Monday's cost, and the trail says a human approved it.
UNKNOWN. A rule the pack can't decide routes to a named person and blocks the draft. Without this state, the system either guesses or silently skips the check — and the trail says the check passed.
What a learned rule needs
"Tell it once that a vendor bills in cases and it remembers" is a real feature. The trail needs: the rule's kind, scope, expression, version, who proposed it (agent or person), who approved it, effective-from, and what it supersedes. If the memory lives inside a model's context, none of that exists and nobody can audit, version or revoke it.
Five questions for any vendor
- Can I export the complete audit trail — all eight fields — as CSV or JSON, without asking support?
- Which rule, by ID and citation, allowed or blocked this draft, and what version was it?
- Where does a learned rule live, and can I see its version history?
- Under whose credential did this action execute in my POS or Metrc?
- Is there an "approve all" button anywhere in the product?
If the answers are "ask us", "the model knows", "our service account", or "yes", the trail won't hold.
BudAlly's proposal lifecycle, the Superseded state and the export are described on the security page; the morning briefing's footer reads "Drafted N · executed 0" because that's the only number that should ever appear there.