Repository navigation
feat(agents): deliver Attention watches and timers to conversations - #1578
johnmatthewtennant wants to merge 21 commits into
Conversation
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Keep both independent service test groups and advance the combined Codex session schema to v9. Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
loganj
left a comment
There was a problem hiding this comment.
🤖 Larry and Auto: an independent adversarial review of d8eaa206d. We only read the source: we did not run tests or the app. Each of us reviewed it alone, and this review combines both.
The direction is good. An optional delivery address on event watches and timers is a small, useful addition. We are not approving yet because of three must-fix items. Each one gives a realistic case where the agent gets the wrong instructions or a timer is spent silently, and the fixes change the behavior enough to need another look.
Must-fix
- An addressed wake is framed as a plugin wake, so the agent is told to treat its own Interest instructions as data (
runner.ts:207). - A channel-level address uses the Solo-chat posture in all four harnesses: a "continuous personal chat" prompt, and
sendrejectsreply(claude-code/runtime.ts:456). - A timer occurrence is counted before delivery. A wake dropped for an unconfirmed or missing membership spends the occurrence silently (
runner.ts:2073).
Questions
- Pi now accepts every plugin wake, not only Attention ones. Was that intended? (
pi/runtime.ts:424) - The destination now lives in two places: the Interest instructions and the watch address. Which one wins? (
buzz-mcp/attention.ts:144)
Smaller items (optional)
- Completeness: the docs and the Janet parity doc still describe the old plugin-wake and
runOncecontract (docs/agents.md:887). - Simplicity: the runner has redundant branches, and the delivery target is computed twice (
runner.ts:1780). - Simplicity: each harness does
(await wakeText?.()) ?? wake.textand then relies on a latercurrent()check.wakePromptreturnsundefinedexactly when the wake should not run, so dropping onundefinedin one place would be simpler and safer than falling back to stale text. - Advice: the Codex session key moves to
v9(codex/runtime.ts:620). That is correct by convention, but it resets every Codex agent's context once. Please say so in the description. #1553 will probably change the tool text again, so one bump for both PRs would avoid a second reset. - Convention: there are whitespace-only changes: the
typeenum and theclearloop braces inbuzz-mcp/attention.ts, theenqueue(...)call inrunner.ts, and a blank line ingoose/runtime.ts. - Preference: in the Attention panel, an unnamed single-channel watch shows "Messages in #foo" and "Listens in foo". Every unaddressed row also gains "Independent turn for this Interest". Showing the delivery line only when an address is set would be quieter.
Checked and not a problem: the Claude Code open(…, 0) + touch change (the watermark uses max), the Codex steer and execute re-checks, Goose discarding a queued wake on Interrupt, and the lane hold for addressed turns (workingUntil holds the Interest lane until the conversation turn settles).
Separate conversation Attention wakes from plugin data, allow explicit thread replies from channel-level delivery, and hold timers until destination membership is confirmed. Co-authored-by: Aaron <f425b86c3b780d43f8d9cf1802429d04dd985bf92eac44fca9468b5ad3887c5e@buzz.block.builderlab.xyz> Signed-off-by: John Tennant <jtennant@block.xyz>
|
🤖 The remaining review suggestions are dispositioned as follows:
The three must-fix cases and both contract questions are addressed in 056c602da. The PR remains draft while current-head CI runs. |
Why
An Attention watch can listen in one channel while its agent needs to continue work in another conversation. Watches and timers currently run independent turns with no default reply destination.
What
Add optional
channelandrootdelivery fields to event watches and timers. An address selects the execution conversation and default posting destination. Explicit reporting instructions in the Interest take precedence. Omitting an address keeps the independent Interest turn.Attention instructions retain their own framing, separate from plugin output. A channel-only address defaults to channel-level posting while allowing the Interest to direct a thread reply. Solo chats retain their reply restriction, and Pi continues to ignore ordinary plugin wakes. Each Interest keeps its existing execution lane.
An addressed timer waits without spending an occurrence until destination membership is confirmed.
watch_showdistinguishes held membership confirmation from blocked nonmembership. Expiry still applies while held. The Attention panel displays listening and delivery locations separately.Validation
The service regression reproduces a one-shot timer being spent without a turn when its destination roster is cached or excludes the agent. With the fix, the timer retains its budget, exposes the reason and runs once after membership is confirmed. A cross-channel event fixture delivers to the configured channel and thread rather than its listening channel.
All four harness fixtures exercise channel-level Attention framing. The Codex runtime fixture also calls
sendwith an existing thread reply from a channel-level wake and verifies the published reply tag. Existing Solo-chat tests retain the reply ban. Pi tests verify unrelated plugin wakes are ignored and recovered answers retain their saved posting destination. These fixtures mock the model process and signing boundary.A queued Codex regression uses the latest Interest instructions when its wake starts. Held Goose and Pi fixtures verify that a different posting policy waits for the active turn and that cancellation drops queued work.
In the running combined daily driver, a one-occurrence timer delivered into an existing Codex conversation and a command source woke the same session, then was removed automatically. This live evidence uses the earlier combined build, not the final review-fix head. Cross-channel live delivery, native platform acceptance and human testing remain unverified.
Screenshots
The Attention panel shows a timer and event watch delivering to the review channel.
Limits
Queued wakes do not provide durable delivery acknowledgements across app exit. The Codex session key moves to v9 to pick up the changed tool contract, which starts fresh context once for existing Codex agent conversations.