4.2 KiB
ai-gateway
ai-gateway is an internal gRPC service that turns free-form text into home
assistant actions. It asks Ollama to produce a structured intent, resolves that
intent against known Home Assistant lights, and calls ha-gateway for any
approved action.
Runtime Flow
- The service loads
.env, configures logging and telemetry, and starts gRPC onGRPC_PORT. AIService.Queryreceives prompt text and an optional model name.- The app refreshes or reads the light cache from
ha-gateway. - Ollama receives a prompt containing the user text and known lights.
- The app parses the model output as JSON intent data.
- Supported intents are executed through
ha-gateway; unsupported or invalid responses return a plain explanation without taking action.
gRPC API
Defined in proto/ai/v1/ai.proto.
AIService.Query: sends text to the AI command flowAIService.ListModels: returns model names reported by Ollama
Supported action intents currently focus on lights:
- turn on a light
- turn off a light
- list known lights
- no-op / unknown intent
Configuration
Environment variables:
| Variable | Default | Description |
|---|---|---|
GRPC_PORT |
50052 |
gRPC listen port |
OLLAMA_URL |
http://192.168.7.96:11434 |
Ollama base URL |
OLLAMA_MODEL |
llama3 |
Default model for queries without an explicit model |
OLLAMA_TIMEOUT |
120s |
HTTP timeout for Ollama calls |
HA_GATEWAY_ADDR |
ha-gateway.home-services.svc.cluster.local:50051 |
gRPC address for ha-gateway |
HA_GATEWAY_SERVER_NAME |
ha-gateway.home-services.svc.cluster.local |
Expected server name for TLS |
TLS_DIR |
empty | Enables mTLS for the server and gateway client when set |
OTEL_ENDPOINT |
empty | OTLP gRPC collector endpoint; empty disables telemetry |
LOG_LEVEL |
info |
debug, info, warn, or error |
LOG_FORMAT |
json |
json or text |
LIGHT_CACHE_TTL |
60s |
Light discovery cache lifetime |
Example env file: .env.example
When TLS_DIR is set, the directory must contain tls.crt, tls.key, and
ca.crt.
Local Run
Start ha-gateway first, then run:
cp .env.example .env
go run ./cmd/gateway
Run from ai-gateway/ so godotenv loads ai-gateway/.env.
For local plaintext development:
HA_GATEWAY_ADDR=localhost:50051
TLS_DIR=
Smoke Checks
grpcurl -plaintext -d '{"text":"list the lights","source":"local"}' \
localhost:50052 ai.v1.AIService/Query
grpcurl -plaintext -d '{}' localhost:50052 ai.v1.AIService/ListModels
Reflection is only registered when LOG_LEVEL=debug; otherwise call by using
the compiled proto descriptors or generated clients.
Test And Build
go test ./...
go build ./...
Build the container image from the workspace root:
docker build -f ai-gateway/Dockerfile -t ai-gateway:dev .
Optionally pass a build version:
docker build -f ai-gateway/Dockerfile --build-arg VERSION=$(git rev-parse --short HEAD) -t ai-gateway:dev .
Package Map
cmd/gateway/ # process entrypoint and wiring
internal/adapters/primary/grpc/ # AIService gRPC server
internal/adapters/secondary/ollama/ # Ollama HTTP client
internal/adapters/secondary/hagateway/ # ha-gateway gRPC client
internal/app/ # query orchestration and intent dispatch
internal/config/ # environment loading
internal/core/domain/ # prompt, intent, and cache types
internal/core/ports/driven/ # app-facing LLM and HA interfaces
internal/logger/ # slog setup
internal/telemetry/ # OpenTelemetry setup
Limitations
- Intent parsing depends on the selected model returning valid JSON.
- Light actions are supported; broader Home Assistant domains are not wired yet.
- The light cache is per-process memory and refreshes by TTL.
- Keep this service internal or protect it with mTLS; it does not implement separate app-layer authorization.