Helix AI
Helix is TeslaSync's optional AI layer. The brand mark (HelixMark) appears anywhere AI is in play — sidebar nav, chatbot avatar, AI feature badges, Settings → AI header.
This page is the user-facing reference. The implementation source of truth is:
internal/ai/features/registry.go— every featureweb/src/ai/features.ts— frontend mirror, generated bytools/aigeninternal/ai/provider/— provider adapter interface + 4 adaptersinternal/ai/{guard,redact,limit,audit,rag,tools,strategies,dispatch}/— runtime
Off by default. Always.
There is no global "AI on" switch. Each Helix feature is enabled individually from Settings → AI. Disabled features are invisible:
| Surface | Off-mode behaviour |
|---|---|
| HTTP route | Returns 404 Not Found (asserted by tools/aivet) |
| React route | Mounts but renders no AI UI — the withAiFeature HOC short-circuits |
| Background job | The dispatcher gate trips before execution |
| Push notifications | The push fan-out worker filters by kind + recipient mode |
These invariants are enforced in CI by a final-gate test suite (Phase-50) that walks every feature in the registry and asserts each off-mode contract.
Surfaces
| Surface | Route | Description |
|---|---|---|
| Helix Chat | /chatbot | Conversational assistant with tool-use over your fleet data |
| AI Settings | /settings/ai | Per-feature toggles, provider config, usage card, redaction controls, restore panel |
| Inline widgets | various pages | 55+ AI*.tsx widgets, each gated by withAiFeature |
The 54 user features
Grouped by intent. Every feature has a stable kebab-case ID; toggle each in Settings → AI.
Narratives & summaries
| Feature ID | What it does |
|---|---|
digest-narration | LLM narration on top of the weekly digest |
yir-narration | Year-in-review narration |
period-compare-narration | "This month vs last month" prose |
tco-narration | True cost of ownership narrative |
cost-forecast-narration | Forward-looking charging cost narrative |
battery-health-forecast-narrative | Battery degradation outlook |
cabin-temperature-impact-narrative | Cabin-temp impact on range / comfort |
vampire-drain-explanation | Why your car drank kWh while parked |
Natural-language builders
| Feature ID | What it does |
|---|---|
nl-alert-builder | Type a sentence → draft an Alert Studio rule |
nl-automation-builder | Type a sentence → draft an automation |
nl-dashboard-composer | Compose a dashboard from prose |
nl-grafana-panel | Compose a Grafana panel from prose |
nl-sql-playground | Natural-language → SQL against the warehouse |
nl-drive-search-replay | "Find the drive where I went over 90" |
nl-search | Global NL search across fleet entities |
signal-explorer-nl-filter | NL filter for the signal explorer |
Predictions & ML
| Feature ID | What it does |
|---|---|
range-prediction-model | Range prediction under stated conditions |
predictive-maintenance | Maintenance prediction from telemetry trends |
smart-charge-schedule-suggestion | Schedule based on rates + departure |
preheat-precool-recommender | When to pre-condition before a drive |
charging-curve-fingerprint-clustering | Cluster sessions by curve shape |
ml-charging-curve-clustering | ML variant with embedding similarity |
learned-per-vehicle-anomaly-baselines | Per-VIN normal-range learning |
Explainers & coaching
| Feature ID | What it does |
|---|---|
drive-coaching | Per-drive efficiency coaching |
safety-setting-explainer | "Why is this safety setting on?" |
anomaly-explanations | Plain-language anomaly explanations |
mqtt-sse-inspector-explanations | What does this MQTT / SSE event mean? |
state-machine-debugger-narrator | Explain a state transition |
log-trace-summarization | Summarise a log or trace span |
software-update-changelog-summarizer | Concise summary of a Tesla changelog |
incident-timeline-summarizer | Timeline summary of an incident |
charging-diagnosis | Diagnose a slow / failed session |
speed-profile-insights | Insights from the speed distribution |
route-efficiency-suggestions | Suggest a more efficient route |
tire-pressure-trend-reasoning | Reason over tyre pressure trends |
Automation & operations
| Feature ID | What it does |
|---|---|
alert-tuning-suggestions | Suggest threshold / cooldown tweaks |
cross-rule-conflict-detection | Find rules that fight each other |
quiet-hours-suggestion | Suggest quiet-hours windows |
inbox-auto-categorization | Categorise inbox / notifications |
feedback-queue-triage | Triage the feedback queue |
data-repair-suggestions | Suggest data-repair actions |
geofence-aware-automation-suggestions | Suggest automations from geofences |
suggest-new-geofences | Suggest new geofences from clusters |
auto-name-unnamed-locations | Name locations from context |
auto-trip-naming | Name trips from route + endpoints |
Multimodal & misc
| Feature ID | What it does |
|---|---|
voice-mode | Voice-driven assistant mode |
watch-face-nl-response | NL response surface for the watch face |
trip-planner-llm-agent | LLM agent for trip planning |
trip-postcard-share-card-image-generation | Generated share-card image for a trip |
vehicle-paint-preview | Image-gen vehicle paint preview |
pii-redaction-shared-exports | LLM-assisted PII redaction for shared exports |
rag-help | RAG-backed in-app help |
lifetime-stats-qa | Q&A over your lifetime stats |
chatbot-llm | The Helix Chat backend |
Ops-only meta-features (3)
| Feature ID | What it does |
|---|---|
__usage__ | AI Usage Card — per-call audit log + spend |
__redaction_bypass__ | Per-(feature, provider) redaction-bypass report |
ai-provider-health | Diagnostic — which adapter is active and what can it do |
The __double_underscore__ IDs are not toggleable per feature; they gate on ai_mode != 'off'.
Providers
Helix talks to LLMs through a small adapter interface (internal/ai/provider/provider.go). Four production adapters ship in-tree plus a mock adapter for tests:
| Adapter | Use cases |
|---|---|
openai | OpenAI hosted models (gpt-4o, gpt-4o-mini, gpt-4.1, …) |
azure | Azure OpenAI deployments (same protocol, different auth + URLs) |
anthropic | Claude models (Sonnet, Opus, Haiku, …) |
ollama | Self-hosted models via Ollama — fully local |
Per-feature provider selection
Provider choice resolves with this precedence (highest wins):
- Per-feature override — set the provider for a specific feature (e.g. use Claude for
drive-coaching, GPT-4o-mini for everything else). - Mode default — the globally configured default for the current
ai_mode. - No provider — the feature stays off.
See ResolveProviderName in internal/ai/provider/config.go.
Decorator chain
Every adapter call is wrapped by decorators in this order (outermost first):
- Trace — OpenTelemetry span with feature ID, provider, model
- Audit — write request / response metadata to the audit log
- Cost — compute spend from token counts × per-model price table (
internal/ai/cost/cost.go) - Rate-limit — per-provider concurrency cap; tripped requests get back pressure, not silent failure
- Redact — outbound PII redaction; bypasses are logged for the bypass report
Result: nothing reaches the network without an audit row and a redaction pass.
Provider health (Ollama)
The Ollama health prober (internal/ai/health/ollama_poll.go) polls the local endpoint periodically. If Ollama goes unreachable, the prober suspends the ollama provider in the rate-limiter so requests fail fast with a clear error instead of hanging. The ai-provider-health feature exposes the current adapter snapshot for ops debugging.
RAG (Retrieval-Augmented Generation)
Features marked NeedsRAG=true in the registry retrieve relevant chunks from the pgvector index before calling the provider. The chunk store and the embedding model are configurable; see internal/ai/rag/.
Tools (function calling)
Features marked NeedsTools=true can invoke functions on the server. The tool registry lives at internal/ai/tools/:
- Each tool has a typed input schema (reflected from the Go DTO) and a typed output.
- The dispatcher (
internal/ai/dispatch/) validates the model's proposed arguments against the schema before running the tool — no schemaless calls reach state-mutating code. - Multiple tool calls per assistant turn are supported (OpenAI, Azure, and Anthropic all allow it). Every call is round-tripped through the conversation history so the next turn sees the result.
Streaming
Features marked NeedsStream=true deliver tokens through SSE via the provider's streaming endpoint. The shared streaming layer lives at internal/ai/stream/.
Audit, usage, cost
The AI Usage Card surfaces:
- Today — token counts, requests, cost, top features
- By feature — per-feature breakdown over the selected window
- Recent — last N calls with feature, provider, model, latency, tokens, cost, and redaction status
Cost is computed locally from the per-model price table; no provider call is needed to price a request.
Redaction
The redact decorator runs against every outbound payload, replacing well-known PII surfaces (VINs, emails, GPS coordinates outside the relevant operation, addresses) with stable token placeholders. Each (feature, provider) pair has a configurable allow-list for fields that legitimately need the raw value. Per-(feature, provider) bypass events are written for the __redaction_bypass__ report.
Restore
The AI Restore Panel (Settings → AI) lets you replay a past AI response from the audit log without re-paying the provider. Useful when iterating on a prompt or recovering a lost narration.
Adding a new Helix feature
The contract is:
- Add a
Featureentry tointernal/ai/features/registry.gowithDefaultOn: false, populatedRoutes, and the right capability flags. - Implement the backend strategy under
internal/ai/strategies/<feature-id>/strategy.gowith agoldens.yamlfixture set. - Wire the handler under
internal/api/ai_<feature_id>_handler.goand mount it insideinternal/api/ai_routes.gousingg.Wrap("<feature-id>", handler). - Add the React component under
web/src/components/ai/AI<FeatureName>.tsxwrapped withwithAiFeature('<feature-id>'). - Run
make generate(orgo run ./tools/aigen) to regenerateweb/src/ai/features.ts. - CI will fail unless:
tools/aivetfinds the route is wrapped byg.Wrap.tools/aigen --checkfinds the frontend mirror is in sync.- The off-mode invariant tests pass for the new feature.
Configuration
See Configuration → AI for every environment variable. The short version: each provider needs an API key (or, for Ollama, a reachable base URL), and a default model. Per-feature overrides live in the database (Settings → AI writes them).
Where Helix is in the UI
- Sidebar — the Helix entry (purple) deep-links to
/chatbot. - Settings — Settings → AI owns toggles, providers, audit, restore.
- Inline — wherever you see an
HelixMarkglyph or a "Generate with Helix" button. Each is governed by exactly one feature ID in the registry.
Acknowledgements
Helix builds on standard provider SDKs and the open Ollama project. The runtime contract (off-by-default, audited, redacted) is described in ADR-015.