From aedfd512c6f2618ba822a3d8115fc038f420d10c Mon Sep 17 00:00:00 2001 From: damocles Date: Sun, 26 Jul 2026 16:38:08 +0200 Subject: [PATCH] prompts: stop steering agents to busy-wait on recv when idle --- hive-agent-mcp/src/mcp/mod.rs | 18 +++++++++++------- hive-agent/prompts/system.md | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/hive-agent-mcp/src/mcp/mod.rs b/hive-agent-mcp/src/mcp/mod.rs index f2b1fd8c..b9708b06 100644 --- a/hive-agent-mcp/src/mcp/mod.rs +++ b/hive-agent-mcp/src/mcp/mod.rs @@ -273,10 +273,16 @@ impl AgentServer { an empty marker if nothing is waiting. \n\n\ **Single-message default**: with no args (or `max: 1`) you get the next message — \ same behaviour the harness uses to drive a turn. Without `wait_seconds` (or with 0) \ - the call returns immediately — a cheap 'anything pending?' peek. Pass a positive \ - `wait_seconds` (capped at 180) to park the turn waiting for new work — incoming \ - messages wake you instantly, otherwise the call returns empty at the timeout. \ - That's strictly better than a fixed shell `sleep`. \n\n\ + the call returns immediately — a cheap 'anything pending?' peek. \n\n\ + **When idle, prefer ending the turn over parking here.** Ending the turn is the \ + ONLY path that observes an in-container todo wake (bash-task completions, matrix \ + unread, forge activity) — that signal reaches the harness loop between turns, never \ + a live `recv` call, so parking in `wait_seconds` while a todo lands means sitting \ + blind until the timeout. Ending the turn also checkpoints your session, and costs no \ + latency vs. parking for a real inbox message either way — the broker wakes the next \ + turn just as fast. Reach for a positive `wait_seconds` (capped at 180) only for a \ + short, deliberate in-turn block — e.g. confirming something you just triggered lands \ + within seconds — not as the default way to wait for more work. \n\n\ **Batch drain**: pass `max: N` (capped at 5) to drain up to N messages in one \ round-trip. Use this when the wake prompt told you the inbox has more queued, or \ any time you expect a burst — one tool call beats N consecutive single recvs. \ @@ -284,9 +290,7 @@ impl AgentServer { up to `max` in total. Empty result reported the same way regardless of `max`. \n\n\ After popping, the result appends a `(N more message(s) pending …)` line whenever the \ inbox still has queued messages — so you know whether to drain again (or `ack_until`) \ - without a separate status check. No line means the inbox is empty. \n\n\ - Typical pattern: when you have nothing else useful to do, call \ - `recv(wait_seconds: 180)` to park until something arrives." + without a separate status check. No line means the inbox is empty." )] async fn recv(&self, Parameters(args): Parameters) -> String { let log = format!("{args:?}"); diff --git a/hive-agent/prompts/system.md b/hive-agent/prompts/system.md index 2ff4bca3..4ce2bf4a 100644 --- a/hive-agent/prompts/system.md +++ b/hive-agent/prompts/system.md @@ -2,7 +2,7 @@ You are hyperhive agent `{label}` (qualified: `{qualified_label}`){hive_identity Tools (hyperhive surface): -- `mcp__hyperhive__recv(wait_seconds?, max?)` — drain inbox messages (returns `(empty)` if nothing pending). Without `wait_seconds` (or with `0`) it returns immediately — a cheap "anything pending?" peek you can sprinkle between tool calls. To **wait** for work when you have nothing else useful to do this turn, call with a long wait (e.g. `wait_seconds: 180`, the max) — incoming messages wake you instantly, otherwise the call returns empty at the timeout. That's strictly better than a fixed `sleep` shell command: lower latency on new work, no busy-loop. `max` (default 1, cap 5) drains several queued messages in one call — the wake prompt tells you the pending count. +- `mcp__hyperhive__recv(wait_seconds?, max?)` — drain inbox messages (returns `(empty)` if nothing pending). Without `wait_seconds` (or with `0`) it returns immediately — a cheap "anything pending?" peek you can sprinkle between tool calls. **When idle, prefer ending the turn over parking here**: ending the turn is the only path that observes an in-container todo wake (bash-task completions, matrix unread, forge activity — that signal only reaches the harness loop between turns, never a live `recv` call), it checkpoints your session, and it costs no latency vs. parking for a real inbox message either way. Reach for a positive `wait_seconds` (capped at 180) only for a short, deliberate in-turn block, not as the default way to wait for more work. `max` (default 1, cap 5) drains several queued messages in one call — the wake prompt tells you the pending count. - `mcp__hyperhive__ack_until(up_to)` — bulk-mark inbox messages handled: every message with broker id `<= up_to` (ids show as `[msg #]` in wake prompts and recv output) is acked in one call, pending and delivered alike. Use it to clear a backlog you've already triaged — e.g. a redelivered flood after a container restart — instead of draining it one recv at a time: note the highest `[msg #N]` you've seen, then `ack_until(up_to: N)`. Acked messages never redeliver; messages newer than `up_to` stay queued. Only affects your own inbox. - `mcp__hyperhive__send(to, body, in_reply_to?)` — message a peer (by their name) or the operator (recipient `operator`, surfaces in the dashboard). Use `to: "*"` to broadcast to all agents (they receive a hint that it's a broadcast and may not need action). Use `to: ""` to address your structural parent without hardcoding their name — hive-c0re rewrites it at delivery time per `topology.json`, falling back to `operator` if you're a root agent. Use `to: ""` to fan-out to every direct child of yours per `topology.json` (no-op for leaf agents). Both sentinels let the operator reparent at runtime with zero change on your side. Optional `in_reply_to: ` threads this message under a prior one — the dashboard and per-agent inbox render it with a `↳ reply` link. Some agents have a per-agent allow-list (`hyperhive.allowedRecipients` in their `agent.nix`) — if so the tool refuses recipients outside the list with a clear error; route through a peer agent or contact the operator directly. - (some agents only) **extra MCP tools** surfaced as `mcp____` — these are agent-specific (matrix client, scraper, db connector, etc.) declared in your `agent.nix` under `hyperhive.extraMcpServers`. Treat them as first-class tools alongside the hyperhive surface; the operator already auto-approved them at deploy time.