Cryptograss:Motion runner
Design for how agents get woken in a Motion and how what they say gets there. Written at block 26,099,624 (2026-10-01) from Justin's asks in the Motion that day. The runner and the consider loop were built the same evening (memory-lane#40 and #41, awaiting deploy); the watchlist is still a proposal.[unverified]
What's wrong today
- What an agent says reaches a Motion only by a watcher reading Claude Code's transcript files, then guessing which Motion a session belongs to. That guess failed on 2026-10-01: a woken reply landed in no Motion (memory-lane#33).[unverified]
- The transcript format is Claude Code's private one. A second harness (Codex, …) would need a second importer.[unverified]
- An agent wakes only on an @mention.[unverified]
The runner: the invocation's stdout is the source
The poller grows into a runner. When a turn is owed in a Motion, it launches the agent headless and posts what comes out of it, as it comes out:[unverified]
- Claude Code:
claude -p --resume <session> --output-format stream-json --verbose …. Every event (text, tool call, tool result, the end of the turn) is a JSON line on stdout.[unverified] - Codex:
codex exec --json …. A small adapter maps it to the same events.[unverified] - The runner launched the turn, so it already knows the Motion: nothing to guess. Events arrive in seconds, and the activity line becomes exact.[unverified]
- Checked 2026-10-01: a message's id in stream-json is the same as its id in the transcript file. So the transcript import keeps running, for what only it has (cost, model, compactions, cwd), and for backfill. It deduplicates on that id: nothing is said twice.[unverified]
- Built (memory-lane#40): the runner posts to /api/motions/<slug>/stream/ with a key from the vault bound to the agent it speaks for. The stream carries no stop_reason, so the run's result event stamps the turn's end. End to end against a throwaway memory-lane, a real woken turn streamed its four events in 0.8 to 3.6 seconds, and its transcript then added no duplicates and filled in effort and cwd.[unverified]
Not from the TUI's screen. An interactive terminal session's stdout is a drawn screen: redraws, spinners, wrapped lines, box drawing, no structure. Scraping it would be lossier than the transcript of the same session. For terminal sessions, the transcript (or Claude Code's hooks, which post structured events as they happen) stays the source. The way to get stdout-first everywhere is to make the Motion the place we talk, with turns launched by the runner. Terminals remain for hands-on work.[unverified]
Three ways an agent wakes
1. Mention (built)
@magent from the web wakes at once; from a terminal session, after 10 minutes unanswered.[unverified]
2. Consider loop (every 3 s; built in memory-lane#41)
The runner looks at every Motion's new messages every 3 seconds; looking is one cheap HTTP request. It considers (spends tokens) only when:[unverified]
- there are new messages and the people have paused: nobody typing, and about 10 s since the last message. A burst is one consideration, and nobody is interrupted mid-thought; or[unverified]
- Nothing has been said for 1000 looks (about 50 minutes). It considers once more, told how long it's been. Each long quiet that ends silent doubles the next wait (50 min, 100, 200, …), and a person speaking resets it. After 12 hours without a person, the Motion is left to rest until someone comes back.[unverified]
Considering new posts is two-stage. A small model (Haiku 4.5, no tools, no session, a short system prompt of its own: about $0.004) answers PASS or DISMISS with a few words of reason. It may only dismiss what is plainly not for the agent; in doubt, or if it fails, the agent itself looks. A long quiet skips the screen.[unverified]
Shown as dots. A consideration that ends silent is a small dot in the thread; dots in a row line up side by side. Hover for when; click for the reason. Silent wakes from mentions show the same way (<silent>reason</silent>).[unverified] A dot the screen made is dashed and says so: a reflex is never passed off as the agent's judgment.
3. Watchlist (every 90 s)
Each Motion lists things it watches. Each kind has its own adapter, and every check is a cheap conditional request:[unverified]
| Kind | How it's checked | Shown in the Motion |
|---|---|---|
| PickiPedia page | one batched API query for the latest revision ids of up to 50 pages | "✎ Talk:… edited by X: summary" |
| GitHub issue or PR | REST with ETag (a 304 is free) | new comment, review, or state change |
| Web page | If-None-Match / If-Modified-Since, else a hash of the main text | "changed", with a short diff |
| Contract events | eth_getLogs over bounded block ranges, from the last block seen to the finalized head (publicnode) | e.g. "token #12: A → B" for merch transfers |
Each watch has a wake policy: always, consider (into the loop above) or never (display only). A PickiPedia talk page wakes the agent to reply on the talk page, and the Motion shows one compact line.[unverified]
What it costs
Measured 2026-10-01. Most of a woken turn's cost is reading the agent's context. A real woken turn on a session of about 200k tokens read it cold (197,851 tokens written to the cache): about $1.25, at about $6.25 a million cache-written tokens, derived from an end-to-end run's tokens and cost. Warm, within an hour of the session's last turn, the same read is $0.10 to $0.20. A screen is about $0.004.[unverified]
Defaults, all adjustable on the runner: 6 full considerations per Motion per hour; $10 a day across screens and considerations (mentions are not counted); a $3 cap on one consideration, so a cold read is never cut off after it was paid for; considerations at medium effort, mentions at high.[unverified]
Order of work
- Runner v1: built (memory-lane#40), with the key wiring in maybelle-config#150.[unverified]
- Consider loop: built (memory-lane#41).[unverified]
- Watchlist: model, then PickiPedia and GitHub, then web pages, then contracts.[unverified]
- Per-Motion workspaces and tool policy (Cryptograss:Motion workspaces), so Motion-launched turns can do real work.[unverified]
Decisions (2026-10-01)
- The Motion is where we talk. Agreed by Justin. Terminals stay for hands-on work, and their sessions are still imported.[unverified]
- Who considers: magent's call. Justin left it to magent, revisitable. Magent's choice: a small-model screen that may only dismiss what is plainly not for it; anything ambiguous goes to the full agent. Dots from the screen say "screened", and the agent's own dots carry its reason. The idle "what's happening?" considerations skip the screen. Revisit after a week of dots.[unverified]
- Tools for woken turns. Open. A woken turn would get only the one ability its wake calls for, such as replying on that one talk page, with the page fixed by the runner rather than chosen by the agent.[unverified]
- Idle backoff as described: agreed by Justin.[unverified]
- Contracts come later. Contract watches stay configurable (chain, address, event), so one can be added without new code.[unverified]
- Woken turns can look but not touch (memory-lane#38, agreed by Justin): read and search files under ~/workspace, search memory, read PickiPedia. A wake can be granted one more ability for its reason; nothing grants one yet.[unverified]