- matrix-relay/relay.py: handle the `i2c` command → Bridge.call("i2c_scan").
- config.template: allow + auto-approve i2c_scan on the default risk profile.
- modulino skill: point "confirm a module is present" at i2c_scan (MCU Qwiic
bus) instead of the Linux i2cdetect.
Completes the container-native path: the three canned prompts (list I2C /
matrix pattern / scroll text) all run through the RouterBridge responder —
no /dev/i2c, no flash — so they work in the App Lab container node.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Make `default` the sole enabled agent in the template so a freshly
provisioned board matches the runtime: web, chat, Refine, and Telegram all
land on the same fully-loaded agent. cloud/local/chaos stay defined (for
opt-in demos of cloud-only / offline / outage) but ship disabled.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The agent now drives the matrix in <1s via the resident responder instead of
compiling+flashing a sketch (~95s). Pieces:
- matrix-relay/: a tiny container (python-apps-base) running relay.py — a
TCP:9999 → RouterBridge relay. The ZeroClaw daemon runs on the host for
hardware access, but the RouterBridge python binding (arduino.app_utils)
only ships in the App Lab image, so JUST the relay runs containerized,
mounting the router socket + publishing :9999 to loopback.
- config.template.toml: add matrix_pattern + matrix_text to the default risk
profile's allowed_tools/auto_approve (the capability filter hides tools not
listed — this was why matrix_text wasn't exposed to the agent).
- skills/led-matrix: lead with "use matrix_text / matrix_pattern first"; only
flash for custom frames (flashing overwrites the responder). NOTE skills load
from each agent's workspace copy, not shared/skills — push to all workspaces.
- provision-host-daemon.sh: flash the responder once + start the relay.
Proven on-hardware: "show a heart" and "scroll GO CLAWS" both instant via the
agent, no flash.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Replaces the never-executed "LiteRT-LM on UNO Q 4GB" spike plan with a
measured record of the local-fallback path we actually run.
Measured on board 65301572 (Qwen2.5-0.5B-Instruct, -c 8192, 4 threads),
using llama-server's own timings rather than wall clock:
prefill ~17-20 tok/s (linear), decode ~6-11 tok/s (degrades with KV)
warm prefix-cached tool call: 3.8s, 6/6 correct structured calls
Two findings that changed the deployment:
1. The board had drifted onto Qwen2.5-Coder-1.5B - larger and tuned for
the wrong task. Reverting to the repo's 0.5B made tool calls ~6x
faster (24s -> 3.8s) and freed ~700MB. The repo was right.
2. The harness, not the model, was the bottleneck. The default agent
profile sent a 4718-token prompt (~4.6 min prefill) and the client
cancelled before the model could answer. A lean runtime profile cuts
that to 706 tokens, lifts prefix-cache match 0.435 -> 0.966, and
completes a full agentic turn with a real tool call in 11s warm.
The ZeroClaw text parser was never at fault.
Prompt cost model for budgeting profiles: ~706 base (1 tool),
~244/additional tool, +315 for uno_q_flash (schema + flash imperative),
~53/skill in compact mode.
Also standardises context on -c 8192 across all three provisioning paths
(a 16k window costs ~16 min to fill at this speed and doubles KV for
nothing), and fixes stale references to the deleted src/lib/harness.ts.
Adds bench-prefill.sh and bench-tools.py as reproducible baselines.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Folds the last unmerged workshop work into main:
- ResiliencePanel — the failure-injection 'theater' UI (cloud outage → on-board
Qwen live demo) that visualizes the [agents.chaos] (custom.dead → llamacpp)
failover, plus Module2 integration + api/nodes support.
- build-deploy.sh — one-command aarch64-musl cross-build + adb deploy helper,
REFRESHED for 0.8.3: adds the web SPA prebuild step and the full feature set
(hardware, peripheral-rpi, embedded-web, gateway-voice-duplex) + the
embedded-web/web_dist_dir gotcha.
Config conflict resolved as a union: the branch's custom.dead + [agents.chaos]
demo blocks alongside this session's channels/voice/skills/risk-profile edits.
Verified: tsc clean, web 229 + api 58 tests green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Vendors the comprehensive UNO Q skill (SKILL.md + 7 references/*.md) and installs
it into EVERY agent's workspace on each board, so agents know this board's
specifics (dual-brain arch, Bridge/RPC, pin tables, LED matrix + the
ArduinoGraphics-not-installed gotcha) instead of guessing generic Arduino.
Why per-agent workspace: ZeroClaw's read_skill returns only SKILL.md; the agent
reads references/*.md via the workspace-sandboxed file_read tool, so references
are only reachable under ~/.zeroclaw/agents/<alias>/workspace/skills/. A
shared/skills bundle surfaces the skill but its references get sandbox-blocked.
- push-skill.sh installs a SKILL.md+references skill into every agent workspace
(discovers aliases from the board); provision-fleet runs it per board.
- config.template risk profile now allows + auto-approves read_skill + file_read
so agents load skills without a human approver (webhook path is non-interactive).
- Flattened the folded 'description: >-' to single-line (ZeroClaw's frontmatter
parser is a flat scanner, not full YAML).
Verified on board 65301572 with cloud/Sonnet-5: discovered arduino-uno-q →
read_skill(SKILL.md) → file_read references/04-bridge-rpc.md → correct
board-specific answer citing the file.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Boards now boot LAN-open (host 0.0.0.0, allow_public_bind, require_pairing=false)
so a team reaches its node's embedded ZeroClaw dashboard + web chat directly by
IP with no token — the 'Open your node' path. Two more modalities ride the same
default (cloud-first) agent:
- Telegram: config seeds [channels.telegram.default] disabled + pre-bound to the
default agent; a team enables it from the dashboard by pasting a @BotFather
token. Dashboard writes only set pending_reload, and /admin/reload is
loopback-only, so a new zeroclaw-reload-watcher.sh (loopback) applies dashboard
config edits within seconds — no shell. provision-fleet pushes + launches it.
- Lockdown: zeroclaw-lockdown.sh flips require_pairing=true, reloads, and mints a
pair code (open -> locked harden step); documented as a board/adb action since
minting + reload are loopback-only.
- Voice: seeds a commented [channels.voice_duplex.default] + documents the
aarch64 build (embedded-web + gateway-voice-duplex); build/hardware work is
separate.
Onboarding scripts (apess-selfregister.sh, provision-uno-q.sh) now tolerate
open-boot: when the gateway mints no pair code, they announce with a placeholder
token (the open board ignores auth) instead of hard-failing.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Prototype #1 of the APESS innovation set: make the Uno Q's unique story —
a real LLM running on the board — visible and demonstrable. A team can
inject a cloud outage and watch their agent keep reasoning on the on-board
Qwen, which is exactly ADD Layer 4 (failure modes) / Layer 5 (edge vs cloud)
made concrete instead of merely documented.
- New `fallback` NodeActivityKind (api + client, kept in sync). `mapNodeEvent`
now recognizes ZeroClaw's failover log lines ("ModelProvider call failed",
"Exhausted retries, trying next model") and surfaces them as a first-class
resilience signal — NOT swallowed by the generic error branch. Rendered in
a distinct rose in the board-activity feeds.
- ResiliencePanel (Module 2): a "Simulate cloud outage" button that routes a
prompt through the board's new `chaos` agent; streams the live failover and
shows a "survived" banner when a fallback is followed by a response. Sim mode
plays a deterministic failover so it demos with zero hardware.
- Board config: a `chaos` agent backed by a deliberately-dead cloud endpoint
(:9099) with `fallback = ["llamacpp.local"]`, so the outage is deterministic
and workshop-safe (no tunnel-hacking, no real cloud to kill).
Tests: api 34, front-end 191 (+ResiliencePanel), typecheck clean, build passes.
Live-on-board validation pending (board USB link down at commit time).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Codify the verified board setup into a repeatable kit under deploy/uno-q/:
- config.template.toml — the tested node config: cloud / cloud+fallback /
on-board-Qwen providers, three agents (default / cloud / local) on the
hardware risk profile, gateway, peripherals. Secrets stripped; cloud
endpoint substituted at provision time.
- provision-uno-q.sh — one-shot adb-driven provisioner (no root): install
config, start llama-server + `zeroclaw daemon`, pair for a bearer token,
and POST /nodes to APESS.
- systemd/{zeroclaw-llama,zeroclaw-daemon}.service — production units
(daemon, not `gateway start`, so peripheral tools register).
- README.md — dev (adb) and production (systemd + LAN bind) runbooks.
The individual steps are hardware-verified: all three agent aliases resolve
and route correctly on the board (local→Qwen, cloud→cloud, default→cloud
with Qwen fallback). Full script orchestration + live phone-home land once
the api (with /nodes) is redeployed.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>