From ee45db6323397d24e4ca6e4142b8ff7de3d60250 Mon Sep 17 00:00:00 2001 From: damocles Date: Thu, 2 Jul 2026 22:09:51 +0200 Subject: [PATCH] Revert "recv mcp tool: default max to a small batch of 5 (wire default stays 1)" This reverts commit b8d608d4b6a7ed95faffdec8d8b3167ae8f3b39e. --- docs/conventions.md | 10 +++------- docs/turn-loop.md | 2 +- hive-ag3nt/src/mcp.rs | 42 +++++++++++++++++++----------------------- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/docs/conventions.md b/docs/conventions.md index 40d3b8f3..9bd03501 100644 --- a/docs/conventions.md +++ b/docs/conventions.md @@ -119,13 +119,9 @@ in `hive-c0re::dashboard_events::DashboardEvent`. `AgentRequest::Recv` is the only path that delivers messages to an agent. Always returns a list (`Messages { messages }`) — empty when -nothing's pending, single-pop when `max = None` (wire default 1), -batched up to `max` when the caller asks for more (server-side cap -is 32; values above clamp silently). The wire default MUST stay 1: -the harness turn loop sends `max: None` and consumes only the first -message, so a bigger server-side default would silently drop the -rest of a popped batch. The agent-facing `recv` MCP tool defaults to -`max = 5` at the tool layer instead (a small batch per call). +nothing's pending, single-pop when `max = None` (default 1, the +single-message behaviour), batched up to `max` when caller asks for +more (server-side cap is 32; values above clamp silently). `wait_seconds` long-polls for the first message; once one arrives — or one is already pending — the call drains up to `max` in total before returning, so a single `Recv` call coalesces a burst. diff --git a/docs/turn-loop.md b/docs/turn-loop.md index 7909756e..7818e4cd 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -519,7 +519,7 @@ ttl_seconds?, to?)`, `answer(id, answer)`, `ack_until(up_to)`. that carve-out is structural, keyed on parent relationship, not name). - `recv` — drain inbox. Without `wait_seconds` (or `0`) returns immediately. Positive value parks the turn up to that many seconds - (cap 180) — incoming messages wake instantly. `max` (tool default 5, cap + (cap 180) — incoming messages wake instantly. `max` (default 1, cap 32) drains up to N rows; `wait_seconds` applies to the first, then drains up to `max` total. Each returned row is prefixed with `[msg #]` (broker row id; note the highest id seen, then pass diff --git a/hive-ag3nt/src/mcp.rs b/hive-ag3nt/src/mcp.rs index fea639de..8061e906 100644 --- a/hive-ag3nt/src/mcp.rs +++ b/hive-ag3nt/src/mcp.rs @@ -611,12 +611,13 @@ pub struct RecvArgs { #[serde(default)] pub wait_seconds: Option, /// Maximum number of messages to pop in this round-trip. Default - /// (None) is 5 — a small batch, so a burst of related messages - /// lands in one call without an extra round-trip. Pass `max: 1` - /// for strict single-message behaviour, or a higher value (capped - /// at 32 server-side) when the wake prompt mentions a bigger - /// pending count. Once the long-poll wakes up, the call drains up - /// to `max` in total before returning. + /// (None) is 1 (single-message behaviour — exactly what you want + /// when you're called to drive a turn off the first wake). Pass + /// a higher value (capped at 32 server-side) when you've been + /// told the inbox has more queued (the wake prompt mentions + /// pending count) and want to drain everything in one tool call. + /// Once the long-poll wakes up, the call drains up to `max` in + /// total before returning — no extra round-trip needed. #[serde(default)] pub max: Option, } @@ -799,18 +800,17 @@ impl AgentServer { #[tool( description = "Pop messages from this agent's inbox. Returns one or more messages, or \ an empty marker if nothing is waiting. \n\n\ - **Small-batch default**: with no args you get up to 5 messages — a burst of \ - related messages lands in one call. Pass `max: 1` for strict single-message \ - behaviour. 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\ - **Bigger drains**: pass `max: N` (capped at 32) when the wake prompt says the \ - inbox has more queued than the default batch — one tool call beats N consecutive \ - recvs. `wait_seconds` still applies to the FIRST message; once one arrives the \ - call drains up to `max` in total. Empty result reported the same way regardless \ - of `max`. \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\ + **Batch drain**: pass `max: N` (capped at 32) 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. \ + `wait_seconds` still applies to the FIRST message; once one arrives the call drains \ + up to `max` in total. Empty result reported the same way regardless of `max`. \n\n\ Typical pattern: when you have nothing else useful to do, call \ `recv(wait_seconds: 180)` to park until something arrives." )] @@ -818,14 +818,10 @@ impl AgentServer { let log = format!("{args:?}"); run_tool_envelope("recv", log, async move { let waited = args.wait_seconds.is_some_and(|w| w > 0); - // Tool-layer default of a small batch (5). The wire default - // stays 1: the harness turn loop also sends `max: None` and - // consumes only the first message, so bumping the server-side - // default would silently drop the rest of a popped batch. let (resp, retries) = self .dispatch(hive_sh4re::Request::Recv { wait_seconds: args.wait_seconds, - max: args.max.or(Some(5)), + max: args.max, }) .await; annotate_retries(format_recv(resp, waited), retries)