How they work

Three ways your
team shows up.

Every interaction with your AI workforce falls into one of three patterns. Pick a tab to see each one.

Your team starts work before you do.

Each morning, your three proactive agents β€” Maya, Kai, and Ava β€” are already on it. Without a prompt, a click, or a calendar invite.

7:55 am
A quiet background helper checks the clock and decides whose turn it is.
8:00 am

Maya begins her inventory scan πŸ“‹ Maya

She walks through every product in your store, compares stock to your reorder thresholds, and makes a note of anything running low or about to oversell. If you've turned on "Let Maya decide", she first checks with Kai how fast each product is selling and flags it by days of cover against your supplier's lead time instead.

8:00 am

Ava starts her morning brief πŸ‘” Ava

She pulls yesterday's activity from each specialist on your team, picks out what matters, and writes you a three-line summary β€” plus one suggested action.

8:02 am

Your brief lands on your phone

One Telegram message. Coffee in hand. You know what happened overnight before you open a single tab.

Telegram Β· 8:02 am
πŸ‘” Ava β€” Good morning, Tom
Here's what happened yesterday:
πŸ“¦ Jim shipped 5 orders, updated tracking on 3.
πŸ“‹ Maya flagged 1 low-stock item β€” Wax Melt β€” Jasmine, 2 units left.
πŸ‘©β€πŸ’» Sarah: 6 support emails β€” 4 answered, 1 waiting for your approval, 1 escalated (a refund request). 2 tickets still open.
πŸ“Š Kai: revenue up 8% vs last week β€” candles leading. One flag: conversion on the homepage dropped since Monday.
One thing for you: approve Maya's reorder draft for jasmine.

It just happens. No servers to manage, no settings to keep up to date β€” your team shows up every morning, on time.

