Skip to content

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 feature
  • web/src/ai/features.ts — frontend mirror, generated by tools/aigen
  • internal/ai/provider/ — provider adapter interface + 4 adapters
  • internal/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:

SurfaceOff-mode behaviour
HTTP routeReturns 404 Not Found (asserted by tools/aivet)
React routeMounts but renders no AI UI — the withAiFeature HOC short-circuits
Background jobThe dispatcher gate trips before execution
Push notificationsThe 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 ​

SurfaceRouteDescription
Helix Chat/chatbotEvidence-first fleet agent with cross-domain tool use, app knowledge retrieval, and visible provenance
AI Settings/settings/aiPer-feature toggles, provider config, today's usage and seven-day per-feature spend, restore panel
Inline widgetsvarious pages55+ AI*.tsx widgets, each gated by withAiFeature

The 56 user features ​

Grouped by intent. Every feature has a stable kebab-case ID; toggle each in Settings → AI.

Narratives & summaries ​

Feature IDWhat it does
digest-narrationLLM narration on top of the weekly digest
yir-narrationYear-in-review narration
period-compare-narration"This month vs last month" prose
tco-narrationTrue cost of ownership narrative
cost-forecast-narrationForward-looking charging cost narrative
battery-health-forecast-narrativeBattery degradation outlook
cabin-temperature-impact-narrativeCabin-temp impact on range / comfort
vampire-drain-explanationWhy your car drank kWh while parked

Natural-language builders ​

Feature IDWhat it does
nl-alert-builderType a sentence → draft an Alert Studio rule
nl-automation-builderType a sentence → draft an automation
nl-dashboard-composerCompose a dashboard from prose
nl-grafana-panelCompose a Grafana panel from prose
nl-sql-playgroundNatural-language → SQL against the warehouse
nl-drive-search-replay"Find the drive where I went over 90"
nl-searchGlobal NL search across fleet entities
signal-explorer-nl-filterNL filter for the signal explorer

Predictions & ML ​

Feature IDWhat it does
range-prediction-modelRange prediction under stated conditions
predictive-maintenanceMaintenance prediction from telemetry trends
smart-charge-schedule-suggestionSchedule based on rates + departure
preheat-precool-recommenderWhen to pre-condition before a drive
charging-curve-fingerprint-clusteringCluster sessions by curve shape
ml-charging-curve-clusteringML variant with embedding similarity
learned-per-vehicle-anomaly-baselinesPer-VIN normal-range learning

Explainers & coaching ​

Feature IDWhat it does
drive-coachingPer-drive efficiency coaching
safety-setting-explainer"Why is this safety setting on?"
anomaly-explanationsPlain-language anomaly explanations
mqtt-sse-inspector-explanationsWhat does this MQTT / SSE event mean?
state-machine-debugger-narratorExplain a state transition
log-trace-summarizationSummarise a log or trace span
software-update-changelog-summarizerConcise summary of a Tesla changelog
incident-timeline-summarizerTimeline summary of an incident
charging-diagnosisDiagnose a slow / failed session
speed-profile-insightsInsights from the speed distribution
route-efficiency-suggestionsSuggest a more efficient route
tire-pressure-trend-reasoningReason over tyre pressure trends

Automation & operations ​

Feature IDWhat it does
alert-tuning-suggestionsSuggest threshold / cooldown tweaks
cross-rule-conflict-detectionFind rules that fight each other
quiet-hours-suggestionSuggest quiet-hours windows
inbox-auto-categorizationCategorise inbox / notifications
feedback-queue-triageTriage the feedback queue
data-repair-suggestionsSuggest data-repair actions
geofence-aware-automation-suggestionsSuggest automations from geofences
suggest-new-geofencesSuggest new geofences from clusters
auto-name-unnamed-locationsName locations from context
auto-trip-namingName trips from route + endpoints
alert-message-template-suggestionPropose a notification message template for Alert Studio
alert-pack-builderPropose a goal-based custom Alert Pack

Multimodal & misc ​

Feature IDWhat it does
voice-modeVoice-driven assistant mode
watch-face-nl-responseNL response surface for the watch face
trip-planner-llm-agentLLM agent for trip planning
trip-postcard-share-card-image-generationGenerated share-card image for a trip
vehicle-paint-previewImage-gen vehicle paint preview
pii-redaction-shared-exportsLLM-assisted PII redaction for shared exports
rag-helpRAG-backed in-app help
lifetime-stats-qaQ&A over your lifetime stats
chatbot-llmThe Helix Chat backend

