docs: document how to use agents
ref: N25B-300
This commit is contained in:
@@ -5,7 +5,8 @@ from control_backend.core.agent_system import BaseAgent as CoreBaseAgent
|
|||||||
|
|
||||||
class BaseAgent(CoreBaseAgent):
|
class BaseAgent(CoreBaseAgent):
|
||||||
"""
|
"""
|
||||||
Base agent class for our agents to inherit from.
|
Base agent class for our agents to inherit from. This just ensures
|
||||||
|
all agents have a logger.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger: logging.Logger
|
logger: logging.Logger
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ class BDICoreAgent(BaseAgent):
|
|||||||
new_args = (agentspeak.Literal(arg) for arg in args)
|
new_args = (agentspeak.Literal(arg) for arg in args)
|
||||||
term = agentspeak.Literal(name, new_args)
|
term = agentspeak.Literal(name, new_args)
|
||||||
|
|
||||||
assert self.bdi_agent is not None
|
|
||||||
|
|
||||||
self.bdi_agent.call(
|
self.bdi_agent.call(
|
||||||
agentspeak.Trigger.addition,
|
agentspeak.Trigger.addition,
|
||||||
agentspeak.GoalType.belief,
|
agentspeak.GoalType.belief,
|
||||||
@@ -102,8 +100,6 @@ class BDICoreAgent(BaseAgent):
|
|||||||
new_args = (agentspeak.Literal(arg) for arg in args)
|
new_args = (agentspeak.Literal(arg) for arg in args)
|
||||||
term = agentspeak.Literal(name, new_args)
|
term = agentspeak.Literal(name, new_args)
|
||||||
|
|
||||||
assert self.bdi_agent is not None
|
|
||||||
|
|
||||||
result = self.bdi_agent.call(
|
result = self.bdi_agent.call(
|
||||||
agentspeak.Trigger.removal,
|
agentspeak.Trigger.removal,
|
||||||
agentspeak.GoalType.belief,
|
agentspeak.GoalType.belief,
|
||||||
@@ -121,8 +117,6 @@ class BDICoreAgent(BaseAgent):
|
|||||||
"""
|
"""
|
||||||
Removes all beliefs that match the given `name`.
|
Removes all beliefs that match the given `name`.
|
||||||
"""
|
"""
|
||||||
assert self.bdi_agent is not None
|
|
||||||
|
|
||||||
relevant_groups = []
|
relevant_groups = []
|
||||||
for key in self.bdi_agent.beliefs:
|
for key in self.bdi_agent.beliefs:
|
||||||
if key[0] == name:
|
if key[0] == name:
|
||||||
@@ -142,7 +136,11 @@ class BDICoreAgent(BaseAgent):
|
|||||||
self.logger.debug(f"Removed {removed_count} beliefs.")
|
self.logger.debug(f"Removed {removed_count} beliefs.")
|
||||||
|
|
||||||
def _add_custom_actions(self) -> None:
|
def _add_custom_actions(self) -> None:
|
||||||
"""Add any custom actions here."""
|
"""
|
||||||
|
Add any custom actions here. Inside `@self.actions.add()`, the first argument is
|
||||||
|
the name of the function in the ASL file, and the second the amount of arguments
|
||||||
|
the function expects (which will be located in `term.args`).
|
||||||
|
"""
|
||||||
|
|
||||||
@self.actions.add(".reply", 1)
|
@self.actions.add(".reply", 1)
|
||||||
def _reply(agent, term, intention):
|
def _reply(agent, term, intention):
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ _agent_directory: dict[str, "BaseAgent"] = {}
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class InternalMessage:
|
class InternalMessage:
|
||||||
|
"""
|
||||||
|
Represents a message to an agent.
|
||||||
|
"""
|
||||||
|
|
||||||
to: str
|
to: str
|
||||||
sender: str
|
sender: str
|
||||||
body: str
|
body: str
|
||||||
@@ -16,6 +20,11 @@ class InternalMessage:
|
|||||||
|
|
||||||
|
|
||||||
class AgentDirectory:
|
class AgentDirectory:
|
||||||
|
"""
|
||||||
|
Helper class to keep track of which agents are registered.
|
||||||
|
Used for handling message routing.
|
||||||
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def register(name: str, agent: "BaseAgent"):
|
def register(name: str, agent: "BaseAgent"):
|
||||||
_agent_directory[name] = agent
|
_agent_directory[name] = agent
|
||||||
@@ -26,6 +35,17 @@ class AgentDirectory:
|
|||||||
|
|
||||||
|
|
||||||
class BaseAgent(ABC):
|
class BaseAgent(ABC):
|
||||||
|
"""
|
||||||
|
Abstract base class for all agents. To make a new agent, inherit from
|
||||||
|
`control_backend.agents.BaseAgent`, not this class. That ensures that a
|
||||||
|
logger is present with the correct name pattern.
|
||||||
|
|
||||||
|
When subclassing, the `setup()` method needs to be overwritten. To handle
|
||||||
|
messages from other agents, overwrite the `handle_message()` method. To
|
||||||
|
send messages to other agents, use the `send()` method. To add custom
|
||||||
|
behaviors/tasks to the agent, use the `add_background_task()` method.
|
||||||
|
"""
|
||||||
|
|
||||||
logger: logging.Logger
|
logger: logging.Logger
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
@@ -39,7 +59,7 @@ class BaseAgent(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def setup(self):
|
async def setup(self):
|
||||||
"""Override this to initialize resources."""
|
"""Overwrite this to initialize resources."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def start(self):
|
async def start(self):
|
||||||
@@ -59,6 +79,9 @@ class BaseAgent(ABC):
|
|||||||
self.logger.info(f"Agent {self.name} stopped")
|
self.logger.info(f"Agent {self.name} stopped")
|
||||||
|
|
||||||
async def send(self, message: InternalMessage):
|
async def send(self, message: InternalMessage):
|
||||||
|
"""
|
||||||
|
Sends a message to another agent.
|
||||||
|
"""
|
||||||
target = AgentDirectory.get(message.to)
|
target = AgentDirectory.get(message.to)
|
||||||
if target:
|
if target:
|
||||||
await target.inbox.put(message)
|
await target.inbox.put(message)
|
||||||
@@ -76,7 +99,7 @@ class BaseAgent(ABC):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
async def add_background_task(self, coro):
|
async def add_background_task(self, coro):
|
||||||
"""Helper to run cyclic behaviors."""
|
"""Helper to add a behavior to the agent."""
|
||||||
task = asyncio.create_task(coro)
|
task = asyncio.create_task(coro)
|
||||||
self._tasks.add(task)
|
self._tasks.add(task)
|
||||||
task.add_done_callback(self._tasks.discard)
|
task.add_done_callback(self._tasks.discard)
|
||||||
|
|||||||
Reference in New Issue
Block a user