LazyBoy is a general-purpose local CLI agent: **observe → decide → act → verify → respond**. The model chooses the next action from the current environment and user objective. Scenario playbooks are optional guidance, never a fixed task router.
The interaction rules below describe legacy single-session mode. Named-agent mode keeps new chat separate from background work and uses task-specific controls.
- For action tasks, the first action is `send_message`, then tools. Multi-stage work uses a short `update_plan` checklist.
-`send_message` is the only user-visible voice. Plain assistant text is a scratchpad. A no-tool response ends the turn (Grok Bot loop). `report_progress` is a text `send_message` alias and continues.
- Commands background after `block_until_ms` (default 30s). Jobs are not killed on `answer`/`done`.
-`spawn_subagent` returns immediately. If the model yields while a subagent or command is still running, the runtime waits and injects a revival (Grok Bot background completion). `check_subagent` / `message_subagent` / `stop_subagent` manage live children; do not poll for completion.
- Human questions, confirmations and handoff **end the turn**. The next user message is the answer; there is no timeout-and-continue.
- In the REPL, background commands/subagents return the prompt. Completion injects a revival and continues automatically; typed input meanwhile is steering. `lazyboy run` still waits in-process so the job is not lost when the process exits.
Model requests are bounded by `LAZYBOY_MAX_ROUNDS_TOTAL` (default 5000). `LAZYBOY_MAX_ROUNDS` only controls local progress frequency. A 20-second heartbeat identifies the operation actually being awaited.
Two identical action/result rounds inject a reminder; three stop as blocked. Empty model responses retry up to three times. File reads/search/`web_fetch`/`send_message` in one batch run in parallel; commands, writes and browser tools stay serial. Successful controlled waits use their own deadlines rather than the identical-output guard.
The core publishes typed events through `Runtime::set_event_handler`; CLI formatting lives in the binary. Tool output, not narrative promises, drives the next request. Process output is streamed to local files and returned incrementally, with one foreground process group per session.
Checkpoint before and after tools, retain plan/pending questions/command metadata/browser URL, and pair every call with a result. On recovery, missing outcomes become explicit unknown results; never replay automatically. Persistent browser profiles include session cookies. Context trimming operates on request copies, preserving stored history, system instructions and user constraints.
Current target: macOS CLI plus a split web stack — Rust `lazyboy serve` is JSON/SSE API for **named Agents** (not session files); the Vite/React app in `web/` is the Grok Bot-shaped shell (agent sidebar, conversation, composer, computer overlay, PWA). Optional Playwright DOM browser and Docker box desktop. Not an Electron clone. Persistent named agents use a local daemon, private memory and a background task scheduler; see [TEAM](TEAM.md). Desktop pixel control is a `computerUse` subagent (`computer` via xdotool); the parent cannot click. Each named agent has its own Docker desktop; opening the agent starts that seat and the UI reports whether it became ready. No separate search key, Electron UI, PTY, or CUA in this version. Browser-only canvas apps and arbitrary natural-language task correctness remain outside what this MVP can guarantee.
Legacy `chat` stays a no-tools streaming chat. `shell` stays available with a 30-second deadline. Synchronous human-wait library helpers are retained for AUTO/offline compatibility; interactive callers must supply the runtime input broker.