NanoClaw
NanoClaw moves scheduled errors and container sessions behind host-owned seams
NanoClaw proposes routing scheduled-task errors to operators, refusing group creation over undisposed folders, and introducing a session-runtime driver with Docker as the built-in implementation. The host is becoming the owner of both delivery and lifecycle truth.
nanocoai/nanoclaw PR #3311 is the inspected primary source: “fix(agent-runner): route scheduled-task errors to the operator (#3223).” The related records below were inspected as supporting context rather than independent confirmation.
The facts
- nanocoai/nanoclaw PR #3311 was created 2026-08-18T00:32:06Z and was open at inspection; its title is “fix(agent-runner): route scheduled-task errors to the operator (#3223).” - nanocoai/nanoclaw PR #3308 was created 2026-08-17T22:58:27Z and was open at inspection; its title is “groups: refuse to create a group over a folder that already exists undisposed.” - nanocoai/nanoclaw PR #3306 was created 2026-08-17T22:57:36Z and was open at inspection; its title is “drivers: a session-runtime driver seam, with Docker as the built-in realization.” - The repository reported 30534 stars, 900 open issues, default branch main, and last push 2026-08-17T23:37:32Z. - The latest tagged-release baseline checked was v2.2.0 published 2026-08-13T20:43:27Z.
What changed
nanocoai/nanoclaw PR #3311 reports: Fixes #3223 Summary A scheduled-task turn that throws (provider error, model error, etc.) previously wrote its error as a chat message copying the batch's routing fields. Task batches carry no routing fields by design (the agent chooses delivery destination at fire time), so the error message had platform_id = channel_type = NULL, and delivery.ts's routing-field guard silently dropped it. The batch was also acked completed, so the task's run history recorded no failure — a recurring task that starts erroring (expired credential, retired model, dead MCP server) fails forever, silently, at full cron cadence. This is the runner-side minimal fix + accounting from the issue's suggested direction (options 1+2): In the task-turn error path (container/agent-runner/src/poll-loop.ts), when routing.taskRun is true, the error is appended to the task's run log via the existing autoAppendTaskLog one-door mechanism (Run FAILED: ) instead of being written as an unroutable chat message. The host's existing task_log handling in src/delivery.ts (unchanged) appends it to the series' tasks/.md. The batch then acks failed (via the existing markFailed) instead of completed. The host's syncProcessingAcks (src/db/session-db.ts, unchanged) already maps a failed processing_ack to a FAILED messages_in row — the same path script-skip:error uses — so ncl tasks list's failed-run count and the recurrence backoff streak both see the failure
nanocoai/nanoclaw PR #3308 reports: Stacked on #3306 and the consumption PR. Two small refusals that close a data-loss shape: **Creating a new agent group over an existing folder is refused.** A leftover folder is either deleted-group residue or an operator-placed directory; silently minting a new group id over it would adopt files the new agent never created (and expose them to it). The error names the folder and the way out. **A folder name the session labels cannot carry verbatim is refused at creation time**, instead of failing later at spawn where the error loses its context. Covers group creation via the CLI, agent-to-agent creation, and channel-approval provisioning, each with tests (including symlink residue whose target is gone). Generated with Claude Code
nanocoai/nanoclaw PR #3306 reports: Adds \src/drivers/\ — a seam between "what a session is" and "how it runs", with Docker as the built-in realization. **Purely additive: no call site changes, nothing in the host loads differently after this PR** (the whole suite is green at this commit alone). What's in the module **\SessionSpec\ vocabulary** — a substrate-neutral description of a session: containers with roles, env, command/args split, mounts, labels, resources, \runAs\, stop grace. **A mount-class taxonomy + \validateSpec\** — where a file lives decides what it *is*: \install-surface\ (read-only, enforced), \identity-material\ (never mounted into the agent container), \group-state\ (pinned to the group subtree), \allowlisted-extra\. Required classes are computed from paths, so a mount can't be relabelled into a weaker class. **A driver registry with an overlay barrel** — out-of-tree drivers register a kind; selection is dormant in this PR (nothing reads it yet). **The Docker driver** — \prepare\ (allocate everything, start nothing; idempotent per session), \start\, snapshot-honest \listSessions\ (an exited runtime is reported \terminal\, never dressed up as live), \watchSessions\ (one driver-level \docker events\ subscription with reconnect + gap reconciliation), \stop\. **A session-events hub** — \onTerminal\ becomes at-most-once sugar over the driver's event stream: every hint is verified against \status()\ before firing, replayed/duplicate events can't fire terminals for live sessions, and stop-intent suppression lives
Why it matters
A pluggable runtime seam is useful only if scheduled failures and stale filesystem ownership remain visible above the driver. Otherwise portability merely relocates ambiguity. The operator test is whether the system remains bounded and its receipts still describe the action after failure, retry or restart.
Current
The primary record was open when captured on 2026-08-18. The tagged-release baseline was v2.2.0 published 2026-08-13T20:43:27Z. Repository metadata, full source bodies, current pull requests and issues, releases, Google News, Hacker News, Lobsters, Metamesh and the rendered ClawCharts row were inspected. ClawCharts selected the subject; it did not prove the claim.
Evidence
The primary URL is https://github.com/nanocoai/nanoclaw/pull/3311. Supporting records are https://github.com/nanocoai/nanoclaw/pull/3308 and https://github.com/nanocoai/nanoclaw/pull/3306. Source bodies, timestamps and states are preserved in the daily evidence bundle. Test counts and reproductions remain attributed to their authors unless identified as independently rerun.
Source boundary
Open work is described as open, closed work as closed, and operator reports as reports. A pull request is evidence of proposed or reviewed direction, not proof of a shipped release. Search residue, package mirrors and historically published source spines were excluded.
Operator take
Give runtime drivers explicit start, stop and receipt contracts, reject stale group directories before allocation, and route every scheduled failure to the owning operator surface. Preserve a before-state receipt, make the smallest reversible change, and verify the original failure independently.
Caveat
Public project records are mutable. Status, scope and evidence can change after publication. This brief records the inspected state and does not authorize changes to a reader’s deployment.
Source inspected; source state, environment and release boundary remain explicit.