feat: Add AgentHive transport (Issue #151)#160
feat: Add AgentHive transport (Issue #151)#160yuzengbaao wants to merge 1 commit intoScottcjn:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new AgentHive transport to the Beacon transport bundle, aiming to support direct integration with AgentHive instances (connect/disconnect, send messages, join swarms), with accompanying unit tests.
Changes:
- Added
AgentHiveTransportimplementation using an async HTTP session. - Exported
AgentHiveTransportfrombeacon_skill.transports. - Introduced
tests/test_agenthive.pycovering basic connect/send/join flows.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
beacon_skill/transports/agenthive.py |
New async transport implementation for AgentHive messaging and swarm joining. |
beacon_skill/transports/__init__.py |
Exposes AgentHiveTransport via the transports package exports. |
tests/test_agenthive.py |
Adds unit tests for connect/disconnect, send_message, and join_swarm. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1,65 @@ | |||
| import logging | |||
| import asyncio | |||
There was a problem hiding this comment.
asyncio is imported but never used in this module, which will trigger linting/static-analysis warnings. Remove the unused import (or use it if there was intended backoff/retry logic).
| import asyncio |
| self.session = aiohttp.ClientSession( | ||
| headers={"Authorization": f"Bearer {self.api_key}"} if self.api_key else {} | ||
| ) |
There was a problem hiding this comment.
Most existing HTTP transports set a User-Agent header on their session (e.g. Moltbook/BoTTube/Claw*), but this ClientSession only sets Authorization. Consider adding a consistent User-Agent (and merging with any caller-provided headers) so outbound requests are identifiable and align with the rest of the transport clients.
| self.session = aiohttp.ClientSession( | |
| headers={"Authorization": f"Bearer {self.api_key}"} if self.api_key else {} | |
| ) | |
| headers: Dict[str, str] = {} | |
| if self.api_key: | |
| headers["Authorization"] = f"Bearer {self.api_key}" | |
| # Ensure a consistent User-Agent so outbound requests are identifiable. | |
| headers.setdefault("User-Agent", "Beacon-AgentHiveTransport/1.0") | |
| self.session = aiohttp.ClientSession(headers=headers) |
| async with self.session.post(url, json=payload) as response: | ||
| if response.status in (200, 201, 202): | ||
| return True | ||
| else: | ||
| text = await response.text() | ||
| logger.error(f"AgentHive send failed: {response.status} - {text}") | ||
| return False | ||
| except Exception as e: | ||
| logger.error(f"AgentHive send error: {e}") | ||
| return False |
There was a problem hiding this comment.
send_message() has multiple important branches that are currently untested: the non-2xx response path (which awaits response.text() and logs details) and the exception handler. Adding tests for these cases would help prevent regressions in error handling (especially since this method returns only True/False, so callers rely on correct failure signaling).
| mock_post = MagicMock() | ||
| mock_response = AsyncMock() | ||
| mock_response.status = 200 | ||
| mock_post.return_value.__aenter__.return_value = mock_response | ||
|
|
||
| agent_hive.session.post = mock_post | ||
|
|
||
| result = await agent_hive.send_message("agent_123", {"text": "hello"}) |
There was a problem hiding this comment.
The mocking of session.post here is not compatible with async with usage in the implementation: MagicMock produces a synchronous __aenter__, but async with requires an awaitable __aenter__/__aexit__. Use an AsyncMock-backed async context manager (and ideally patch aiohttp.ClientSession in connect() to return a mocked session) so the test doesn't depend on a real aiohttp session and the context-manager protocol matches the production code.
| mock_post = MagicMock() | ||
| mock_response = AsyncMock() | ||
| mock_response.status = 200 | ||
| mock_post.return_value.__aenter__.return_value = mock_response | ||
|
|
||
| agent_hive.session.post = mock_post | ||
|
|
||
| result = await agent_hive.join_swarm("swarm_123", {"name": "test_agent"}) |
There was a problem hiding this comment.
Same issue as test_send_message_success: MagicMock does not provide an awaitable __aenter__ for async with. Switch to an async context manager built from AsyncMock (or patch aiohttp.ClientSession.post appropriately) to avoid the test failing at runtime.
| from beacon_skill.transports.agenthive import AgentHiveTransport | ||
|
|
||
| @pytest.fixture | ||
| def agent_hive(): |
There was a problem hiding this comment.
patch is imported but unused in this test module. Either remove it, or (preferred) use it to patch aiohttp.ClientSession so unit tests don't create real sessions/resources.
| def agent_hive(): | |
| @patch("aiohttp.ClientSession", autospec=True) | |
| def agent_hive(mock_client_session): |
| import logging | ||
| import asyncio | ||
| from typing import Dict, Any, Optional | ||
| import aiohttp |
There was a problem hiding this comment.
This module imports aiohttp, but aiohttp is not declared in pyproject.toml project dependencies (only requests, cryptography, etc.). Installing the package from its declared dependencies will therefore fail at import/runtime for AgentHiveTransport. Either add aiohttp to the declared dependencies (or an optional extra) or refactor this transport to use the existing requests/with_retry approach used by other transports.
|
Closing — @yuzengbaao, we have seen a pattern of template/auto-generated PRs from this account across multiple Elyan Labs repos. beacon-skill already has 15 working transports and a complete HeartbeatManager with Ed25519 signing, peer tracking, and on-chain anchoring. New transports need to follow existing patterns in If you want to contribute genuinely: read the existing code, pick ONE transport, and submit a PR that works end-to-end with tests. Quality over quantity. This is Sophia's House — we teach, we don't just reject. But we do require real code. |
Fixes #151 by adding the new
AgentHiveTransportintegrating directly with AgentHive instances out-of-the-box.Changes
beacon_skill/transports/agenthive.pywith full async session handling (connection, disconnect, message sending, and swarm joining).__init__.py.tests/test_agenthive.py).