Technical detail β€” how the daily rhythm runs, for agent architects
Scheduling
Every time is per-shop in the shop's timezone β€” the 8am here is illustrative. BullMQ schedulers tick and enqueue jobs: Maya's scan at maya_shop_settings.dailyScanTime, Kai's snapshot at kai_shop_settings.snapshotTimeLocal (default 07:00, 5-min poll), and the specialist snapshot workers ~30 min before the owner's brief time. The first brief is held until the day after Telegram is connected β€” the connection-day brief and its snapshot are suppressed (compared in the shop's timezone) so Ava's welcome message is the owner's first contact, not a brief on an empty relationship. The brief time and on/off are changeable from the dashboard or straight from chat β€” just tell Ava "send my brief at 7:30" or "turn off the morning brief" and confirm; she checks the new time still leaves room for Maya's scan and Kai's snapshot beforehand.
Pre-computed snapshots
Each specialist writes its 24h summary before the brief β€” no agent is called live at brief time. jim-snapshot-worker and sarah-snapshot-worker write agent_memory; maya-scan-worker records a DailyMemo; kai-snapshot-worker upserts kai_snapshots.
Brief synthesis
brief-worker gathers each hired specialist's SpecialistReport (runJimDailySummary / runSarahDailySummary / runMayaDailySummary / runKaiAnalyticsSummary) and makes exactly one Claude Sonnet call per shop β€” no tools, worker concurrency 4. Ava writes it in the owner's preferred_language (falling back to the store-wide shops.language when none is set) and briefing_structure.
Delivery
One Telegram message (via the shared @broomAI, or your own bot if you brought one), plus the web dashboard. A missing snapshot degrades to a "no snapshot yet" section β€” the brief still ships.

When you message your team.

Type in chat or Telegram. The right agent picks up β€” and asks you before changing anything. Replies are concise by default (the answer first, no padding); you can switch the whole team to a more balanced or detailed style anytime in Settings β†’ Response style.

1
"Add tracking 1Z123 to order #1003."
You, in chat or Telegram.
2
The routing brain reads your message and recognizes it would change your store.
It knows the difference between a question, a small action, and a real change.
3
It hands the request to πŸ“¦ Jim β€” your shipping specialist.
4
Jim drafts the action and stops at a checkpoint.
Anything that touches your store waits for your yes.
5
Jim replies: "I'll add tracking 1Z123 to order #1003. Reply yes to confirm."
6
You reply yes β€” Jim does it, confirms back, and logs the change.

They remember what you tell them

"Jim, always use UPS for fragile orders."
β†’
πŸ“¦ Jimremembers it and applies it from then on
"Sarah, sign off as 'The Team' and keep it warm."
β†’
πŸ‘©β€πŸ’» Sarahuses that tone & sign-off in the replies she drafts

Every teammate keeps a short memory of your standing preferences β€” just tell them in chat, or add, edit, and remove items yourself on each agent's page in the dashboard. They apply what they remember when answering you and when doing their own work. (Sarah's preferences shape the tone and sign-off of customer replies and any offer you've authorized β€” never the facts, which always come from your real order data.)

Language works the same way. You pick the language your team speaks when you sign up (and can change it anytime in Settings) β€” every agent replies in it. Want just one teammate in a different language? Tell that agent on Telegram; it'll ask whether the change is just for them or for everyone, then remember it. A per-agent choice always wins, so you can run the whole team in English but have Kai answer you in French.

You can also set how your team frames things. There's a store-wide messaging style in Settings: keep it standard, or switch it to sales-led, where every teammate leads with the revenue angle and ends with the next move that grows sales β€” restock a best-seller before it sells out, prioritise a high-value order, nudge a popular pairing, win back a lapsing customer. It changes the emphasis of what your team says, never what they can actually do, and the numbers always come from your real store data.

They also build up a picture of your store over time. Beyond the standing preferences above, your team keeps a short, growing set of notes about how your store actually behaves β€” recurring issues and how they were solved, what worked (a discount, a supplier swap), busy seasons, supplier quirks, common customer questions. Each night a quiet background routine reviews the day and updates these notes; the next day your team starts already knowing the context, instead of asking again. They look a note up only when it's relevant to your question, and they treat it as background β€” never acting on an old note without checking the live data first. You can switch this off anytime in Settings (next to the thinking-level control); it's on by default.

Who picks up the phone?

"How's revenue this week?"
β†’
πŸ“Š Kaian analytics question β€” answered straight away
"If traffic spiked but no one bought, what would you do?"
β†’
πŸ“Š Kaia hypothetical analytics question β€” still Kai's diagnostic, not a generic strategy chat
"Watch mobile traffic β€” ping me if it dips."
β†’
πŸ“Š Kaia watch assignment β€” tracked daily, alerts if triggered
"Refund order #1003."
β†’
πŸ“¦ Jima real change β€” pauses for your yes
"Change the delivery address on order #1002."
β†’
πŸ“¦ Jima real change β€” he tells you the order's shipping status first, then pauses for your yes
"What's running low?"
β†’
πŸ“‹ Mayainventory question β€” answered straight away
"Send an order request to Tom."
β†’
πŸ“‹ Mayaa supplier reorder β€” Maya writes the purchase-order email and sends it once you approve
"Add the England jersey to the store β€” sizes S/M/L/XL, 25 of each."
β†’
πŸ“‹ Mayaa new product β€” Maya creates it with all its sizes and starting stock once you approve
"Customer #2244 wants to return."
β†’
πŸ‘©β€πŸ’» Saraha support thread β€” drafts a reply for you
"Kai, only alert me on big stuff."
β†’
πŸ“Š Kaia settings change β€” he shows current β†’ new and waits for your yes. Every agent takes its settings by chat the same way.
"What's going on?"
β†’
πŸ‘” Avaa big question β€” pulls from the whole team
Technical detail β€” routing & the approval gate, for agent architects
Routing
Every inbound message runs through the Haiku router (ManagerRouter), which picks Ava or a hired specialist β€” biased toward conversational continuity, with an explicit domain rule per specialist: Jim for order-fulfilment writes, Kai for analytics (including hypothetical "what would you recommend if X?" framings), and Maya for inventory, product/catalog (including creating brand-new products β€” "add this product to the store"), supplier, and reorder asks β€” including supplier purchase-order emails like "send an order request to Tom", which used to slip through to Ava because she has no email tools (as did add-product asks, until the catalog rule was added). A brief interim handoff line is shown in the customer's language.
Trust levels β†’ guardrails
The four trust levels are the guardrailLevel ladder enforced at runtime:
ALWAYS_ALLOWED reads & lookups Β· CONFIRM_USER small actions Β· OWNER_APPROVAL store-mutating / refunds / customer email Β· BLOCKED never.
Approval gate
Writes never run silently. The runtime interceptor (approval-interceptor.ts) catches the tool_use, persists a pending_approvals row with a paraphrased summary, and asks the owner β€” only a yes executes the real tool. CONFIRM_USER and OWNER_APPROVAL are intercepted identically. If an approved action can't be completed (e.g. the store rejects it), the agent doesn't just say "failed" β€” it reads the real error, explains in plain language why it didn't work, and tells you what it needs or offers an alternative.
Yes / no / modify
The reply is read by a hand-written multilingual classifier (~45 lines) returning approve / cancel / unclear. Anything that isn't a clean yes or cancel (e.g. "yes but use UPS") supersedes the pending approval with a fresh proposal.
Concurrency & audit
A Postgres advisory lock (pg_advisory_xact_lock, keyed on conversation id) serialises turns; every executed write lands one or more action_log rows that power Recent Activity. Web β†’ API calls carry a short-lived Bearer JWT.
Token budget gate
Every shop has a BroomAI-token balance (free starter grant + one-time top-ups). Each AI call deducts model-weighted tokens at the single Claude choke point. Before every request the team checks that your balance can cover it β€” so a request is never half-served and your balance can't run a meaningful deficit; the moment there aren't enough tokens for the next request, the worker replies with a friendly "your team is paused β€” top up" note instead of calling the AI, and everything resumes the moment a top-up lands.

When something happens, your team tells you first.

You don't have to ask. Ava, Maya, Kai, Jim, and Sarah all start conversations on their own β€” they watch your store (Jim watches your deliveries, Sarah watches your support inbox) and ping you with the news, plus a draft or action you can approve in one tap.

Stock running low

Maya catches it before you do

1.Shopify lets us know inventory changed.
2.Maya checks the new level against your reorder threshold.
3.If it's below, she pings you with a reorder draft ready to send.
πŸ“‹ Maya
⚠️ Wax Melt β€” Jasmine is at 2 units (threshold 5). Want me to reorder 20 from Pinegrove? Reply yes to approve.
Oversell warning

Before the order goes out

1.A new order would push your stock below zero.
2.Maya catches it the moment the order lands.
3.She pings you with options β€” hold, split, or contact the customer β€” before anything ships.
πŸ“‹ Maya
Heads up β€” order #1041 would oversell Candle β€” Fig by 1. Want me to put it on hold?
Delivery gone quiet

Jim spots a stuck parcel

1.Jim keeps an eye on every shipment's status from Shopify.
2.An order was marked shipped but the tracking never started moving.
3.He pings you so you can chase it before the customer does β€” one message per problem, no spam.
πŸ“¦ Jim
πŸ“¦ Order #1042 has a label but the carrier hasn't scanned it in β€” it's been sitting with no movement for 3 days. The parcel may not have been handed over yet.
First hello

Ava introduces your team

1.The moment you connect Telegram, Ava says hi β€” your whole team is already on board.
2.She introduces your teammates and offers a button to meet each one β€” plus "ask me anything".
3.Tap a teammate to say hi, or just ask Ava a question. (Your morning brief starts the next day.)
πŸ‘” Ava
πŸ‘‹ Hi β€” I'm Ava, your store manager for Wickfield Candles. So glad to have you here! Here's a quick read on things β€” your store has 12 orders in the last 30 days across 34 products. I'll keep the whole team on top of all of it. I don't work alone β€” let me introduce your team:
πŸ“Š Kai β€” analytics Β· πŸ“‹ Maya β€” inventory Β· πŸ“¦ Jim β€” shipping.
Tap a teammate to say hi:
πŸ“Š Meet Kai πŸ“‹ Meet Maya πŸ“¦ Meet Jim Ask me anything
On the house

Ava tells you when free credit lands

1.When we add free credit to your account, Ava sends you a quick, friendly heads-up so you know it's there.
2.No catch β€” it's just there to spend on questions and tasks for your team.
3.Ask her anything about your store to put it to use. (You'll see it in the dashboard too, even if Telegram isn't connected.)
πŸ‘” Ava
Surprise! πŸŽ‰ We've just added 50,000 free BroomAI tokens to your account β€” on the house. Spend them however you like: ask me about your sales, your stock, your orders… anything about your store. What should the team look into first?
Meet the team

Each teammate introduces itself when you tap "Meet"

1.Tap Meet Kai / Maya / Jim in Ava's welcome and that teammate says hi.
2.Each one shares a real number from your store, a tip on getting the most from them, and buttons to meet whoever's left or ask a question.
3.It's instant, and shown in your store's language β€” the team speaks whichever of the supported languages you chose at setup. (If Telegram isn't connected yet, the intro waits for you in the dashboard.)
πŸ“¦ Jim
Hey β€” I'm Jim, your shipping specialist. Great to meet you! I keep your orders moving so nothing slips through the cracks. Right now you've got 3 orders waiting to ship, and the oldest has been waiting since June 1. I work straight from your Shopify orders, so I'm ready to go.
Want to meet the rest of the team, or ask me something?
πŸ“Š Meet Kai πŸ“‹ Meet Maya Ask me about your orders
Next step

They point you to the obvious next move

1.The first time you actually ask an agent something, they answer β€” then add one friendly line pointing to what would help most next.
2.Ava suggests hiring Kai for analytics; Kai suggests connecting Google Analytics (and hiring Maya); Maya suggests adding your suppliers so she can draft reorders.
3.It's a one-time nudge with a link β€” never a repeated ask, and only when it actually applies.
πŸ“Š Kai
Your traffic's up 12% week-on-week, driven mostly by search.

Tip: connect Google Analytics and I can break down traffic sources, conversion, and per-channel performance β€” not just Shopify's own sales. Connect it here β†’
Daily brief

Ava sums up the morning

1.The morning after you connect, the daily rhythm kicks in (day one is just Ava's hello). Each morning Ava cross-references the whole team.
2.She picks out what matters and skips the noise.
3.You get one brief β€” three lines β€” with one thing to do.
πŸ‘” Ava
Yesterday: 5 orders shipped, 1 low-stock flag, 4 customer questions. One thing for you: approve Maya's reorder for jasmine.
Analytics alert

Kai spots a trend before it hurts

1.Kai runs his morning analysis β€” pulling Shopify sales data (and GA4 if connected) β€” and then re-checks your headline numbers every few hours through the day. Those in-between checks are cheap: he only runs the full analysis when something has actually moved past a threshold you set, so a midday drop doesn't wait until tomorrow.
2.He rates each insight by severity. You control which level triggers a Telegram ping in his settings.
3.When an in-between check catches something above your threshold, it goes straight to your phone right away β€” that's the point of the midday checks. Everything from the morning run comes together in your daily brief a few minutes later, so Kai doesn't ping you separately for it and then repeat it in the brief.
4.He raises each finding once β€” it won't keep re-appearing in tomorrow's brief (and the day after) with the same dates. When the situation clears, Kai quietly marks it resolved; if it's still going, you only hear about it again when it actually gets worse.
πŸ“Š Kai
⚠️ Conversion dropped 34% this week β€” 210 sessions but only 3 orders (1.4%, down from your usual ~7%). Traffic held steady, so this is a conversion problem, not a reach one β€” something between landing and checkout changed. Worth a look.
Customer emails support

Sarah works the inbox

1.A customer emails your support address. Sarah reads it and sorts what it's about.
2.She finds the order and checks the sender's email matches it. If it doesn't match β€” or it's a refund, cancellation, or order change β€” she escalates to you instead of answering.
3.To answer she can look things up: product availability and price (in stock / low / out β€” never your exact counts), your shipping options to a country, and β€” for a verified sender β€” the order's tracking. She drafts a reply from those real details and shows it to you to approve before it sends (or auto-sends it, if you've turned that on). If a lookup comes up empty she escalates instead of guessing.
4.She can ping your main Telegram channel as it happens β€” you choose which: when a draft is ready, when she escalates, and/or when a reply was sent. Draft-ready and escalation pings are on by default; reply-sent is off. Flip any of them to match how chatty you want her (and it only happens if your Telegram bot is connected).
πŸ‘©β€πŸ’» Sarah
πŸ“¨ A customer asked where order #2244 is. The email matches the order β€” it shipped Tuesday, out for delivery today. Here's a draft reply with the tracking link. Reply yes to send.
Technical detail β€” the proactive triggers, for agent architects
Maya β€” webhooks & daily scan
Two Shopify webhooks fire her in real time: orders/create (oversell check) and inventory_levels/update (threshold check). Each webhook route verifies β†’ enqueues β†’ returns 200 fast; a separate worker drains the queue and sends one message per event (a discrete, actionable thing happened), deduped via Redis SET … NX EX 86400 keyed on (shop, type, variant, tz, day) so the same SKU doesn't ping twice. The daily scan works differently: it does not send its own message. It records the day's findings (so they land in your morning brief) and quietly queues each reorder draft for approval behind the scenes β€” then stops, leaving the news to Ava's brief a few minutes later. That mirrors Kai's daily run and stops a separate "good morning, you're low on…" Maya message from arriving right before a brief that already covers it. (For the webhooks to fire, Maya's subscriptions have to exist on your store β€” they're set up when you hire her and now re-checked on every Shopify reconnect and on startup, so a hiccup can't quietly switch the real-time alerts off.)
Kai β€” analyst chain
Three BullMQ workers chain: kai-snapshot-worker β†’ kai_snapshots β†’ kai-analyst-worker (Claude Sonnet, scores insights 1–5) β†’ kai_insights β†’ kai-proactive-worker. Runs once daily (full analysis) plus an intra-day tripwire every tripwireIntervalHours (default 4): the tripwire computes the cheap snapshot and a deterministic gate (evaluateTripwire) only fires the Sonnet analyst when revenue / orders / conversion / sessions move past tripwireThresholdPct (default 15%) vs the prior 24h β€” quiet ticks cost zero LLM and write nothing. The daily full run does not ping Telegram β€” its insights are delivered by the daily brief that runs minutes later β€” so only the intra-day tripwire (and owner-initiated manual runs) send proactive pings, and then only for severity β‰₯ proactiveSeverityThreshold (default 3); everything else waits for the brief, and analyst-side dedupe means a persistent dip pings once, not every check. The message itself is plain-language (friendly severity tag + headline + suggested actions) β€” the insight's internal evidence fields are never dumped into it. The daily run also includes a deterministic bought-together pass (no Claude, no tokens): it mines persisted order line items for products frequently purchased together and raises a low-severity bought_together insight for a strong pair β€” a bundling/cross-sell prompt that flows through the same feed + brief, and pairs with Maya's bundles.
Jim β€” delivery webhooks & daily scan
Two Shopify webhooks fire him in real time β€” fulfillments/create and fulfillments/update (carrier-driven status transitions: failure / attempted-delivery / delivered). Each route verifies β†’ enqueues onto jim-event-queue β†’ returns 200 fast. Because the absence of progress never arrives as a webhook, a daily safety-net scan (jim-scan-queue, fanned out per shop alongside the pre-brief snapshots) re-reads recently-shipped orders and catches the quiet failures: shipped with no tracking past a grace window, a label stuck pre-transit, or a parcel stalled in transit. Both detectors run the same pure rule set (evaluateDelivery over Shopify's shipment_status), dedupe per (fulfillment, flag) in agent_memory so the same parcel pings once, and deliver one message per problem through jim-proactive-queue (Claude prose, deterministic fallback). It works from Shopify's own shipment status β€” which only some carriers populate β€” so an opt-in carrier-API fallback (per-shop carrierTrackingEnabled, default off) fills the gap: for exactly the parcels Shopify can't track, Jim looks them up with a carrier API for a live status, ETA, and exception reason (which can also clear a false alarm), then a webhook follows up if the parcel later fails. The fallback is multi-provider β€” Jim routes each carrier to the provider that covers it and is cheapest (EasyPost for the common US carriers, TrackingMore for the long tail of ~1,600 carriers incl. integrators like MBE) β€” so a seller on a regional integrator still gets tracked. Each tracker registered costs BroomAI tokens (the same balance as the AI agents) and is skipped when the shop is out of balance, so it's reserved for the gone-quiet cases. Owner-tunable thresholds + the on/off switches live in jim_shop_settings; subscriptions are set up on hire and re-checked on every Shopify reconnect and on startup.
Sarah β€” inbox loop
Connecting Sarah's support inbox (a second Gmail connection, purpose='support') registers a Gmail users.watch. New mail flows users.watch β†’ Google Cloud Pub/Sub β†’ /api/webhooks/gmail/push (verifies a shared token β†’ enqueues β†’ 200 fast) β†’ sarah-inbox-worker. The worker records a support_ticket per thread, runs a Haiku triage (category + confidence) wrapped in deterministic guards, enforces the identity check (sender email == order email) and the always-escalate rule for critical actions (refund / cancel / dispute / order edit), then runs the reply brain as a bounded Sonnet tool-loop (≀3 steps) that may call three customer-safe, field-whitelisted consult lookups β€” lookup_product (coarse stock only, no exact counts/cost/vendor), get_shipping_options (Shopify shipping zones or policy text, no carrier contract rates), and identity-gated get_order_tracking β€” then drafts a grounded reply or escalates. Answerable emails below the confidence threshold are now attempted (drafted, held for approval) rather than escalated; confidence still gates auto-send. Replies are grounded only in order facts + the admin knowledge base + those looked-up facts; a failed lookup returns "unavailable" β†’ escalate, never guess. Each capability is owner-toggleable (default on).
Delivery & retry
Proactive messages are best-effort sent to shop.briefingChatId via the shop's Telegram client; on failure deliveredToTelegram stays false so the next run re-enqueues. Reply intents ack / snooze 24h / tell me more update the insight's status.
Token budget gate
All of these proactive paths pause when the shop's BroomAI-token balance is exhausted: the brief is skipped, Maya and Kai alerts hold, and Sarah's inbox degrades to record-only (every email is still captured as a ticket, nothing is lost). When the balance runs out you'll see the "your team is paused β€” top up" message the next time you chat, and everything resumes automatically after a top-up.
Still no silent writes
Proactive agents respect the same approval gate β€” Maya's reorder pauses for your yes showing the full email + recipient, and only then does she send it (the default; a kept-but-disabled "drafts only" mode would save it for you to send instead), and Sarah's email reply waits for your approval by default (auto-send is an opt-in per-shop setting, off by default; even then she never touches orders or inventory β€” refunds, cancels, and order edits always escalate). Ava and Kai are read-only by design and never mutate the store.