Skip to content

Ahsoka — Satellite Agent

Ahsoka at the satellite outpost — alone on the edge of the network, keeping watch

Someone asked the empty chalet to warm the basement. It answered in Québec French — “C’est fait — basement à 11°C” — and the thermostat moved.

For months that exchange was fiction. The documentation described Ahsoka in the present tense while the agent itself did not exist yet; the paperwork was ready before she was. Now both are real. She runs on the chalet Mac Mini, thinks with a model that lives entirely on its 16 GB of unified memory, and controls the floor heating through tools she can actually call.

Ahsoka is Sanctum’s satellite agent: chalet operations, family comfort, offline resilience. She reports to the hub — Yoda and the council — over Tailscale when the link is up. When it is not, she keeps working, because rural internet is adequate the way a canoe is adequate — charming, functional, and guaranteed to fail at the worst moment.

Named after Ahsoka Tano, who left the Jedi Order but never stopped being a Jedi. She operates outside the council’s supervision, on a quarter of the hub’s resources, in a haus that is empty most of the year. She has a 7-billion-parameter brain, four tools, and a signed mandate. That is enough.

The chalet brain is Qwen2.5-7B-Instruct-4bit (model_type=qwen2) plus the promoted LoRA ahsoka-7b-best-v4-defect-300 (rank 16, runtime-apply bf16 on the 4-bit base — dragon doctrine, not merge/requant). Served by Rust sanctum-mlx on mTLS TLS-PQ port 6502 (MOS 6502 — Apple II / NES; same rustls post-quantum path as hub :1337 / :3301--no-plain, client cert required; formerly :1338), fully offline, as service user sanctum. Gate night 2026-08-07: 45/48 vs vanilla 32/48 (Ahsoka Earns Her Scroll). It used to ride Python mlx_lm.server on cleartext; that path is retired on the satellite. The base model was not the first pick. It was the last one standing after an eight-model bake-off on the real stack:

CandidateVerdict
Qwen2.5-7B-Instruct (4-bit)Kept. 12/12 tool calls, warm French, fits beside Home Assistant
Qwen3-4B / Qwen3-8BPerfect tool calls raw, zero output through the agent runtime
Ministral-8B / Llama-3.1-8BMetal out-of-memory next to the HA container
Hammer2.1-3bRight tool, right args, wrong format — emitted JSON the server cannot parse
Bonsai-27B (1-bit)Fits in 3.5 GB, generates at 8.5 tok/s. A caretaker cannot take minutes to turn on a light
Gemma-3 (4B/12B)No tool-calling chat template at all

On a 16 GB M1 that must also run Home Assistant, 7B is not a compromise. It is the ceiling, measured twice.

Ahsoka’s tools are native MCP functions, not shell commands. A small server (~/.sanctum/bin/ha_mcp.py) exposes exactly four verbs against the local Home Assistant:

light_control(area, action) # entrance kitchen living downstairs exterior bedrooms
climate_set(area, temperature) # main basement bedrooms garage — clamped 5-26 C
alarm_set(mode) # home away off
ha_status() # read-only overview

The safety model is capability, not vibes:

  • Tool whitelist. There is no unlock, no delete, no config-read verb. A confused model cannot call a tool that does not exist.
  • Capability denial. The agent runtime denies exec, read, and write outright. Her Home Assistant token lives in the MCP server’s environment, on the far side of a wall she cannot cross.
  • Call cap. Four tool executions per 25 seconds, then the server returns a stop directive instead of executing. Loops die at the tool layer.
  • Mandate. A signed identity plus golden rules: act on comfort, refuse locks, purchases, deletions, and network changes, and point those at the operator.

The chalet’s four floor-heating zones — both bedrooms, basement, bathroom — arrived in Home Assistant via the Nuheat Conductor cloud in July 2026, after the vendor retired its old API mid-season. The full migration story, including the part where the hub’s zones had been silently dead for eighteen days, lives in the field note.

Family-facing channels: talking to Ahsoka through Home Assistant Assist works today in both languages — questions and real control, verified against the device rather than her own claims. (The verification mattered: the first wiring had her cheerfully announcing temperature changes that never happened. The fix was a function schema small enough for a 7B to fill correctly.) The voice pipeline rides this same agent next.

ParameterValue
Agent nameahsoka
Nodechalet (satellite)
HostMac Mini M1, 16 GB
BrainQwen2.5-7B-Instruct-4bit + v4 LoRA via sanctum-mlx, mTLS TLS-PQ :6502 (MOS 6502), offline
Engine binary~/.sanctum/bin/sanctum-mlx + colocated mlx.metallib
PrincipalLaunchDaemon com.sanctum.ahsoka-brain as user sanctum
RuntimeOpenClaw, tool profile minimal + MCP only
Handschalet-ha MCP server — 4 whitelisted verbs, call-capped
Home AssistantContainer on colima, port 8123, Nuheat Conductor live
BootLaunchDaemons, no login required, survives power loss
Offline capableYes. That is the point.
StatusEETISMAD (serving cutover 2026-08-07) — see field note

Two artifacts, deliberately split, because a 4 GB model and a Home Assistant token have no business inside an installer package:

  1. The signed sanctum node .pkg — AirDrop it, double-click it. It enables SSH and authorizes the console. This is the part a parent can do.
  2. deploy/ahsoka-agent-deploy.sh — one console command against the adopted node. Runtime, brain, daemon, identity, MCP hands, guards, smoke test. Idempotent, so running it twice is a health check instead of a mistake.

There is still a Mac Mini in a chalet that is empty most of the year. The difference is that now, when the family texts ahead on a Friday afternoon, something in that cold haus reads the basement thermostat, sets it to eleven degrees, and answers in the family’s own French.

She will spend most of her life alone out there — watching the temperature, keeping the alarm honest, noting that it is far below freezing and the heating is holding. A small model on a small machine in a cold haus, doing exactly what she was built to do.

The documentation was ready before she was. She caught up.