City Hacks · Challenge 2

Student AI Intake → Work Order

A student reports a building problem to a tool-using AI agent over Telegram, a phone call, or web chat. The agent classifies it, asks for + confirms a real location, drafts a polished report, and — only after the student confirms — files a real CriticalAsset work order (due in 30 days), appearing live on the operator dashboard.

Agentic · tool-loop CriticalAsset GraphQL Mongo cityhacks Telegram · Twilio voice
Try it & watch the demo
Telegram intake — reporting a building issue
Telegram intake — confirming the work order
Web intake — Start a New Request (/report)

Actors & Systems

Student (Telegram · phone · web)
AI Agent (OpenAI · gpt-5-mini)
CriticalAsset GraphQL
MongoDB (local)

Status Accents

sky — channels / To Do
emerald — server-side / API
rose — append-only · never delete
violet — async / webhook

Connections

solid — synchronous call
dashed — async / webhook
amber — agent & primary path

Tooling

match_location
propose_report
add_change_request
monospace = ids & tool names
In plain English — how it all works

No jargon here. This is the simple version of what happens when a student reports a building problem — and how staff handle it. The three boxes below cover the big picture, how a student creates a request, and how the staff dashboard works.

1

The big picture

A student notices something broken — a heater that won't turn on, a leaking sink. Here is the whole journey, start to finish:

Student
notices a problem
AI assistant
listens & helps
Work order
written up
Staff dashboard
staff see & act
Student notified
kept in the loop
2

How to create a request (the student)

Reporting a problem takes a minute or two. Just five steps:

  1. 1
    Reach the assistant the way you like. Message the Telegram bot, call the phone number, or use the web chat. Pick whatever is easiest for you.
  2. 2
    Say what's wrong and where. Describe the problem and the building and room. The assistant asks a quick question or two and confirms it has the exact location right.
  3. 3
    Review the summary. The assistant writes a clear, professional report for you and shows you a short summary of what it will file.
  4. 4
    Confirm it. On Telegram, tap Yes (you'll also see Cancel and Keep talking). On a call, just say "yes." Choosing Cancel throws it away — and it double-checks before doing so.
  5. 5
    Done — it's filed. A real work order is created (with a due date about 30 days out) and staff can see it right away. Later, you can still add a photo or a note to a request you already made.
3

How the dashboard works (the staff)

Facilities staff manage everything from one screen:

  • One list of every request. The Work Orders Dashboard shows them all, with simple counts at the top: Open In Progress Overdue.
  • Search and filter to find anything. Narrow the list by status, priority, or building, and click any request to see the full details — what's wrong, where, how urgent, the due date, and any photos.
  • Update the status, and the student hears about it. When staff move a request forward (for example, to In Progress or Done), the student who reported it is messaged automatically — closing the loop.
Pages & Routes — explore the app

Route map · every page & endpoint

Pages · user-facing
  • GET / Work Orders Dashboard — the operator's list of every request, with counts & filters.
  • GET /report Web intake chat — student talks to the AI agent and uploads photos.
  • GET /architecture.html This architecture & workflow diagram (static).
Channel & intake APIs
  • POST /api/telegram/webhook Telegram bot updates — text & inline buttons (Yes / Cancel / Keep talking) into the agent loop.
  • POST /api/twilio/voice Inbound phone call — caller speaks the issue; a spoken "yes" files it.
  • POST /api/twilio/sms Inbound/outbound SMS — text channel & status notifications.
  • POST /api/whatsapp/webhook WhatsApp messages routed into the same agent.
  • POST /api/intake/chat Web chat turn — drives the tool-using agent loop.
  • POST /api/intake/submit Confirms & files the drafted report as a real work order.
  • POST /api/intake/upload Uploads an intake photo (presign → store → confirm).
Work-order APIs
  • GET /api/workorders List all work orders for the dashboard.
  • PATCH /api/workorders/[id] Update one order (e.g. status change) — triggers a student notification.
  • DELETE /api/workorders/[id] Remove an order.
  • GET·POST /api/workorders/[id]/notes Read or append a context note (append-only).
  • GET·POST /api/workorders/[id]/attachments Read or append a photo/file (append-only).
System Map · two channels converge on one agent
Student
entry channels
A Telegram bot

Text + inline buttons — ✅ Yes / ✖️ Cancel / 💬 Keep talking — routed into the agent loop.

POST /api/telegram/webhook
B Phone call · Twilio voice

Caller speaks the issue; a spoken "yes" files it, "cancel" → an are-you-sure prompt.

POST /api/twilio/voice
C Web chat

Describes the issue and drops intake photos — same agent loop.

POST /api/intake/*
one agent, every channel
client → /api/*

Every channel only ever reaches our server via /api/*. The CriticalAsset token never reaches the client.

AI Agent — OpenAI (gpt-5-mini)
tool-using loop · the centerpiece
agent loop
01 · THINK
Reason
plan next step from context
02 · ACT
Call tool
invoke a typed tool
03 · OBSERVE
Read result
ingest tool output
04 · RESPOND
Reply / loop
answer or iterate
repeats until the report is ready / the student is answered
Agent tools → CriticalAsset GraphQL & Mongo
match_location
→ getLocations · confirm "where" against a REAL locationId (never invented)
propose_report
classify category + priority · draft a polished report to confirm
list_student_orders
look up a returning student's orders by phone / chat id
add_change_request
append-only note/photo on an existing order
createWorkOrder
on confirm · due in 30 days · + intake photos
uploadAttachment
presign → PUT → confirm · holds file keys
API & Stores
server-side
G CriticalAsset GraphQL

Work orders · locations · users · file uploads.

workOrders getLocations fileUploads
M MongoDB cityhacks

Stores what the API can't: student contact, order links, notes.

students
phone · name? ·
workOrderIds[]
conversations
phone? · channel
messages[] · draft
changeRequests
append-only
workOrderId · note · fileIds[]
notifications
workOrderId · phone
lastStatusSent · history[]
D Operator Dashboard

Challenge-1 app at / — new order lands as To Do

N Status notifications

On a dashboard status change, the linked student is messaged on their own channel (Telegram bot / SMS).

Server-side boundary. The browser only calls our /api/* routes; the CriticalAsset API token lives only on the server and never reaches the client. Tools execute server-side, then results stream back to the agent.
Append-only change-requests add · never remove
flow 5 · stored as changeRequests
+

When a student adds a photo and/or a context note to an existing order, it is written as a new change-request — existing report content is never deleted or edited. Operators see each addition surfaced on the dashboard as a timestamped entry.

Seven Flows · numbered & directional

1
Intake
Student reports a building problem over Telegram, a phone call, or web chat — all into the one agent loop.
2
Locate + classify
Agent asks for + verifies a real building/address via match_location (never invented), then sets category + priority.
3
Confirmation gate
Before any write — Telegram buttons or a spoken "yes" to confirm; Cancel → an are-you-sure prompt.
4
Create work order
On confirm, createWorkOrder due in 30 days · links student ↔ order. Lands To Do.
5
Returning student
Known student → list_student_orders → add_change_request (append-only; never deletes/edits).
6
Dashboard → notify
Operator changes the order (PATCH) → the linked student is notified on their channel (Telegram bot / SMS) → logged in notifications.
7
One agent, every channel
The same agent is shared across Telegram, voice, and web — one tool loop, one confirmation gate, no matter how the student arrives.
happy path: intake → confirm (buttons / "yes") → createWorkOrder (due +30d) → dashboard To Do ⇢ operator PATCH ⇢ student notified
City Hacks · Challenge 2 — agentic intake → CriticalAsset work order · solid = sync  ·  dashed = async/webhook