Daftar Closing Agent: Gemini plans the shop's day; the phone commits the books
This piece was created for the purpose of entering the All Things Agentic Hackathon.
Yemeni and MENA shops still close the day on paper. Balances live in memory. Collections wait until someone remembers who owes. That chore is the friction I built for — Taskmaster, not a chatbot.
Daftar Closing Agent (وكيل إغلاق الدفتر) treats the merchant's business day as the long-running task. Each Cloud Run POST /run is fast on purpose. Cloud Run may scale to zero. The durable work sits on the phone in Drift.
What the agent actually does
Mid-day. Voice or text (Mohamed owes 500 sugar). Gemini 3.5 Flash on Vertex AI, via Google ADK on Cloud Run, emits a proposal. Money hits Drift only after Confirm.
Close. One plan. One tap: Confirm & Send Statements. Then a device-owned ritual: Drift localDay summary → Google Drive backup → FIFO aging → Collections Desk → POST /v1/email/send-batch → smtp.gmail.com.
Aging ranks who is emailed (min(shortlist, 20)). MIME PDF statements go to the ranked Top 5. The rest get a fixed text-only reminder. Gemini does not pick recipients and does not send mail. Confirm without sending still closes the books; send-batch is never called.
Figure 1. Contest architecture. Gemini proposes; the merchant confirms; Drift commits. POST /v1/email/send-batch is a sibling FastAPI route — not an ADK tool. The Architecture HUD observes SMTP; it does not feed the confirm gate.
Why this stack (Architectural Discipline)
| Official ask | What Daftar does |
|---|---|
| Decouple |
/run emits proposals only. Drift commits money. SMTP is a sibling FastAPI route, not a FunctionTool. |
| State | Drift + device ClosingAgentPhase. Scoped daftarContext. No vector database — a debt ledger is a financial source of truth, not a RAG corpus. |
| Credentials | Cloud Run IAM + ID tokens with custom audiences. No allUsers. Gmail App Password in Secret Manager only (gmail-smtp-app-password), never in Flutter. |
| Failures | Confirm-gate lock per proposalId. Drive skip does not abort close. Per-row SMTP failed / skipped. Cloud Run down → ledger intact. Durable send key is device batchId. |
One LlmAgent named closing_agent. Eight frozen FunctionTools. No send-email tool. No SequentialAgent. Mid-day capture is one intent-dependent hop. The close ritual is device-deterministic after one plan confirm.
The offline Drift ledger, Drive backup, and Khazna UI are pre-existing substrate (disclosed). The agentic close path — ADK, Gemini 3.5, HITL, Gmail SMTP, Architecture HUD — was built during the Submission Period (3–31 August 2026).
Proof of Action
SMTP 250 means Gmail accepted the message. It is not mailbox-delivered, not a read receipt, and not a delivery webhook. Gmail SMTP has none. I did not fake delivered. I did not film WhatsApp as the send.
Proof is Cloud Logging daftar.agent.email (unique Message-ID + 250) plus the recipient inbox: MIME PDF on the ranked Top 5, text-only remainder by design.
Figure 2. Cloud Run logs on project daftar-closing-agent. smtpCode: 250 and status: sent are server accept. toMasked keeps the inbox private. This is not proof the mailbox received the mail.
Figure 3. Device-rendered statement for **Omar* (integer USD cents, shown as dollars). On close-the-day, Omar is in the text-only remainder. MIME PDFs attach only for the ranked Top 5 (for example Mohamed). Gemini does not choose who gets a PDF.*
The on-device Architecture HUD shows the same close: model gemini-3.5-flash, tool propose_closing_plan, HITL rail (Propose → Confirm → Commit → Rank), and Sent · Message-ID last-8. The HUD observes; it does not confirm money or send mail.
Figure 4. After close. Thirteen ritual tasks sealed, backup on Drive, seven overdue in the send set. Sent · is Message-ID last-8, matching logs. Today's Drift localDay on this frame is two small debts (USD 3.50) — the sample-store today strip, not the filmed Mohamed $500 capture.
What I learned
The agent should be a clerk who proposes, not a cashier who writes the books. For an offline merchant, the phone is the system of record. Frozen tools are cheaper to reason about than a ninth “just send it” tool.
Repo: github.com/akrmcodes/daftar-closing-agent
Hackathon: All Things Agentic · Track: Taskmaster · Individual




Top comments (0)