Emergency SOS Network for Your Community By Mindtech Mesh Networks | Technical Architecture by GarageAGI LLC
The Operator is an ultra-lean, 100% off-grid AI switchboard and emergency dispatch gateway built on the Meshtastic LoRa network. It provides automated, decentralized 911-style triage and routing for communities when traditional cellular and internet infrastructure fails.
A working emergency network for the cost of ONE police radio. Hardware agnostic. Open source. Community first.
Props to the developers behind GuardianBridge. We studied their web UI, SQLite databases, and admin panels closely β incredible work for mapping and administration.
But we needed something built for the absolute edge. No web dashboards. No database schemas. No hardcoded logic trees deciding how an emergency should be handled. We needed a Lean Machine.
We dumped the rigid logic trees and built a Smart AI Router. A local LLM (Gemma 3 via Ollama) runs right on the gateway, acting as a dynamic 911 dispatcher. It parses unstructured panic messages, extracts context, and asks dynamic triage questions β all while routing instant GPS coordinates directly to first responders.
No internet. No cloud APIs. No complex databases. Just Python, LoRa, and edge AI.
Citizen types: "!fire Tree fell, kitchen is burning"
β
on_receive()
β
ββββββββββββ΄βββββββββββ
β β
INSTANT (no queue) QUEUED (AI triage)
β β
1. ACK to citizen: ai_worker picks up:
"[SOS] !FIRE RECEIVED "Tree fell, kitchen
GPS: 40.29,-74.73" is burning"
β β
2. Safety bounce-back: LLM responds with full
"If triggered by emergency context
accident, send !safe" injected into prompt:
β β
3. DISPATCH DM to "Is anyone trapped
Firehouse node inside?"
β [Send !safe when
4. Triage session opens emergency is resolved]
β β
5. LOG to .jsonl DM back to citizen
Citizen types: "!911"
β
ACK: "[SOS] 911 RECEIVED. GPS: 40.29,-74.73"
β
Menu: "Reply with a NUMBER:
1 = Fire
2 = Medical
3 = Police
4 = Other
5 = Accident (sent by mistake)"
β
Citizen replies: "2"
β
Maps to !ems β same dispatch flow as above
β
β οΈ No reply after 2 min?
β Broadcast to ALL responders:
"!911 NO RESPONSE β Possible incapacitation"
Citizen sends "!safe"
β
Lookup active_sessions for sender
β
Route [CANCELLED] to SAME
responder(s) who got original dispatch:
"!FIRE from 609-555-0199 marked
SAFE by sender. Use your judgment."
β
ACK citizen: "SOS cancelled."
β
Close triage session β LOG to .jsonl
"Use your judgment." β The responder always makes the final call, not the software. A citizen could be coerced into cancelling. The audit trail preserves both the original dispatch and the cancellation.
When a citizen triggers any SOS (!fire, !911, etc.), The Operator opens a triage session for that sender. Every subsequent message β regardless of content β routes through the Emergency Dispatch prompt until !safe or a 10-minute timeout.
The LLM receives the full triage session object injected into its system prompt every turn:
ACTIVE EMERGENCY:
Trigger: !ems
Time: 2026-02-26T22:22:57
Citizen: 609-555-0199 (Liberty-Node-02)
GPS: 40.29,-74.73
Dispatched To: !22334455 (EMS)
TRIAGE LOG:
[22:23:05] CITIZEN: I cut myself
[22:23:05] OPERATOR: Are you currently experiencing any active bleeding?
[22:23:30] CITIZEN: Yes
[22:23:30] OPERATOR: Assess the wound. Size, location, vital signs.
CURRENT MESSAGE: My cat is stuck in a tree
RULES:
- You are triaging the above emergency ONLY.
- If the citizen goes off-topic, redirect.
The citizen's cat question gets redirected back to the laceration. The LLM can't drift because the emergency is in the prompt, not in memory.
Triage history is capped at 12 entries. When exceeded, the system keeps the first 2 (original emergency description) and the last 10 (recent conversation). The anchor is never lost.
Elevate the affected hand. Is the bleeding slowing?
[Send !safe when emergency is resolved]
The !safe footer is stamped by code, not generated by the LLM. Deterministic. Every message. The citizen always knows how to exit.
First responders can lock out citizens who abuse the system.
Responder receives bogus [DISPATCH]
Responder sends: !spam
β
Auto-targets the last citizen dispatched to THIS responder
(no node ID typing required)
β
Force-closes any active triage session
Locks citizen out for 120 minutes
β
Responder gets: "[RESTRICTED] Liberty-Node-02 locked out for 120 min."
Citizen gets: "Your access has been temporarily restricted."
While restricted, ALL commands are blocked β no !911, no !fire, no general chat. Hard gate.
Responder sends: !cancel
β
"[RESTRICTED LIST]
1. Liberty-Node-02 (609-555-0199) β 87 min left
2. Liberty-Node-14 (732-555-0312) β 22 min left
Reply with number to remove."
β
Responder sends: 1
β
Citizen immediately restored + notified
Restrictions auto-expire after 120 minutes. The watchdog thread cleans them up.
| Command | Action | Bypasses Queue? |
|---|---|---|
!911 |
Guided numbered menu β dispatch | β |
!police |
Direct dispatch to Police node with GPS | β |
!fire |
Direct dispatch to Fire node with GPS | β |
!ems |
Direct dispatch to EMS node with GPS | β |
!help |
Broadcast dispatch to ALL responders | β |
!sos [context] |
Broadcast dispatch + AI triage | β |
!safe |
Cancel active SOS / exit triage session | β |
!ping |
Range test β Operator replies PONG | β |
!status |
System health check | β |
| (any text) | Routed to AI switchboard (or triage if session active) | β |
| Command | Action |
|---|---|
!spam |
Restrict last-dispatched citizen for 120 min |
!cancel |
Show restricted list β numbered removal |
| Slot | Message | Purpose |
|---|---|---|
| 1 | !911 |
Universal emergency β works for everyone |
| 2 | !safe |
Exit triage / cancel SOS |
| 3 | !help |
Instant broadcast to all responders |
| 4 | !status |
Check if Operator is alive |
All events are logged to operator_logs.jsonl β one JSON object per line. Machine-readable, grep-friendly, streamable.
| Type | When |
|---|---|
rx |
Every incoming message |
sos_dispatch |
SOS trigger fired, GPS extracted, dispatched |
sos_911_triggered |
Citizen sent !911, menu shown |
sos_911_no_response |
No reply to !911 after 2 min β all responders alerted |
sos_false_alarm |
Citizen selected "5 = Accident" on !911 menu |
triage_exchange |
Each citizen β operator turn during active triage |
general_exchange |
Normal AI chat (non-emergency) |
sos_closed |
Session ended (reason: safe / timeout / restricted / shutdown) |
restricted |
Citizen locked out by responder |
restriction_lifted |
Responder manually removed restriction |
restriction_expired |
Lockout auto-expired after 120 min |
command |
!ping, !status responses |
bouncer_drop |
Message dropped due to queue overload |
system |
Startup, shutdown, errors |
{"type":"sos_dispatch","ts":"2026-02-26T22:22:57","sender":"!0408a160","phone":"609-555-0199","trigger":"!ems","context":"I cut myself","gps_lat":null,"gps_lon":null,"routed_to":"!22334455"}
{"type":"triage_exchange","ts":"2026-02-26T22:23:05","sender":"!0408a160","session_trigger":"!ems","citizen":"I cut myself","operator":"Are you currently experiencing any active bleeding?"}
{"type":"sos_closed","ts":"2026-02-26T22:26:00","reason":"safe","sender":"!0408a160","phone":"609-555-0199","trigger":"!ems","exchange_count":6,"duration_seconds":183}
{"type":"restricted","ts":"2026-02-26T23:00:00","sender":"!0408a160","phone":"609-555-0199","duration_minutes":120,"locked_by":"!aabbccdd"}| Feature | Description |
|---|---|
| 100% Offline | Runs on a recycled SFF PC or Raspberry Pi with local Ollama. Unplug the ethernet β it doesn't care. |
| !911 Guided Menu | Numbered selection for citizens who can't type. Two taps + one digit = full dispatch. |
| Triage Sessions | Context-locked AI β every message routes through emergency prompt until !safe or timeout. |
| Session Prompt Injection | Full triage object (trigger, GPS, history) injected into every LLM call. No drift. |
| Restricted List | Responders lock out spammers with !spam. 120-min auto-expiry. !cancel to manually remove. |
| Responder Authorization | !spam and !cancel only work from nodes in the RESPONDERS config. Silent drop for everyone else. |
| Auto GPS Extraction | Pulls coordinates from Meshtastic Node DB. Citizens never type their location. |
| Silence-After-911 Alert | No reply to !911 menu within 2 min = broadcast to all responders as possible incapacitation. |
| JSONL Audit Trail | Machine-readable event log. Every dispatch, triage exchange, restriction, and cancellation recorded. |
| Deadlock-Free | Separate state_lock and log_lock. No nested acquisition. |
| Echo Cancellation | Gateway ignores its own transmissions β hexβint conversion. |
| Word Boundary Matching | !fireplace won't dispatch the fire department. |
| Self-Healing | All sends wrapped in safe_send(). USB drops don't crash the script. |
- Any PC or Raspberry Pi running Linux
- 1Γ Meshtastic node (e.g., Heltec V3, Meshnology N32) connected via USB as the gateway
# Install Ollama and pull the model
curl -fsSL https://ollama.com/install.sh | sh
ollama pull gemma3:latest
# Install Python dependencies
pip install meshtastic pypubsub openaiOpen operator_v7.py and update the RESPONDERS dictionary with actual Node IDs (meshtastic --nodes):
RESPONDERS = {
'!sos': None, # Broadcasts to all responders
'!police': '!aabbccdd', # Police Station node ID
'!fire': '!eeff0011', # Firehouse node ID
'!ems': '!22334455', # EMS node ID
'!help': None # Broadcasts to all
}python3 operator_v7.py [Lawrence High School] [Library]
Anchor + Operator GW Anchor
β β
βββββ Solar Repeater βββββββ€
β β
βββββ Solar Repeater βββββββ€
β β
[Municipal / Police] [Firehouse Rt 206]
Anchor + Responder Anchor + Responder
- 4 Municipal Anchors β School, Library, Municipal Complex, Firehouse
- 6 Solar Repeaters β Volunteer rooftops bridging the anchors
- 20 Citizen Handhelds β Distributed at community workshops
- 1 Operator Gateway β SFF PC running
operator_v7.py - 31 total nodes covering one full township
operator_v7.py
βββ on_receive() β Radio packet router
β βββ RESPONDER BLOCK β !spam, !cancel (authorized nodes only)
β βββ RESTRICTION GATE β Hard block for locked-out citizens
β βββ !ping / !status β System commands
β βββ !safe β Cancel SOS / exit triage
β βββ !911 β Guided menu β dispatch
β βββ !911 reply (1-5) β Menu selection β dispatch or false alarm
β βββ SOS triggers β Direct dispatch + triage session
β βββ Active triage? β Route to triage queue
β βββ General messages β Route to AI queue (bouncer at depth > 15)
β
βββ ai_worker() β Background thread
β βββ Triage mode β Session prompt injection + !safe footer
β βββ General mode β Standard Operator prompt
β
βββ dispatch_sos() β Shared dispatch logic (flags + 911 converge here)
βββ watchdog() β Background thread (30s sweep)
β βββ Triage timeouts β 10 min silence β close + notify
β βββ !911 no-response β 2 min silence β broadcast incapacitation alert
β βββ Expired lockouts β Auto-remove from restricted list
β
βββ State
β βββ active_sessions{} β Triage session objects per sender
β βββ restricted_list{} β Locked-out citizens with expiry
β βββ last_dispatch_to{} β Responder β citizen mapping for !spam
β βββ pending_911{} β Awaiting menu reply
β βββ pending_cancel{} β Awaiting !cancel number reply
β βββ conversation_history{} β General chat (non-emergency)
β
βββ Helpers
β βββ safe_send() β Error-wrapped radio transmit
β βββ match_trigger() β Word-boundary SOS matching
β βββ is_my_node() β Echo cancellation
β βββ is_responder() β Authorization check
β βββ is_restricted() β Lockout check with auto-expiry
β βββ get_node_gps() β GPS from Meshtastic node DB
β βββ get_node_name() β Phone/name lookup
β βββ log_event() β JSONL append
β
βββ Triage Engine
βββ create_session() β Initialize session object
βββ build_triage_prompt() β Inject session into system prompt
βββ trim_exchanges() β First 2 + last 10 memory cap
βββ close_session() β Flush to JSONL + cleanup
!911guided menu β Numbered selection for low-literacy users. No reply = incapacitation alert.!spam(responder only) β Auto-targets last-dispatched citizen. 120-min lockout. Force-closes triage.!cancel(responder only) β Numbered restricted list for manual removal.is_responder()authorization β Silent drop for unauthorized!spam/!cancelattempts.restricted_list{}β Hard gate in router. All commands blocked while restricted.last_dispatch_to{}β Tracks responderβcitizen mapping for!spamtargeting.pending_911{}β Awaits menu reply with 2-min timeout watchdog.dispatch_sos()β Extracted shared function. !flags and !911 converge.
- Triage session objects β Full incident state injected into every LLM prompt.
- Context-locked routing β All messages route through triage until
!safeor timeout. - JSONL logging β Machine-readable event stream replacing markdown.
!safefooter β Code-stamped on every triage response.- Timeout watchdog β Auto-closes stale sessions after 10 min.
!safecommand β Citizens cancel accidental SOS. Responders receive[CANCELLED].- Safety bounce-back β Second message after SOS ACK: "Send !safe to cancel."
- SOS triggers with instant GPS dispatch.
- Dynamic AI prompting β Emergency vs general mode.
- Deadlock fix β Separated state and log locks.
- Echo cancellation β
is_my_node()with hexβint. - Word boundary matching β
match_trigger().
- Multi-threaded queue with
ai_worker. - Dynamic Bouncer. Conversation memory. Chunked LoRa TX.
- Beacon range test. Markdown logging.
| Phase | Timeline | Milestone |
|---|---|---|
| Layer 1 | Spring 2026 | Deploy 31-node mesh in Lawrence Township, NJ |
| Community | Summer 2026 | Public workshops at the library β citizens build their own nodes |
| Municipal | Fall 2026 | Demo to township officials, grant applications |
| Freedom Core | 2027 | Transition to 100% American-allied hardware (Semtech + Nordic + US assembly) |
CC BY-SA 4.0 v1.0 β Mindtech Mesh Networks
Technical architecture by GarageAGI LLC.
Powered by Meshtastic Β· Semtech SX1262 Β· Ollama