diff --git a/TODO.md b/TODO.md index 1dde347..8c1d1ae 100644 --- a/TODO.md +++ b/TODO.md @@ -34,6 +34,46 @@ Pick anything from here when relevant. Cross-cutting design notes live in the harness. Pairs well with the unprivileged-container work — would let the operator drop into the container without `nixos-container root-login`. +## Manager → operator question channel + +- **`mcp__hyperhive__ask_operator(question, options?)` tool** on the manager + MCP surface. The manager turn pauses; the question gets surfaced as a + prominent prompt on the dashboard (its own section, or interleaved with + the operator inbox); the operator's typed answer comes back as the tool + result. Modelled after Claude Code's `AskUserQuestion` tool. + + Design open questions: + + - **Storage.** New sqlite table `operator_questions(id, asker, question, + options_json, asked_at, answered_at, answer)` — or piggyback on the + existing message broker with a new envelope kind. Probably a new + table because the lifecycle (pending → answered) is different from + fire-and-forget messages. + + - **Waiting semantics.** The MCP tool call needs to block until + answered. Two options: + 1. Long-poll from inside the tool handler (broker-style — broadcast + on insert, await via `tokio::sync::broadcast`). Simple but the + claude turn stays alive for the whole wait, eating context-window + budget. + 2. Tool returns a `question_id` immediately; manager re-enters its + inbox loop and a `HelperEvent::OperatorAnswered { id, answer }` + wakes it. Cheaper context-wise but two-step. + + - **Dashboard UX.** New "◆ M1ND H4S QU3STI0NS ◆" section at the top + when any question is pending. Inline `
` with a textarea (or + select if `options` were provided), POST `/api/answer-question`. + State refresh + the live SSE stream notify the manager harness. + + - **Sub-agent path.** Sub-agents don't get the tool — they message the + manager and the manager decides whether to relay the question to the + operator. The manager's system prompt already covers this. + + - **Timeout / cancel.** Questions that sit pending too long: do they + expire? Manager probably wants to know if the operator hasn't + answered after some interval so it can fall back. Maybe a per- + question `ttl_seconds`. + ## Loop substance - **Notes compaction.** `/state/` is bind-mounted persistently and agents diff --git a/hive-ag3nt/prompts/agent.md b/hive-ag3nt/prompts/agent.md index 6ce3ab8..a722f08 100644 --- a/hive-ag3nt/prompts/agent.md +++ b/hive-ag3nt/prompts/agent.md @@ -5,7 +5,9 @@ Tools (hyperhive surface): - `mcp__hyperhive__recv()` — drain one more message from your inbox (returns `(empty)` if nothing pending). - `mcp__hyperhive__send(to, body)` — message a peer (by their name) or the operator (recipient `operator`, surfaces in the dashboard). -Need new packages, env vars, or other NixOS config for yourself? You can't edit your own config directly — message the manager (recipient `manager`) describing what you need. The manager edits `/agents/{label}/config/agent.nix` on your behalf, commits, and submits an approval that the operator can accept on the dashboard; on approve hive-c0re rebuilds your container with the new config. +Need new packages, env vars, or other NixOS config for yourself? You can't edit your own config directly — message the manager (recipient `manager`) describing what you need + why. The manager evaluates the request (it doesn't rubber-stamp), edits `/agents/{label}/config/agent.nix` on your behalf, commits, and submits an approval that the operator can accept on the dashboard; on approve hive-c0re rebuilds your container with the new config. + +Need to ask the human operator a question (clarification, permission, choice)? You don't have direct operator access — ask the manager to surface the question on your behalf ("please ask the operator: …"). The manager has a channel for this. Durable knowledge: write to `/state/notes.md` (free-form) or any other path under `/state/`. That directory is bind-mounted from the host and persists across container destroy/recreate — claude's `--continue` session only carries short-term context, but `/state/` is forever. Read it back at the start of relevant turns to remember things across resets. diff --git a/hive-ag3nt/prompts/manager.md b/hive-ag3nt/prompts/manager.md index 47ac024..76e54d1 100644 --- a/hive-ag3nt/prompts/manager.md +++ b/hive-ag3nt/prompts/manager.md @@ -10,6 +10,17 @@ Tools (hyperhive surface): Your own editable config lives at `/agents/hm1nd/config/agent.nix`; every sub-agent's lives at `/agents//config/agent.nix`. Use file/git tools to edit + commit, then `request_apply_commit`. +Sub-agents are NOT trusted by default. When one asks for a config change (new packages, env vars, etc.), verify the request before staging: + +- Does it match what the agent actually needs to do its declared role? +- Is the package legitimate (no obviously-malicious names, no overly broad permissions)? +- Are there cheaper / safer alternatives that don't need a config edit? +- If the change has any ambiguity or could affect other agents / the host, surface the question to the operator (see below) instead of staging it yourself. + +You're the policy gate between sub-agents and the operator's approval queue — the operator clicks ◆ APPR0VE on your commits, so don't submit changes you wouldn't defend. + +You can surface questions to the operator. (NOT YET IMPLEMENTED: a dedicated `mcp__hyperhive__ask_operator` tool will land soon — it pauses the turn, drops a prompt on the dashboard, and resumes with the answer.) For now, send to `operator` with a clear question and wait for the next turn to see their reply; the cadence is slower but the shape is the same. + Messages from sender `system` are hyperhive helper events (JSON body, `event` field discriminates): `approval_resolved`, `spawned`, `rebuilt`, `killed`, `destroyed`. Use these to react to lifecycle changes — e.g. greet a freshly-spawned agent, retry a failed rebuild, or note the change to the operator. Durable knowledge: