1Mandate
Bots prepare, people decide. The bots watch orders, stock and the calendar; they draft, check, remind and flag. They never move stock, commit money, or promise anything to a customer on their own. Every bot action shows on the dashboard as one plain-English line, and every bot has a kill switch.
2The ten bots
| # | Bot | Watches | Does | Never does |
|---|---|---|---|---|
| 1 | Order Intake Bot | Orders mailbox (dnata / Gate Gourmet PO emails, non-airline emails) | Airline POs: fixed template parser per caterer (system-generated POs). Non-airline: extracts customer, PO, dates and lines with AI; matches product codes; creates a draft order with a confidence score per field | Confirms an order or reserves stock |
| 2 | Availability Bot | New and edited orders | Calculates available-to-promise per line; suggests earliest delivery date for non-airline; pushes airline lines into the Production Planning matrix | Promises a date to the customer |
| 3 | Invoice Prep Bot | Orders without an invoice number | Picks the right Xero (SkyCrest vs Annie Makes Cakes); prepares invoice lines; V2: creates a draft invoice in Xero | Approves, sends or changes an invoice |
| 4 | Confirmation Bot | Invoiced orders not yet confirmed | Drafts the customer confirmation email from a template (lines, dispatch date, method) | Sends without a human, or changes quantities |
| 5 | Production Bot ("Alex's assistant") | Shortfalls on orders, planner "to produce", tartlet NEED TO MAKE | Builds a daily make-list by date and product; sends Alex the missing-items alert for non-airline shorts | Changes planner quantities or production priorities |
| 6 | Allocation Bot | Packing queue, stock IN events | Proposes allocations earliest-dispatch-first; re-checks short lines when stock arrives; flags orders competing for the same stock | Allocates or releases stock without a packer confirming |
| 7 | Dispatch Scheduler Bot | Orders dispatching tomorrow | 14:00 the day before: builds the schedule (Interstate by port โ Roadmaster, Sydney โ driver run, Non-airline โ all customers); drafts Roadmaster booking email and driver run sheet; lists orders not ready | Books transport or marks anything dispatched |
| 8 | Stock Reconciler Bot | Transactions, dispatches, XLSM syncs | Nightly: negative stock, dispatched-but-not-deducted, large manual adjustments, app vs XLSM differences after a sync | Adjusts stock |
| 9 | Hermes Reminder Bot (runs on Hermes Agent) | Dashboard "seen" status, staff roster | 07:00 per-person to-do list; if a person hasn't opened their dashboard by check-in time โ WhatsApp/Telegram โ SMS โ phone call (Twilio) โ manager. Also chases uninvoiced / unconfirmed / unbooked orders. Full spec: DASHBOARD.md ยง4 | Calls anyone not opted in, calls more than once a day, or contacts outside 06:00โ18:00 |
| 10 | Order Pattern Bot | Airline PO history per kitchen | Learns each kitchen's rhythm (SYD every 3โ4 days, MEL/BNE weekly, PER ~3 weeks); flags "expected order not received"; 8-week demand forecast per product for the make-list; menu-change and slow-mover alerts. Basis: AIRLINE_ANALYSIS.md | Creates orders or contacts customers |
3Autonomy levels
| Level | Meaning | Examples | Default for |
|---|---|---|---|
| L1 โ Human only | Bot may surface information; a named person acts | Dispatch (stock out), allocation, invoice approval, customer promises, stock adjustments, cancelling orders | Money, stock, customer commitments โ permanently |
| L2 โ Bot prepares, human approves | Bot creates a proposal; nothing happens until someone clicks Approve | Draft order from email, proposed allocation, confirmation email, Roadmaster booking email, make-list | Most bot output at launch |
| L3 โ Bot acts and reports | Bot acts and logs it; fully reversible; no money/stock effect | Reminders, digests, shortage flags, reconciliation reports, planner refresh | Low-risk communication and checks |
Raising an action from L2 to L3 needs an admin setting change and a written confirmation by the business owner. There is no automatic "autonomy creep".
4Eight rules that make the loop real
- Named human, not "the system" โ every approval records
decided_byand time. - Reversible by default โ bots only create proposals, flags and messages; undo is always one click.
- Escalate, don't guess โ low-confidence extraction or ambiguity goes to the human queue; the bot never retries into a wrong answer.
- Kill switch per bot and per action type โ in Admin โ Agents.
- No silent autonomy creep โ level changes are logged and need two people.
- Stock, money and customer promises stay L1.
- Human override wins โ if a person rejects a bot proposal, the reason is captured and the bot does not re-propose the same thing.
- Loop health is monitored โ proposals waiting too long show on the digest like overdue orders.
5Daily schedule
| When | Job |
|---|---|
| Every 15 min (06:00โ20:00) | Inbox scan โ draft orders; stock-IN watcher โ re-check short lines |
| Every 15 min (06:00โ11:00) | Hermes: dashboard-seen check โ message โ SMS โ call โ manager ladder |
| 06:30 | Shortage sweep + Pattern Bot forecast โ Alex's make-list for today + next 3 days; expected-order watch |
| 07:00 | Daily digest via Hermes โ per-person to-do list (office, packing, Alex, admin) |
| 14:00 | Day-before dispatch schedule draft + booking drafts + "not ready" list |
| 16:00 | Chase: uninvoiced, unconfirmed, unbooked for tomorrow |
| Tuesday 10:00 | Interstate reminder โ MEL/BNE dispatch peaks on Wednesday: check Roadmaster bookings |
| 20:00 | Stock reconciliation report |
| 02:00 | Database backup (copy of stock.db, keep 30 days) |
| Monday 08:00 | Weekly summary: orders, dispatches, shortfalls, bot acceptance rate |
6Decision rights
| Decision | Bot | Human |
|---|---|---|
| Create order | Drafts from email | Office confirms |
| Delivery date (non-airline) | Suggests | Office confirms with customer |
| Invoice | Prepares lines / Xero draft | Office approves in Xero |
| Confirmation email | Drafts | Office sends |
| Allocate stock | Proposes | Packing confirms |
| What to make | Builds make-list | Alex decides |
| Transport booking | Drafts schedule + emails | Office books |
| Dispatch (stock out) | Checks readiness | Packing / office dispatches |
| Stock adjustment | Flags differences | Admin adjusts |
7Technical design
7.1 Runtime
- Hosting cron is confirmed available (4 Oct 2026).
- Bots 1โ8 and 10 are PHP CLI jobs in
includes/agents/, started by the host's cron:php stock_control.php --agent=<name>(blocked from web access). - One cron entry every 5 minutes runs
--agent=dispatcher, which decides which bots are due (fromagent_schedule), so only one cron line is needed. - Each run takes a lock (
agent_runsrow) so two runs never overlap.
7.2 Event stream
- Every order / stock change writes to
events(type,entity,entity_id,payload,created_at). Bots read events since their last cursor. - Examples:
order.created,order.invoiced,order.confirmed,line.short,stock.in,allocation.created,order.dispatched,xlsm.synced.
7.3 New tables (additive)
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL,
entity TEXT NOT NULL, entity_id INTEGER, payload TEXT DEFAULT '{}',
username TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now','localtime'))
);
CREATE TABLE IF NOT EXISTS agent_settings (
agent TEXT PRIMARY KEY, enabled INTEGER DEFAULT 0,
level TEXT DEFAULT 'L2', config TEXT DEFAULT '{}',
updated_by TEXT DEFAULT '', updated_at TEXT DEFAULT ''
);
CREATE TABLE IF NOT EXISTS agent_proposals ( -- the human approval queue
id INTEGER PRIMARY KEY AUTOINCREMENT, agent TEXT NOT NULL,
kind TEXT NOT NULL, -- draft_order | allocation | email | booking | make_list
entity TEXT, entity_id INTEGER, summary TEXT NOT NULL,
payload TEXT NOT NULL, confidence REAL DEFAULT 1.0,
status TEXT DEFAULT 'PENDING', -- PENDING | APPROVED | REJECTED | EXPIRED
decided_by TEXT DEFAULT '', decided_at TEXT DEFAULT '', reason TEXT DEFAULT '',
created_at TEXT DEFAULT (datetime('now','localtime'))
);
CREATE TABLE IF NOT EXISTS agent_runs (
id INTEGER PRIMARY KEY AUTOINCREMENT, agent TEXT NOT NULL,
started_at TEXT, finished_at TEXT, status TEXT, cursor_event_id INTEGER DEFAULT 0,
summary TEXT DEFAULT '', error TEXT DEFAULT ''
);
CREATE TABLE IF NOT EXISTS agent_log ( -- one plain-English line per action
id INTEGER PRIMARY KEY AUTOINCREMENT, agent TEXT NOT NULL,
message TEXT NOT NULL, level TEXT DEFAULT 'info',
entity TEXT, entity_id INTEGER, created_at TEXT DEFAULT (datetime('now','localtime'))
);7.4 AI usage
- Only the Order Intake Bot needs a language model (reading free-form emails / PDFs). Server-side call to the Claude API; key stored in a config file outside
public_html, never in source or the browser. - Prompt returns strict JSON (customer, PO, dates, lines[code, description, qty, unit]); every field carries a confidence. Unknown product codes are matched against
productsby name; anything < 0.85 confidence is highlighted for the human. - All other bots are plain rules over the database โ predictable, cheap, testable.
- Data sent to the model: the order email/attachment text only. No user passwords, no ledger.
7.5 Screens
- Bot inbox (
?page=agents) โ pending proposals with Approve / Edit & approve / Reject (reason). Badge count in the header. - Activity feed on the home page โ latest
agent_loglines. - Admin โ Agents โ per-bot on/off, level, schedule, last run, error, acceptance rate.
7.6 Hermes (bot 9)
- Runs on a small VPS or always-on office PC (the messaging gateway is a persistent process the shared host can't run).
- Talks to the app only through
?api=agent_unseen,?api=agent_reminder,?api=agent_ackwith a bearer token. Details inDASHBOARD.mdยง4.
7.7 Hosting checks still needed
- โ Cron available.
- PHP
imapextension (or a mailbox that can forward to a pipe / webhook) for the Order Intake Bot. - Outbound HTTPS allowed (Claude API, later Xero API).
pdftotextor a PHP PDF text library for PDF POs.