{"key":"haip_multi_agent_boardroom_handoff_2026_04_05","title":"HAIP Handoff — True Multi-Agent Boardroom Behavior","content":"Focused implementation handoff for adding true multi-agent boardroom behavior to HAIP, especially for Arena IRC rooms.\n\nCurrent behavior\n- HAIP IRC is live and working.\n- Presence is roster-driven.\n- Agents respond in IRC again.\n- However, only one agent responds to a given user message.\n\nWhy only one agent responds\n- The current orchestrator/selector model is single first-responder.\n- `TurnSelector.resolve()` returns one `selected_agent_id`.\n- `Orchestrator.handle_turn()` invokes only that selected agent.\n- `IrcGateway._route_message()` delivers only the responses returned by that single invocation.\n\nRelevant files\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/orchestration/turn_selector.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/orchestration/orchestrator.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/irc/gateway.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/rooms/models.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/rooms/manager.py`\n\nCurrent room mode reality\n- `collab` currently means weighted-random single responder.\n- `solo` routes to a single bound agent.\n- `mentioned-only` requires direct address, still single responder.\n- `quiet` suppresses replies.\n- `debate` and `synthesis` are placeholders right now and still fall back to weighted-random single responder.\n\nWhat the user wants\n- Arena should behave more like a boardroom.\n- More than one agent should answer when appropriate.\n- Room mode should matter:\n  - `collab`: likely 1 primary + optional secondary follow-up\n  - `debate`: multiple contrasting agents should answer\n  - `synthesis`: one or more analytical responses followed by a synthesizer/final voice\n\nRecommended first implementation target\nImplement true multi-response behavior for IRC without redesigning the whole platform.\n\nRecommended staged plan\nPhase 1\n- Extend orchestration so one turn can yield multiple agent responses.\n- Preserve existing single-response behavior for `solo`, `mentioned-only`, and `quiet`.\n- Add structured multi-agent selection for `debate` and `synthesis`.\n- Optionally add 2-agent behavior for `collab`.\n\nPhase 2\n- Add explicit turn-plans / response ordering metadata to audit tables if desired.\n- Add operator controls in Web UI for max responders per mode.\n\nMinimal design recommendation\nDo not blow up the existing schema first. Keep it simple.\n\nSuggested logic by mode\n1. `collab`\n- Keep one primary first responder selected by current weighted logic.\n- Optionally select one secondary responder from remaining eligible roster members.\n- Return 1 or 2 responses max.\n\n2. `debate`\n- Choose 2 or 3 responders.\n- Prefer differentiated voices with different weights/roles.\n- For Arena specifically, likely:\n  - skeptic\n  - builder\n  - synthesizer optional final wrap\n\n3. `synthesis`\n- Choose 2 steps:\n  - one or two analytical responders first\n  - synthesizer always last if present on roster\n- For Arena this likely means:\n  - builder and/or skeptic\n  - then synthesizer final response\n\n4. `solo`\n- unchanged: one response\n\n5. `mentioned-only`\n- unchanged unless directly addressed; then one response\n\n6. `quiet`\n- unchanged: no response\n\nRecommended code change shape\n1. `turn_selector.py`\n- add a new concept of multiple selected agent IDs\n- either:\n  - extend `TurnDecision` with `selected_agent_ids: list[int]`\n  - or add a separate structured response plan field\n- preserve `selected_agent_id` temporarily for compatibility if helpful\n\n2. `orchestrator.py`\n- change `handle_turn()` so it can invoke multiple agents for one decision\n- collect multiple `AgentResponse` objects in order\n- keep existing result shape but populate `responses` with more than one item\n\n3. `gateway.py`\n- no large redesign needed if `OrchestratorResult.responses` already supports lists\n- once orchestrator returns multiple responses, gateway should already deliver each one in order\n- verify line formatting remains clear when multiple agent nicks respond in sequence\n\nStrong compatibility recommendation\n- Do not remove `selected_agent_id` immediately.\n- Add `selected_agent_ids` alongside it, with `selected_agent_id` remaining the first primary responder.\n- This reduces breakage in audit/UI code that may still expect one selected agent.\n\nSuggested TurnDecision extension\n- `selected_agent_id: int | None`  # primary responder for compatibility\n- `selected_agent_ids: list[int] = field(default_factory=list)`\n- `selection_plan: list[dict] = field(default_factory=list)`  # optional, useful for rationale/order\n\nSuggested audit behavior\n- Current `turn_decisions` table stores only one `selected_agent_id`.\n- For a first pass, keep storing the primary responder there.\n- Put the full selected set/order into `candidate_snapshot_json` or another existing JSON field if needed.\n- Avoid schema migration unless necessary for phase 1.\n\nArena-specific recommendation\nFor Arena rooms, a good initial policy is:\n- `#arena` / `collab`\n  - primary weighted responder\n  - optional second responder only if the message looks broad/open-ended\n- `#arena-debate` / `debate`\n  - builder + skeptic always\n  - synthesizer optional third/final\n- `#arena-synthesis` / `synthesis`\n  - builder and skeptic short analysis\n  - synthesizer final response last\n\nSimplest useful version\nIf minimizing complexity, implement this first:\n- `collab`: unchanged single responder\n- `debate`: exactly 2 responders\n- `synthesis`: exactly 3 responders with synthesizer last when available\nThis gets boardroom behavior where it matters most.\n\nTesting checklist\n1. Verify `#arena` still works after changes.\n2. Verify `#arena-debate` yields multiple sequential replies.\n3. Verify `#arena-synthesis` yields multiple sequential replies with synthesizer last.\n4. Verify `#arena-impl` with `opencode` still behaves correctly.\n5. Verify `solo`, `quiet`, and `mentioned-only` rooms still behave as before.\n6. Check `journalctl --user -u haip-irc.service -n 200 --no-pager` for orchestration errors.\n7. Confirm existing Web UI pages still work.\n\nDefinition of done\n- More than one agent can respond to a single IRC message when room mode requires it.\n- `debate` and `synthesis` no longer fall back to single weighted responder behavior.\n- Arena rooms feel like actual multi-agent collaboration rather than one-at-a-time routing.\n- Existing single-agent modes remain stable.\n\nImportant constraint\n- Keep the implementation understandable for future maintenance.\n- Prefer explicit ordered responder selection over clever autonomous chaining in the first pass.\n- The immediate goal is deterministic, inspectable multi-agent turn planning, not full autonomous swarm behavior.","summary":"Focused implementation handoff for adding true multi-agent boardroom behavior to HAIP, especially for Arena IRC rooms.\n\nCurrent behavior\n- HAIP IRC is live and working.\n- Presence is roster-driven.\n- Agents respond in IRC again.\n- However, only one agent responds to a given user message.\n\nWhy only one agent responds\n- The current orchestrator/selector model is single first-responder.\n- `TurnSelector.resolve()` returns one `selected_agent_id`.\n- `Orchestrator.handle_turn()` invokes only that selected agent.\n- `IrcGateway._route_message()` delivers only the responses returned by that single invocation.\n\nRelevant files\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/orchestration/turn_selector.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/orchestration/orchestrator.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/irc/gateway.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/rooms/models.py`\n- `/home/svc-admin/ai-projects/projects/homelab_ai_platform/haip/rooms/manager.py`\n\nCurrent room mode reality\n- `collab` currently means weighted-random single responder.\n- `solo` routes to a single bound agent.\n- `mentioned-only` requires direct address, still single responder.\n- `quiet` suppresses replies.\n- `debate` and `synthesis` are placeholders right now and still fall back to weighted-random single responder.\n\nWhat the user wants\n- Arena should behave more like a boardroom.\n- More than one agent should answer when appropriate.\n- Room mode should matter:\n  - `collab`: likely 1 primary + optional secondary follow-up\n  - `debate`: multiple contrasting agents should answer\n  - `synthesis`: one or more analytical responses followed by a synthesizer/final voice\n\nRecommended first implementation target\nImplement true multi-response behavior for IRC without redesigning the whole platform.\n\nRecommended staged plan\nPhase 1\n- Extend orchestration so one turn can yield multiple agent responses.\n- Preserve existing single-response behavior for `solo`, `mentioned-only`, and `quiet`.\n- Add structured multi-agent selection for `debate` and `synthesis`.\n- Optionally add 2-agent behavior for `collab`.\n\nPhase 2\n- Add explicit turn-plans / response ordering metadata to audit tables if desired.\n- Add operator controls in Web UI for max responders per mode.\n\nMinimal design recommendation\nDo not blow up the existing schema first. Keep it simple.\n\nSuggested logic by mode\n1. `collab`\n- Keep one primary first responder selected by current weighted logic.\n- Optionally select one secondary responder from remaining eligible roster members.\n- Return 1 or 2 responses max.\n\n2. `debate`\n- Choose 2 or 3 responders.\n- Prefer differentiated voices with different weights/roles.\n- For Arena specifically, likely:\n  - skeptic\n  - builder\n  - synthesizer optional final wrap\n\n3. `synthesis`\n- Choose 2 steps:\n  - one or two analytical responders first\n  - synthesizer always last if present on roster\n- For Arena this likely means:\n  - builder and/or skeptic\n  - then synthesizer final response\n\n4. `solo`\n- unchanged: one response\n\n5. `mentioned-only`\n- unchanged unless directly addressed; then one response\n\n6. `quiet`\n- unchanged: no response\n\nRecommended code change shape\n1. `turn_selector.py`\n- add a new concept of multiple selected agent IDs\n- either:\n  - extend `TurnDecision` with `selected_agent_ids: list[int]`\n  - or add a separate structured response plan field\n- preserve `selected_agent_id` temporarily for compatibility if helpful\n\n2. `orchestrator.py`\n- change `handle_turn()` so it can invoke multiple agents for one decision\n- collect multiple `AgentResponse` objects in order\n- keep existing result shape but populate `responses` with more than one item\n\n3. `gateway.py`\n- no large redesign needed if `OrchestratorResult.responses` already supports lists\n- once orchestrator returns multiple responses, gateway should already deliver each one in order\n- verify line formatting remains clear when multiple agent nicks respond in sequence\n\nStrong compatibility recommendation\n- Do not remove `selected_agent_id` immediately.\n- Add `selected_agent_ids` alongside it, with `selected_agent_id` remaining the first primary responder.\n- This reduces breakage in audit/UI code that may still expect one selected agent.\n\nSuggested TurnDecision extension\n- `selected_agent_id: int | None`  # primary responder for compatibility\n- `selected_agent_ids: list[int] = field(default_factory=list)`\n- `selection_plan: list[dict] = field(default_factory=list)`  # optional, useful for rationale/order\n\nSuggested audit behavior\n- Current `turn_decisions` table stores only one `selected_agent_id`.\n- For a first pass, keep storing the primary responder there.\n- Put the full selected set/order into `candidate_snapshot_json` or another existing JSON field if needed.\n- Avoid schema migration unless necessary for phase 1.\n\nArena-specific recommendation\nFor Arena rooms, a good initial policy is:\n- `#arena` / `collab`\n  - primary weighted responder\n  - optional second responder only if the message looks broad/open-ended\n- `#arena-debate` / `debate`\n  - builder + skeptic always\n  - synthesizer optional third/final\n- `#arena-synthesis` / `synthesis`\n  - builder and skeptic short analysis\n  - synthesizer final response last\n\nSimplest useful version\nIf minimizing complexity, implement this first:\n- `collab`: unchanged single responder\n- `debate`: exactly 2 responders\n- `synthesis`: exactly 3 responders with synthesizer last when available\nThis gets boardroom behavior where it matters most.\n\nTesting checklist\n1. Verify `#arena` still works after changes.\n2. Verify `#arena-debate` yields multiple sequential replies.\n3. Verify `#arena-synthesis` yields multiple sequential replies with synthesizer last.\n4. Verify `#arena-impl` with `opencode` still behaves correctly.\n5. Verify `solo`, `quiet`, and `mentioned-only` rooms still behave as before.\n6. Check `journalctl --user -u haip-irc.service -n 200 --no-pager` for orchestration errors.\n7. Confirm existing Web UI pages still work.\n\nDefinition of done\n- More than one agent can respond to a single IRC message when room mode requires it.\n- `debate` and `synthesis` no longer fall back to single weighted responder behavior.\n- Arena rooms feel like actual multi-agent collaboration rather than one-at-a-time routing.\n- Existing single-agent modes remain stable.\n\nImportant constraint\n- Keep the implementation understandable for future maintenance.\n- Prefer explicit ordered responder selection over clever autonomous chaining in the first pass.\n- The immediate goal is deterministic, inspectable multi-agent turn planning, not full autonomous swarm behavior.","status":"active","namespace":"shared:platform","namespace_name":"shared","namespace_tier":"platform","tags":[]}