Jev Assist

September 19, 2026 · View on GitHub

Home Assistant custom conversation agent: Jev (TypeSafe System One, jev-latest) classifies an utterance, then either calls a light / climate / cover service (fast path) or hands off to the SpaceXAI Grok conversation agent.

Install (HACS)

  1. HACSCustom repositories
  2. URL: https://github.com/luxus/ha-conversation-jev — category Integration
  3. Download Jev Assist, then restart Home Assistant
  4. Settings → Devices & services → Add integration → Jev Assist

Manual install: copy custom_components/jev_assist/ into your HA config/custom_components/ folder and restart.

Configuration

  1. TypeSafe / Jev API key (required, from typesafe.ai; the same key if issued via Vercel) — stored on the config entry, not in configuration.yaml.
  2. Grok (primary): Sign in with Grok (uses Grok CLI OAuth client)
    Device-code + PKCE against https://auth.x.ai via shared package ha_spacexai_auth (start_device_auth / poll_token / ensure_fresh) using the public Grok CLI client_id b1a00492-073a-47ea-816f-4c329264a828 (verified against xai-org/grok-build crates/codegen/xai-grok-login/src/config.rs). Home Assistant shows a URL and user code, polls the token endpoint, and stores access + refresh tokens. Setup/reload calls ensure_fresh (refresh only near expiry). If the IdP rotates the refresh token, the new one is persisted.
  3. Grok (optional fallback): API key for https://api.x.ai when OAuth entitlement is missing or you bill via console.x.ai.

This integration does not use Home Assistant Application Credentials.

After setup, pick Jev Assist as the conversation agent in an Assist pipeline.

What it does

  • Jev questions (DE/EN) live in criteria.py and are sent in one typesafe-sdk AsyncTypeSafeClient.system_one call (jev-latest, explicit RetryPolicy(max_retries=2) / 10s timeout). State is a named JSON object: utterance, language, exposed_entities, areas.
  • Router kinds: fast_service | grok | reject (gates in CONTRACT.md / const.py: FAST_MIN_CONFIDENCE=0.80, NOUL_YES_THRESHOLD=0.55, NOUL_UNSURE_LOW=0.40).
  • Fast path domains: light (turn_on / turn_off / toggle / set_brightness), climate (set_temperature / turn_on / turn_off / set_hvac_mode), cover (open / close / stop / set_position / set_tilt). Maps live in light_map.py, climate_map.py, cover_map.py.
  • Multi-area same action: „alle Lichter in Schlafzimmer und Flur“ / “all lights in bedroom and hallway” stays fast_service (union of Assist-exposed lights in those rooms only), even if Jev marks is_compound.
  • Whole-home safety: target_area=none never fires all exposed entities of a domain. Confident scope=whole_home is treated the same (does not use a single-room Choice). Needs a name-token match, an explicit area, two or more named areas, or exactly one Assist-exposed entity of that domain for simple on/off-style actions.
  • Grok path: conversation.async_converse to conversation.spacexai_grok (GROK_HANDOFF_AGENT_ID; override with config-entry grok_handoff_agent_id). No TTS/STT/chat stack inside Jev.

Tests

pip install -r requirements-dev.txt
pytest

Router tests mock Jev; no live API keys are required.