Offline-first customer support for React Native, with local knowledge, device AI, visible sources, and a recoverable action outbox.
Airgap is a starter kit for branded mobile support apps that must stay useful when a network is slow, unavailable, or intentionally blocked. It retrieves approved local documents first, then uses an operator-controlled answer provider to phrase the result. Models do not supply company facts. The bundled documents do.
The default demo makes no model request and needs no download. It lets a new contributor check retrieval, citations, privacy status, and the interface before choosing an inference provider or connecting a backend.
The left cards show replies of a national government app's assistant: five published on its
2026-09-21 launch day and two from screenshots of 2026-10-12. The right panel shows Kuya B, the
government-services template, on the same seven prompts on an Android 15 emulator configured
with a 3-bit Gemma 4 E2B file. The president and Palace statement questions go to the model.
The app shows the record unless the model copies it exactly. The challenge, clock, identity,
refusal and resignation answers are code paths.
The president answer comes from a dated record. Its card gives the publisher and the checked date. A challenge re-reads that record. The time comes from the device clock. The identity comes from configuration. A prompt probe gets a fixed refusal from code.
A question about why the DICT Secretary resigned gets a fixed refusal and the dated Palace record, with no reasons. The case study gives every source and the nine controls behind the take.
This GIF shows the same build on an Android 15 emulator and an iPhone 17 Pro Simulator with
built-in document answers. Capture details are in demo/recordings.json.
Install Node.js 22.18 or newer, JDK 17, and Android SDK 36. Then run these commands.
git clone https://github.com/xmpuspus/airgap.git && cd airgap
npm ci
npm run androidChoose Try Offline Demo, then tap a suggested question. This path needs no model file or support service.
To create a branded telco starting point without cloning the full repository, use the published scaffolder.
npx create-airgap-bot support-app --template telco
cd support-app
npm install
npm run androidFor iOS, install CocoaPods dependencies and run the checked Airgap scheme.
npm ci && bundle install
cd ios && bundle exec pod install && cd ..
npm run iosCompile Apple Foundation Models support with Xcode 26 or newer. The app still deploys to iOS 15.1 and reports the Apple provider as unavailable on older or ineligible devices.
The local browser lab and CLI replay 26 government cases from saved public sources and call no model. The reproduction guide covers the commands, the five recorded features, and the local-model comparison.
The diagram below is the whole request path for one user message. Code owns every
control point. The model only phrases retrieved records. The nine controls behind it
are in docs/support-bot-minimum.md.
docs/diagrams/build_minimum_support_bot.py
writes the draw.io source and the PNG.
Text version of the diagram
INPUTS
Config (JSON) brand, bot identity, scope, provider policy, blocklist,
refusal templates
Knowledge store dated records {as_of, content, keywords, source_url},
signed and versioned bundles
REQUEST PIPELINE (per user message, in this order)
1. Guardrails blocklist + prompt-probe rules -> fixed refusal,
(code) no inference
2. Deterministic greeting; "sigurado ka dyan?" -> replay the last
intents (code) record-backed answer; date/time -> system clock;
action phrases -> keyword router
3. Retrieval (local) BM25 over the knowledge store -> top-k dated records
4. Verbatim records identity and scope records render as written,
model skipped
5. Provider chain policy picks one: on-device model (Gemma 4 E2B)
(model phrases only) | demo formatter | optional cloud
prompt = rules + retrieved records + question
6. Output validation every amount, date, and name in the answer must
(code, before render) exist in the records; streamed tokens are gated;
on a miss -> show the record
7. Provenance answer source, publisher, and checked date on
the card. Audit records keep provider and model
ACTIONS (the model never decides)
keyword router -> REST backend connector | offline outbox with
idempotency keys and receipts
EVIDENCE
template fixtures and retrieval assertions in CI
public-service CLI executes government answer/route assertions in CI
recordings pinned to their source commit; manifest validated in CI
Airgap routes every model-made answer through the same provider contract. Before each request, Airgap reads the current device state, applies operator policy, and tries permitted providers in priority order. Cancellation, failure reasons, model identity, timing, and answer provenance use one result shape.
| Provider | Runs where | Data path | Current state in this repository |
|---|---|---|---|
| Apple on-device model | iOS 26+, Apple Intelligence eligible device | On device | Swift bridge, streaming, cancellation, readiness checks |
| Android system AI | Android API 26+, supported AICore device | On device | ML Kit Prompt API beta2 bridge, download, warmup, streaming |
| Downloaded Airgap model | iOS 15.1+ and Android API 24+ | On device | llama.rn, pinned file size and SHA-256 |
| Cloud service | Either platform | Operator endpoint | Off by default, needs policy and a fresh access token |
| Document answers | Either platform | Deterministic on device | Default demo provider, no model request |
Apple Foundation Models needs an Apple Intelligence-capable device. The Android code uses ML Kit GenAI Prompt API, which needs API 26, a supported device, and an available or downloadable Gemini Nano feature.
| Mode | Selection rule |
|---|---|
demo |
Uses only demo, regardless of the configured production provider order |
offline-only |
Excludes cloud and tries permitted local providers in priority order |
prefer-offline |
Uses the configured order, normally system model, downloaded model, then cloud |
prefer-online |
Uses the configured order, normally cloud before local providers |
The operator order takes precedence over a user routing preference. A busy, unsupported, quota-limited, background-blocked, oversized, or failed provider can fall through to the next permitted provider. Cancellation does not fall through and cannot create a second answer.
| State | What the person sees | Next action |
|---|---|---|
| Ready | Provider is available now | Continue |
| Download needed | The device can obtain the model | Download, only when operator policy permits it |
| Downloading | Current model transfer progress | Keep the app open |
| Unavailable | Plain reason and the remaining chain | Update, enable, or use another permitted provider |
Onboarding shows only the next useful action. Settings shows the complete ordered chain, provider state, model identity, operating-system version, and operator policy result.
airgap.config.json controls platform, domain, locale, OS floor, model
downloads, cloud use, and provider priority.
{
"llm": {
"mode": "offline-only",
"supportDomain": "telco",
"providers": [
{
"id": "apple-foundation-models",
"enabled": true,
"priority": 0,
"platform": "ios",
"minimumOsVersion": "26.0",
"locales": ["en", "en-US"],
"allowModelDownload": false,
"allowCloudFallback": false
},
{
"id": "llama-rn",
"enabled": true,
"priority": 10,
"platform": "all",
"allowModelDownload": true,
"allowCloudFallback": false
},
{
"id": "demo",
"enabled": true,
"priority": 30,
"platform": "all"
}
]
}
}Unknown IDs, duplicate providers, explicit platform conflicts, and an empty
enabled chain fail validation. The resolver enforces minimumOsVersion against
fresh device-state data. A downloadable Android system model is not offered when
allowModelDownload is false. For a cloud entry, allowCloudFallback: false
removes it from the chosen chain.
- Airgap searches local documents before generation.
- Apple, Android, downloaded-model, and demo answers keep prompt text and output on the device during inference.
- Conversations, the action outbox, user preferences, telemetry buffers, and other application state use separate encrypted MMKV stores. Their random keys live in the platform key store.
- Telemetry is off by default and does not include customer text by default.
- Cloud generation is off until an operator enables its provider, sets up the endpoint, and installs an access-token provider.
Android ML Kit processes prompts and outputs locally, but its terms state that the APIs can contact Google for updated models, fixes, compatibility data, and performance or usage metrics. Operators must show that in user notices and store disclosures. See ML Kit terms and privacy.
The runtime can support offline FAQs, troubleshooting, policies, locations, hours, eligibility guidance, and queued service requests across the eight included industries. The examples show that the same code can load different brands, prompts, actions, and documents.
| Industry | Configuration and knowledge | Recorded example |
|---|---|---|
| Airline | examples/airline/ |
demo/industry-airline.gif |
| Banking | examples/banking/ |
demo/industry-banking.gif |
| Electric utility | examples/electric-utility/ |
demo/industry-electric.gif |
| Government services | examples/government-services/ |
demo/industry-government.gif and demo/airgap-showcase-government.gif |
| Healthcare | examples/healthcare/ |
demo/industry-healthcare.gif |
| Insurance | examples/insurance/ |
demo/industry-insurance.gif |
| Telecom | examples/telco/ |
demo/industry-telco.gif |
| Water utility | examples/water-utility/ |
demo/industry-water.gif |
An operator still owns document accuracy, identity, authorization, production actions, escalation, retention, accessibility, legal review, and device fleet testing. The examples are fixtures and do not certify industry use. In particular, Google's ML Kit GenAI terms prohibit clients directed to people under 18 and prohibit clinical practice or medical advice. Review the GenAI terms before enabling Android system AI.
flowchart LR
Q[Support question] --> R[Local document retrieval]
R --> P[Operator provider policy]
P --> A[Apple on-device model]
P --> G[Android system AI]
P --> L[Downloaded llama.rn model]
P --> C[Authenticated cloud service]
P --> D[Deterministic document answer]
A --> V[Answer card with its source]
G --> V
L --> V
C --> V
D --> V
Q --> T{Configured action route}
T -->|online| B[Authorized backend]
T -->|offline| O[Encrypted outbox]
O --> B
Models phrase retrieved information. They do not choose tools, authenticate a person, approve a sensitive action, or mutate an account. The deterministic tool router and operator backend keep those responsibilities.
The main path starts in src/services/orchestrator.ts.
The provider policy is in
src/services/inference/providerResolver.ts,
and src/components/chat/AnswerProvenance.tsx
shows the answer source, publisher, and checked date on the answer card.
| Evidence | Target | Result | Unchecked behavior |
|---|---|---|---|
| Joint and iOS GIFs | Android 15 emulator + iOS 26.4 simulator | Readiness, UI, and cited answers | Physical native providers |
| Fresh Android GIF | Android 15 emulator | Answer, queue, Outbox, and privacy checked | Android system AI or physical-device behavior |
| Eight industry GIFs | Android 15 emulator | Fixture-specific onboarding, answer, and sources checked | Production data, actions, approvals, or compliance |
| iOS native compile | Generic iOS Simulator | Foundation Models bridge compiles | Eligible physical-device runtime |
| Android debug compile | Android app, min SDK 24 | ML Kit beta2 bridge compiles | Supported AICore device runtime |
| iOS provider scenario | iOS 26.4 simulator | Native bridge, routing, answer, provenance, and UI | Apple model output or physical-device behavior |
| Android provider scenario | Android 15 emulator | Native bridge, routing, answer, provenance, and UI | AICore or Gemini Nano model output |
| Gemma 4 E2B takes | Android 15 emulator | Four takes of ten, seven, six, and five prompts on the on-device model | Phone speed, repeated runs, or production data |
| Apple host probe | Apple-silicon Mac, macOS 26 | Framework and environment availability | iPhone behavior; AI must be enabled by the owner |
Every kept app GIF records source commit, provider ID, model identity, device,
operating system, evidence class, capture command, dimensions, duration, byte
size, public playback speed, and loop review. demo/kb-studio.gif is a terminal
recording of the KB Studio tool and has no manifest entry. Label simulator and emulator footage
by its actual target, never as a physical device. Run npm run recordings:validate
to check all sixteen assets.
Provider reports add a separate class for what generated the answer:
deterministic-runtime, simulated-provider, host-native-model, virtual-device-model, or
target-device. Run
npm run providers:validate to check the scenario manifest, or follow
docs/provider-validation.md to run the full app scenario, Apple
host probe, physical-device preflight, and optional downloaded-model placement.
- Physical-device evaluation for Apple Foundation Models and Android system AI is still a release gate.
- Android Prompt API is beta, foreground-only, quota-limited, device-limited, and restricted to inputs under 4,000 tokens.
- Apple and Android system model output can change after operating-system or model updates. Prompt and retrieval evaluation must run against each supported device and model identity.
- The downloaded model is about 2.45 GB (2.28 GiB). Its latency, memory use, and answer quality are device-dependent.
- The reference server uses an in-memory rate limiter. Production deployments need durable controls, monitoring, TLS termination, and real business systems.
- Airgap is not a hosted control plane, identity provider, account system, or claim of regulatory compliance.
docs/README.mdroutes operators, app developers, backend developers, and maintainers to the right guideDEPLOYMENT.mdcovers native provider setup, signing, rollout, and rollbackCUSTOMIZATION.mdcovers brand, knowledge, actions, and configuration fieldsdocs/enterprise-integration.mdcovers identity, API, sync, and production boundariesdocs/hybrid-llm-design.mdexplains provider routing and failure handlingdocs/sync-architecture.mdexplains signed knowledge updatesdocs/tool-calling.mdexplains the deterministic action boundarydocs/safety-layer.mdexplains safety checks and their limitsdocs/support-bot-minimum.mdlists the nine controls any support bot needs before the model mattersdocs/case-study-government-assistant-launch.mdreplays one public launch failure against those controlsdocs/observability.mdlists diagnostics, telemetry fields, and privacy limitsdocs/kb-studio.mdcovers local knowledge authoring and validationdocs/recordings.mdgives the reproducible media evidence processdocs/provider-validation.mdexplains provider scenarios, host and device checks, and evidence labelsSECURITY.mdlists supported versions and private vulnerability reportingSUPPORT.mdexplains how to report a reproducible problemCONTRIBUTING.mdgives the development and test workflowROADMAP.mdlists release gates and planned work
Use GitHub Issues for reproducible bugs and scoped feature requests. Report vulnerabilities through private vulnerability reporting.
Airgap is available under the MIT License. Apple, Google, model files, and connected services keep their own terms and licenses.