Ops-only meta-features (3) ​

Feature IDWhat it does
__usage__AI Usage Card — per-call audit log + spend
__redaction_bypass__Per-(feature, provider) redaction-bypass report
ai-provider-healthDiagnostic — 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:

AdapterUse cases
openaiOpenAI hosted models (gpt-4o, gpt-4o-mini, gpt-4.1, …)
azureMicrosoft Foundry OpenAI v1 only ({resource}.services.ai.azure.com/openai/v1 or {resource}.openai.azure.com/openai/v1). Select Auto, Chat Completions, or Responses. No model-name routing or older API surfaces.
anthropicClaude models (Sonnet, Opus, Haiku, …)
ollamaSelf-hosted models via Ollama — fully local

Set Deployment name to the exact portal deployment name. The optional Embedding deployment name is independent of the chat deployment. Both use the same Foundry v1 base URL and API key; the persisted provider key remains azure, so existing credentials and feature-provider selections are preserved. Resource-root URLs automatically receive /openai/v1; /models, deployment-path URLs, queries, and other API paths are rejected rather than routed elsewhere.

API protocol defaults to Auto: Chat Completions first, then one Responses attempt only on structured operation-not-supported / not-found errors. Chat Completions and Responses call only the selected API, without fallback. The selection is persisted as api_protocol (auto, chat_completions, or responses) and is used by validation and Helix Chat/Stream identically. Embeddings always call /openai/v1/embeddings, regardless of chat protocol.

Existing configuration migration: obsolete flavor, api_version, deployment, and embedding_deployment fields are not part of the adapter. For entries without api_protocol, the configuration-read boundary promotes a previously effective chat deployment override into model (a stale override from a Foundry-flavor entry is ignored, preserving its existing model identity). An embedding override is promoted into embedding_model. The settings form displays these effective names and removes obsolete keys on Save. Modern entries with api_protocol ignore obsolete override keys. No legacy routes or model-specific heuristics remain. Review the visible names and endpoint before saving.

Validate uses a 30-second timeout and an explicit 1,024-output-token Azure probe budget (including reasoning tokens). Normal requests keep their caller-supplied token budget.

Auto makes at most two attempts and never changes the configured API base. Authentication, rate-limit, server, and token-budget failures do not trigger fallback; if both protocols fail, both errors are retained. The dispatcher does not replay a finalized Azure failure as another Chat call. Responses requests send store: false and replay tool calls/results, encrypted reasoning items, and assistant message phases explicitly between tool turns. Opaque continuation state is kept only in memory, not serialized into saved history or client responses. Existing content redaction still applies. Responses fallback streaming is buffered, not token-by-token SSE: Helix receives text/tool chunks followed by one terminal event after completion. Failed, incomplete, refused, and empty Responses results are errors, not success. Chat Completions also rejects malformed/empty completions and unfinished streams; truncated or filtered tool calls are never executed. Cancellation closes the upstream stream, including when the downstream client stops accepting output.

Protocol references: Azure Responses API and Azure OpenAI v1 lifecycle.

Per-feature provider selection ​

Provider choice resolves with this precedence (highest wins):

  1. Per-feature override — set the provider for a specific feature (e.g. use Claude for drive-coaching, GPT-4o-mini for everything else).
  2. Mode default — the globally configured default for the current ai_mode.
  3. No provider — the feature stays off.

See ResolveProviderName in internal/ai/provider/config.go.

Settings → AI shows audited per-feature calls, input/output tokens, and estimated cost over the last seven days, ordered by cost. The daily cost cap, when set, applies to all Helix calls combined; feature toggles are opt-ins, not individual cost caps. Provider/model labels come from the latest matching call among the 50 most recent audited calls, not from the seven-day aggregates. Features without such a recent call have no provider/model attribution in this view. Usage queries are disabled while Helix is off.

Decorator chain ​

Every adapter call is wrapped by decorators in this order (outermost first):

  1. Trace — OpenTelemetry span with feature ID, provider, model
  2. Audit — write request / response metadata to the audit log
  3. Cost — compute spend from token counts × per-model price table (internal/ai/cost/cost.go)
  4. Rate-limit — per-provider concurrency cap; tripped requests get back pressure, not silent failure
  5. 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/.

Helix Chat uses an embedded corpus of maintained TeslaSync documentation. A local BM25-style retriever ranks that corpus in process, so product questions remain grounded without provider embeddings, a populated pgvector index, or the separate rag-help feature toggle. Retrieved passages include source paths that Chat can cite in its answer.

Grounding and evidence ​

Every strategy runs under the shared Helix intelligence contract. It requires fleet-specific factual claims to come from tool results or context supplied in the current run, while preserving the output format requested by each feature. Helix calls out missing, stale, sparse, or conflicting evidence instead of filling gaps from model priors. It provides concise rationale, not hidden chain-of-thought.

The shared streaming UI retains a privacy-safe execution trail: tool name, running/succeeded/unavailable status, successful source count, and terminal token usage. Tool arguments and raw result payloads are deliberately excluded from this shared metadata because they can contain locations, VINs, or other fleet details.

Helix Chat can discover safe vehicle summaries and use all twelve core read-only fleet tools: vehicle state and location, battery status, drives and drive detail, charging sessions and charge detail, active and recent alerts, geofences, and period efficiency. It can chain these sources for cross-domain analysis. Questions about TeslaSync itself use the chatbot-scoped application knowledge retriever and cite only sources returned by retrieval.

Response voice and evaluations ​

Every language-producing Helix surface follows one voice contract: warm, observant, and precise. Responses lead with the most useful supported observation, fit their shape to the question, and stay honest about what TeslaSync knows. Grounded semantics always win over style — a pretty sentence with an invented fact fails review, and so does technically valid monotony.

Severity and surface set the tone, never the other way around:

  • Informational moments may be memorable and specific to the event.
  • Warnings stay sharp and restrained; critical conditions stay urgent but calm, with the condition unmistakable and a safe next step where one exists.
  • Safety, compact (voice/watch), and privacy-control surfaces keep their exact meaning and length contracts; no jokes soften warnings and no desktop narrative formatting leaks into glanceable surfaces.
  • Builders and other proposal surfaces put personality in the explanation only: the structured draft the user reviews stays exact.

When AI is off or a feature is disabled, the deterministic baseline remains the product: template digests, manual Alert Studio forms, typed search filters, and the existing CRUD pages. AI panels are absent from the DOM; AI routes return 404; background jobs and push fan-out stay gated.

Response quality is verified two ways. Deterministic checks (always runnable offline) assert tool sequencing, schema/placeholder validity, scope bindings, redaction, and that each goldens.yaml evaluates the production prompt it is pinned to (see TestGoldenPromptMatchesProduction in every strategy test):

bash
go test ./internal/ai/... ./cmd/ai-eval/...
go run ./cmd/ai-eval --all            # canned mock provider, zero network egress
go run ./cmd/ai-eval --feature digest-narration
go run ./tools/aivet                  # registry / route / guard coverage

Editorial quality (grounding, relevance, tone, concision, creative variety) is scored per-feature by the judge_rubric blocks in each goldens.yaml, either by the LLM judge (ai-eval --all --judge, needs JUDGE_PROVIDER + JUDGE_API_KEY) or by human review of before/after outputs on the same fixture. Canned fixtures prove deterministic contracts only — hand-authored fixture prose is never evidence that a live model writes well.

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.
  • Provider-specific streaming fragments are assembled into complete, schema-valid tool calls before execution. Partial JSON never reaches a tool.

Streaming ​

Features marked NeedsStream=true deliver tokens through SSE via the provider's streaming endpoint. Deltas are forwarded as they arrive rather than materializing a complete response and replaying it as one chunk. A stream that closes without a terminal frame is reported as incomplete. 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:

  1. Add a Feature entry to internal/ai/features/registry.go with DefaultOn: false, populated Routes, and the right capability flags.
  2. Implement the backend strategy under internal/ai/strategies/<feature-id>/strategy.go with a goldens.yaml fixture set.
  3. Wire the handler in its carved subpackage at internal/api/ai<slug>/handler.go (one directory per feature, e.g. internal/api/aialerttune/handler.go) and mount it inside internal/api/ai_routes.go using g.Wrap("<feature-id>", handler).
  4. Add the React component under web/src/components/ai/AI<FeatureName>.tsx wrapped with withAiFeature('<feature-id>').
  5. Run make generate (or go run ./tools/aigen) to regenerate web/src/ai/features.ts.
  6. CI will fail unless:
    • tools/aivet finds the route is wrapped by g.Wrap.
    • tools/aigen --check finds 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 HelixMark glyph 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.

Self-hosted Tesla intelligence · MIT licensed · Privacy policy