Case study — automated operations pipeline

Columbus Fleet Ops

Six months of AI-assisted micromobility operations (Jan–Jun 2026). Twice a day, an agent pulled live data from the fleet warehouse, classified coverage, rebuilt six dashboards, and texted every stakeholder a different view of the same run.

Fleet Bird / Spin shared scooters Cadence 6:00 AM & 3:00 PM ET Recipients 4 (ops lead, team lead, 2 partners) Status retrospective — no longer live
Architecture

One run, three outputs, one memory

Every run read live fleet data, produced dashboards and messages, and wrote a JSON snapshot that the next run read back — the only thing that let a stateless twice-daily job behave like it remembered yesterday.

Source
Presto / Metabase — scans, tasks, bounties, vehicles
Analysis layer — AI agent, twice daily
Coverage classification · schedule inference · anomaly detection · partner gap evaluation
6 dashboards
Static HTML, deployed to a host
JSON snapshot
State carried across runs
iMessage × 4
Per-audience content & tone
Notion hub
Partner reports
Feedback loop
Notes widget → JSON export → read at next run's pre-flight

Per run: main ops dashboard · GPS scan map · two partner reports · schedule comparison · worker registry · OOB rebalance worklist (xlsx + self-contained SVG map).

01 · Coverage-gap detection

Schedule vs. presence, cross-checked three ways

Every run cross-referenced the official Homebase schedule, a schedule inferred from 14 days of scan patterns, and live scans today. The day was classified 🟢 / 🟡 / 🔴, and only the last two ever triggered an alert.

COVERED

Auto-generated message

All internal workers active by 7:15 AM. Partner B on a 6-day active streak. Rebalance external share dipped to 44% yesterday.
Workers active4 / 4
Peak-hour demand~19 bounties
Alert sentfalse
alert_channelnone

Illustrative — reconstructed from sanitized production message examples. Try the toggle above.

02 · Partner accountability

Accountability without adversarial alerts

External operators set their own schedules — a gap on a low-demand day is planned downtime, not a no-show. Alerts were gated on demand context, deduped via a persisted alert_sent_today flag, and never used the words "alert" or "warning" in partner-facing text.

Meaningful gap → sent (demand was real)

🔴 PARTNER COVERAGE — Columbus 6AM [Name] — your team hasn't shown scan activity today. Bounties available: ~38 swaps + ~24 rebalances estimated Please confirm your team is heading out, or let [ops lead] know if coverage needs to be arranged.

Softer signal → heads-up, not an alert

🟡 PARTNER HEADS UP — Columbus 3PM Active days last 7: 2 / 7 Swap coverage last period: ~31% of available Rebalance coverage last period: ~18% of available Wanted to flag this so we can stay on top of things together.

Quiet day, zero bounties → no message at all. The gate is demand, not the gap itself.

03 · Commitment tracking

Two numbers the whole partnership hinged on

Battery swaps and rebalances completed by external operators, computed daily from task completions, rendered as color-thresholded progress against target.

Swap coverage92% / target 100%
Rebalance coverage44% / target ≥50%

Marker shows the ≥50% target line — this is the "external rebalance share dipped to 44%" flag from the digest above. See sql/task-completions-external-share.sql.

04 · Out-of-bounds rebalance

An exclusion cascade, run twice daily

Every vehicle with a same-day GPS fix passed through three exclusions before landing on a worklist — stale coordinates send field workers to places vehicles no longer are.

Vehicle has an active bounty excluded
Vehicle sits inside an in-bounds polygon excluded
Vehicle sits inside a launched nest polygon excluded
Remaining vehicles → OOB worklist emitted

Output: an xlsx with per-vehicle deep links, plus a fully self-contained inline-SVG map — no CDN dependencies, so it renders in a chat preview as readily as a browser tab. See sql/fresh-gps-oob-export.sql.

05 · Human-in-the-loop feedback

Memory with zero infrastructure

Each dashboard carried a notes widget backed only by localStorage. Notes exported to JSON, and the next run's pre-flight step read them back in as prior-run context — a feedback loop between a human and an autonomous agent with no server at all.

notes — main dashboardlocalStorage
📌 Prior run noted: Partner A lead confirmed back Monday — gap alert suppressed through the weekend as instructed.
Retrospective

What we learned

SIGNAL QUALITY

Scans are attendance, not performance. One field worker showed 13 scans against 31 confirmed task completions in the same window. Every presence signal was cross-referenced against the task table before any conclusion.

TRUST

Demand context must gate alerts. Early versions flagged every partner scan gap. That erodes trust fast when the partner simply wasn't scheduled — gating on "was there meaningful work available?" turned the channel from noise into signal.

DATA PROVENANCE

Distrust convenient documents. Two externally-produced audit spreadsheets proved unreliable — one showed zero activity on a day with confirmed field work. Policy: the warehouse is canonical, missing ranges are flagged as pipeline gaps, never assumed zero.

IDENTITY

Identity resolution needs a human channel. Day-of-week inference misbucketed workers; only database email evidence and human confirmation were reliable. The worker registry carried explicit Confirmed / Unconfirmed states.

FRESHNESS

GPS freshness is correctness. The vehicle query joins the dimension table for the same-day GPS fix rather than trusting the current-state snapshot.

DISTRIBUTION

Static HTML + texts beat BI logins. Field operators reliably opened a short link from a text. Nobody logged into a BI tool.

METRIC HYGIENE

Admin accounts distort field metrics. The ops lead's own account was excluded from every field-action query by standing policy.

Reference

Repo map

PathContents
sql/Annotated production queries (Presto dialect)
snippets/Feedback widget, reusable patterns
examples/Sanitized message examples, partner report excerpts, run snapshot schema
screenshots/Dashboard and map captures

All personal identifiers — names, phone numbers, emails, account UUIDs, internal admin URLs — have been removed or replaced with placeholders. Fleet-level data shown is representative.