Pre-stage household grocery carts from Instacart history
A collection of infrastructure add-ons for OpenClaw that turn it into a household operating system. Task: A collection of infrastructure add-ons for OpenClaw that turn it into a household operating system. Built for a real family, running in production on a Mac Mini M4. These aren't typical OpenClaw skills (SKILL.md files that teach the LLM what to do). Most are infrastructure — daemons, databases, pipelines, and automation that run alongside OpenClaw, handling the things an LLM shouldn't be trusted to do reliably. Some (Apple Reminders, Tool Routing) are pure skill definitions that teach the LLM correct tool selection and usage patterns. Here are some examples of this setup in my daily life: The Core Idea: LLM Plans, Code Delivers Every component follows the same principle: the LLM decides what to do, deterministic code executes it. No LLM is involved at message delivery time, flight polling time, or database write time. The LLM's job is language and reasoning. Code handles reliability. Components 1. Outbox — Scheduled Message Delivery A SQLite message queue with a polling daemon. The LLM writes messages to a table with a scheduled send time. A Python daemon delivers them via iMessage (BlueBubbles). No LLM at delivery time. Why it exists: OpenClaw crons re-invoke the LLM at delivery time. The LLM reinterpreted instructions differently each run — trip dinners went as individual DMs instead of group chat, a flight monitor ran 22 polls and delivered zero notifications. The outbox pattern eliminates this failure mode entirely. 2. Trip Manager — Database-First Trip Automation The LLM writes trip data directly to SQLite through a CLI (trip-db.py add-flight, add-hotel, etc.). Outbox messages are auto-generated for flight reminders, hotel check-ins, and dinner notifications. Flight monitor state is auto-derived. Update any record, regenerate downstream — only the changed items, no full regeneration. Setup automation: Creating a trip automatically texts the household manager asking "solo or group?" A solo reply triggers setup-solo (resolves the traveler from contacts, sets their phone as the notification recipient). A group reply triggers adding travelers + find-group-chat (scans recent iMessage chats to discover the group GUID). No manual GUID lookups. Watchers — additive recipients. Two kinds of people exist on a trip: travelers (the people actually flying — drive primary routing) and watchers (people who want a copy of flight events without traveling). A parent at home tracking their kid's flight, a partner CC'd on a business trip's status. Watchers are stored as travelers rows with role='watcher', resolved from contacts.sqlite by name (or explicit --phone override), and excluded from update_travelers_display so the trip's primary routing is untouched. Adding a watcher is additive — add-watcher --trip <id> --name Manan adds one travelers row and changes nothing else. When the flight monitor sends a notification, it queues one outbox row per watcher in addition to the primary recipient (source tag flight:<num>:watcher). Watchers are nullable — every trip without one continues to work exactly as before. Why it exists: Family travel has dozens of moving parts — flights, hotels, restaurants, Uber links, group chat notifications — spread across confirmation emails and text threads. Without structure, details get lost and nobody gets reminded. The trip manager gives the LLM a single database to write to, and deterministic scripts handle all the downstream notification scheduling and flight tracking setup. 3. Flight Monitor — Real-Time Flight Tracking Daemon A persistent daemon that polls FlightAware AeroAPI, detects events (landing, delay, gate change, diversion), and sends notifications through the outbox. Adaptive polling — 3 minutes during active window, 30 minutes when idle. No LLM in the polling loop. Watcher fanout. After every event, the monitor queues one outbox row to the trip's primary recipient (group chat for group trips, traveler's phone for solo) and then one additional row per watcher (travelers rows with role='watcher', see Trip Manager above). The primary delivery is unchanged whether watchers exist or not; the fanout block is wrapped so any per-watcher failure (missing phone, outbox enqueue error, DB query failure) surfaces as a system_alert to the household manager rather than dying silently. Dedup skips watchers whose phone equals the primary recipient.; tools: OpenClaw. Human role: The original post does not say how a person stayed involved.; limitations: Requires an active Instacart session and the instacart-pp-cli binary. The system relies on stable canonical item IDs; if Instacart rotates IDs, fallback name-searching may introduce errors. Human intervention is mandatory for placing orders, as the tool only stages carts. Operating costs include potential API fees for underlying services, though the core logic is local. Source reliability is high for the described architecture, but specific performance metrics beyond accuracy are not provided..
Tools
Published on Agent Work Atlas:
Overview
A collection of infrastructure add-ons for OpenClaw that turn it into a household operating system.
Workflow
A collection of infrastructure add-ons for OpenClaw that turn it into a household operating system. Built for a real family, running in production on a Mac Mini M4. These aren't typical OpenClaw skills (SKILL.md files that teach the LLM what to do). Most are infrastructure — daemons, databases, pipelines, and automation that run alongside OpenClaw, handling the things an LLM shouldn't be trusted to do reliably. Some (Apple Reminders, Tool Routing) are pure skill definitions that teach the LLM correct tool selection and usage patterns. Here are some examples of this setup in my daily life: The Core Idea: LLM Plans, Code Delivers Every component follows the same principle: the LLM decides what to do, deterministic code executes it. No LLM is involved at message delivery time, flight polling time, or database write time. The LLM's job is language and reasoning. Code handles reliability. Components 1. Outbox — Scheduled Message Delivery A SQLite message queue with a polling daemon. The LLM writes messages to a table with a scheduled send time. A Python daemon delivers them via iMessage (BlueBubbles). No LLM at delivery time. Why it exists: OpenClaw crons re-invoke the LLM at delivery time. The LLM reinterpreted instructions differently each run — trip dinners went as individual DMs instead of group chat, a flight monitor ran 22 polls and delivered zero notifications. The outbox pattern eliminates this failure mode entirely. 2. Trip Manager — Database-First Trip Automation The LLM writes trip data directly to SQLite through a CLI (trip-db.py add-flight, add-hotel, etc.). Outbox messages are auto-generated for flight reminders, hotel check-ins, and dinner notifications. Flight monitor state is auto-derived. Update any record, regenerate downstream — only the changed items, no full regeneration. Setup automation: Creating a trip automatically texts the household manager asking "solo or group?" A solo reply triggers setup-solo (resolves the traveler from contacts, sets their phone as the notification recipient). A group reply triggers adding travelers + find-group-chat (scans recent iMessage chats to discover the group GUID). No manual GUID lookups. Watchers — additive recipients. Two kinds of people exist on a trip: travelers (the people actually flying — drive primary routing) and watchers (people who want a copy of flight events without traveling). A parent at home tracking their kid's flight, a partner CC'd on a business trip's status. Watchers are stored as travelers rows with role='watcher', resolved from contacts.sqlite by name (or explicit --phone override), and excluded from update_travelers_display so the trip's primary routing is untouched. Adding a watcher is additive — add-watcher --trip <id> --name Manan adds one travelers row and changes nothing else. When the flight monitor sends a notification, it queues one outbox row per watcher in addition to the primary recipient (source tag flight:<num>:watcher). Watchers are nullable — every trip without one continues to work exactly as before. Why it exists: Family travel has dozens of moving parts — flights, hotels, restaurants, Uber links, group chat notifications — spread across confirmation emails and text threads. Without structure, details get lost and nobody gets reminded. The trip manager gives the LLM a single database to write to, and deterministic scripts handle all the downstream notification scheduling and flight tracking setup. 3. Flight Monitor — Real-Time Flight Tracking Daemon A persistent daemon that polls FlightAware AeroAPI, detects events (landing, delay, gate change, diversion), and sends notifications through the outbox. Adaptive polling — 3 minutes during active window, 30 minutes when idle. No LLM in the polling loop. Watcher fanout. After every event, the monitor queues one outbox row to the trip's primary recipient (group chat for group trips, traveler's phone for solo) and then one additional row per watcher (travelers rows with role='watcher', see Trip Manager above). The primary delivery is unchanged whether watchers exist or not; the fanout block is wrapped so any per-watcher failure (missing phone, outbox enqueue error, DB query failure) surfaces as a system_alert to the household manager rather than dying silently. Dedup skips watchers whose phone equals the primary recipient.
Reported result
The initial LLM-driven browser approach failed with 11 out of 14 items incorrectly added due to autosuggest mismatches. Replacing this with a CLI using canonical item IDs achieved 100% accuracy and made the workflow deterministic. The system successfully stages carts on Wednesdays and Saturdays, sending a single notification with a checkout link. No autonomous ordering occurs, as the CLI intentionally lacks checkout capabilities, requiring human confirmation to complete purchases.
Human role
The original post does not say how a person stayed involved.
Limitations
Requires an active Instacart session and the instacart-pp-cli binary. The system relies on stable canonical item IDs; if Instacart rotates IDs, fallback name-searching may introduce errors. Human intervention is mandatory for placing orders, as the tool only stages carts. Operating costs include potential API fees for underlying services, though the core logic is local. Source reliability is high for the described architecture, but specific performance metrics beyond accuracy are not provided.
Try it
Act as a household automation engineer. I need to set up a deterministic grocery reordering system using OpenClaw and a custom CLI. Inputs: - [Instacart Account Credentials] - [Purchase History Data Source] - [Target Notification Channel, e.g., iMessage] - [Output Directory for Scripts] Steps: 1. Implement a nightly script to scrape order history into a local SQLite DB using canonical item IDs. 2. Create a cadence analyzer that computes median days between purchases to tag items as 'due', 'soon', or 'not_due'. 3. Build a cart-staging script that uses the CLI to add 'due' items to the Instacart cart via item IDs, with a safe fallback for ID rotation. 4. Configure a weekly cron job (e.g., Wed/Sat) to run the staging script and send a notification with the checkout URL. 5. Ensure the system never places orders automatically; it must only stage the cart and notify the user. Deliverables: - Python scripts for history scraping, cadence analysis, and cart building. - SQLite schema for tracking reorder notifications. - Configuration files for cron jobs and notification delivery. Quality Check: - Verify that 100% of staged items match the canonical IDs from history. - Confirm that no LLM is involved in the actual cart-building or notification delivery steps. - Test with a small sample of 5 items before full deployment. - Require human confirmation before enabling the cron job for real accounts. If inputs are missing, ask for the specific Instacart CLI tool or API access details. Do not proceed with browser automation if a CLI is available.
Source reports are not independently verified. Publication date is the catalog publication date, not the original article date.