From 1f9926fe00d6216b8cc580d580fb7c10b1b94694 Mon Sep 17 00:00:00 2001 From: Kasper Date: Sat, 22 Nov 2025 10:28:52 +0100 Subject: [PATCH] chore: apply suggestion Changed `add_background_task` to `add_behavior` and added extra docs. --- .../agents/actuation/robot_speech_agent.py | 2 +- .../agents/bdi/bdi_core_agent/bdi_core_agent.py | 2 +- .../agents/communication/ri_communication_agent.py | 2 +- .../transcription_agent/transcription_agent.py | 2 +- src/control_backend/agents/perception/vad_agent.py | 2 +- src/control_backend/core/agent_system.py | 12 +++++++++--- .../agents/perception/vad_agent/test_vad_agent.py | 6 +++--- .../unit/agents/actuation/test_robot_speech_agent.py | 4 ++-- .../communication/test_ri_communication_agent.py | 6 +++--- .../transcription_agent/test_transcription_agent.py | 2 +- test/unit/core/test_agent_system.py | 2 +- 11 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/control_backend/agents/actuation/robot_speech_agent.py b/src/control_backend/agents/actuation/robot_speech_agent.py index 048da35..48316b9 100644 --- a/src/control_backend/agents/actuation/robot_speech_agent.py +++ b/src/control_backend/agents/actuation/robot_speech_agent.py @@ -45,7 +45,7 @@ class RobotSpeechAgent(BaseAgent): self.subsocket.connect(settings.zmq_settings.internal_sub_address) self.subsocket.setsockopt(zmq.SUBSCRIBE, b"command") - await self.add_background_task(self._zmq_command_loop()) + await self.add_behavior(self._zmq_command_loop()) self.logger.info("Finished setting up %s", self.name) diff --git a/src/control_backend/agents/bdi/bdi_core_agent/bdi_core_agent.py b/src/control_backend/agents/bdi/bdi_core_agent/bdi_core_agent.py index ec88282..6421383 100644 --- a/src/control_backend/agents/bdi/bdi_core_agent/bdi_core_agent.py +++ b/src/control_backend/agents/bdi/bdi_core_agent/bdi_core_agent.py @@ -31,7 +31,7 @@ class BDICoreAgent(BaseAgent): await self._load_asl() # Start the BDI cycle loop - await self.add_background_task(self._bdi_loop()) + await self.add_behavior(self._bdi_loop()) self.logger.debug("Setup complete.") async def _load_asl(self): diff --git a/src/control_backend/agents/communication/ri_communication_agent.py b/src/control_backend/agents/communication/ri_communication_agent.py index b37d160..02a457d 100644 --- a/src/control_backend/agents/communication/ri_communication_agent.py +++ b/src/control_backend/agents/communication/ri_communication_agent.py @@ -37,7 +37,7 @@ class RICommunicationAgent(BaseAgent): if await self._negotiate_connection(): self.connected = True - await self.add_background_task(self._listen_loop()) + await self.add_behavior(self._listen_loop()) else: self.logger.warning("Failed to negotiate connection during setup.") diff --git a/src/control_backend/agents/perception/transcription_agent/transcription_agent.py b/src/control_backend/agents/perception/transcription_agent/transcription_agent.py index d9aca49..d3114ed 100644 --- a/src/control_backend/agents/perception/transcription_agent/transcription_agent.py +++ b/src/control_backend/agents/perception/transcription_agent/transcription_agent.py @@ -37,7 +37,7 @@ class TranscriptionAgent(BaseAgent): self.speech_recognizer.load_model() # Warmup # Start background loop - await self.add_background_task(self._transcribing_loop()) + await self.add_behavior(self._transcribing_loop()) self.logger.info("Finished setting up %s", self.name) diff --git a/src/control_backend/agents/perception/vad_agent.py b/src/control_backend/agents/perception/vad_agent.py index 667d6db..b257137 100644 --- a/src/control_backend/agents/perception/vad_agent.py +++ b/src/control_backend/agents/perception/vad_agent.py @@ -93,7 +93,7 @@ class VADAgent(BaseAgent): # Warmup/reset await self.reset_stream() - await self.add_background_task(self._streaming_loop()) + await self.add_behavior(self._streaming_loop()) # Start agents dependent on the output audio fragments here transcriber = TranscriptionAgent(audio_out_address) diff --git a/src/control_backend/core/agent_system.py b/src/control_backend/core/agent_system.py index e308b4c..4828553 100644 --- a/src/control_backend/core/agent_system.py +++ b/src/control_backend/core/agent_system.py @@ -1,6 +1,7 @@ import asyncio import logging from abc import ABC, abstractmethod +from collections.abc import Coroutine from dataclasses import dataclass # Central directory to resolve agent names to instances @@ -69,7 +70,7 @@ class BaseAgent(ABC): await self.setup() # Start processing inbox - await self.add_background_task(self._process_inbox()) + await self.add_behavior(self._process_inbox()) async def stop(self): """Stops the agent.""" @@ -98,8 +99,13 @@ class BaseAgent(ABC): """Override this to handle incoming messages.""" raise NotImplementedError - async def add_background_task(self, coro): - """Helper to add a behavior to the agent.""" + async def add_behavior(self, coro: Coroutine): + """ + Helper to add a behavior to the agent. To add asynchronous behavior to an agent, define + an `async` function and add it to the task list by calling :func:`add_background_task` + with it. This should happen in the :func:`setup` method of the agent. For an example, see: + :func:`~control_backend.agents.bdi.BDICoreAgent`. + """ task = asyncio.create_task(coro) self._tasks.add(task) task.add_done_callback(self._tasks.discard) diff --git a/test/integration/agents/perception/vad_agent/test_vad_agent.py b/test/integration/agents/perception/vad_agent/test_vad_agent.py index 20a388c..2b83eae 100644 --- a/test/integration/agents/perception/vad_agent/test_vad_agent.py +++ b/test/integration/agents/perception/vad_agent/test_vad_agent.py @@ -42,7 +42,7 @@ async def test_normal_setup(per_transcription_agent): async def swallow_background_task(coro): coro.close() - per_vad_agent.add_background_task = swallow_background_task + per_vad_agent.add_behavior = swallow_background_task per_vad_agent.reset_stream = AsyncMock() await per_vad_agent.setup() @@ -110,7 +110,7 @@ async def test_out_socket_creation_failure(zmq_context): async def swallow_background_task(coro): coro.close() - per_vad_agent.add_background_task = swallow_background_task + per_vad_agent.add_behavior = swallow_background_task await per_vad_agent.setup() @@ -130,7 +130,7 @@ async def test_stop(zmq_context, per_transcription_agent): async def swallow_background_task(coro): coro.close() - per_vad_agent.add_background_task = swallow_background_task + per_vad_agent.add_behavior = swallow_background_task zmq_context.return_value.socket.return_value.bind_to_random_port.return_value = random.randint( 1000, 10000, diff --git a/test/unit/agents/actuation/test_robot_speech_agent.py b/test/unit/agents/actuation/test_robot_speech_agent.py index b5dd166..1ec2c6f 100644 --- a/test/unit/agents/actuation/test_robot_speech_agent.py +++ b/test/unit/agents/actuation/test_robot_speech_agent.py @@ -35,7 +35,7 @@ async def test_setup_bind(zmq_context, mocker): coro.close() swallow = Swallow() - agent.add_background_task = swallow + agent.add_behavior = swallow await agent.setup() @@ -62,7 +62,7 @@ async def test_setup_connect(zmq_context, mocker): coro.close() swallow = Swallow() - agent.add_background_task = swallow + agent.add_behavior = swallow await agent.setup() diff --git a/test/unit/agents/communication/test_ri_communication_agent.py b/test/unit/agents/communication/test_ri_communication_agent.py index 6f0492b..20b9379 100644 --- a/test/unit/agents/communication/test_ri_communication_agent.py +++ b/test/unit/agents/communication/test_ri_communication_agent.py @@ -55,7 +55,7 @@ async def test_setup_success_connects_and_starts_robot(zmq_context): coro.close() swallow = Swallow() - agent.add_background_task = swallow + agent.add_behavior = swallow await agent.setup() @@ -85,7 +85,7 @@ async def test_setup_binds_when_requested(zmq_context): coro.close() swallow = Swallow() - agent.add_background_task = swallow + agent.add_behavior = swallow with patch(speech_agent_path(), autospec=True) as MockRobot: MockRobot.return_value.start = AsyncMock() @@ -213,7 +213,7 @@ async def test_setup_warns_on_failed_negotiate(zmq_context, mocker): async def swallow(coro): coro.close() - agent.add_background_task = swallow + agent.add_behavior = swallow agent._negotiate_connection = AsyncMock(return_value=False) await agent.setup() diff --git a/test/unit/agents/perception/transcription_agent/test_transcription_agent.py b/test/unit/agents/perception/transcription_agent/test_transcription_agent.py index 4a5d928..2458ad1 100644 --- a/test/unit/agents/perception/transcription_agent/test_transcription_agent.py +++ b/test/unit/agents/perception/transcription_agent/test_transcription_agent.py @@ -36,7 +36,7 @@ async def test_transcription_agent_flow(mock_zmq_context): agent.send = AsyncMock() agent._running = True - agent.add_background_task = AsyncMock() + agent.add_behavior = AsyncMock() await agent.setup() diff --git a/test/unit/core/test_agent_system.py b/test/unit/core/test_agent_system.py index ee26c48..001ead3 100644 --- a/test/unit/core/test_agent_system.py +++ b/test/unit/core/test_agent_system.py @@ -34,7 +34,7 @@ async def test_agent_lifecycle(): async def dummy_task(): await asyncio.sleep(0.01) - await agent.add_background_task(dummy_task()) + await agent.add_behavior(dummy_task()) assert len(agent._tasks) > 0 # Wait for task to finish