Agent Class
Overview
The Agent is an abstract class for creating autonomous agents. These
agents can perform actions and communicate with other providers. During
instantiation, an agent is initialized with a set of instructions and
can optionally be linked with a database provider.
An Agent works by advancing through a sequence of tasks. It
implements iterator methods (__iter__ and __next__) for this
purpose. Each iteration corresponds to a step of the task that the
Agent has been designed to accomplish. This step could be a
conversation turn, which involves generating a new message from the
‘assistant’ and then parsing the reply from the ‘user’. The run
method can be used to execute these tasks until completion, with the
task being deemed complete when the __next__ method returns
None.
It has abstract properties for fetching its responses, associated conversation, and tools, whose concrete implementation is instantiated by subclasses. It also has an abstract method for setting a database provider, essential for managing conversations with the user.
Usage Example:
The following example shows a basic creation of a subclass of Agent:
class SimpleAgent(Agent):
"""Implements the abstract Agent class for a simple specific agent."""
def __init__(self, instructions: str) -> None:
super().__init__(instructions)
def __iter__(self):
...
def __next__(self) -> str:
...
@property
def conversation(self) -> LLMConversation:
...
@property
def agent_responses(self) -> List[LLMChatMessage]:
...
@property
def tools(self) -> Sequence[Tool]:
...
def run(self) -> str:
...
This example shows a simple implementation of the Agent abstract
class. The ... represents sections of code that must be implemented
to define the specific behaviour of the SimpleAgent.
Limitations
The Agent abstract class doesn’t provide an easy method to modify or
control the flow of execution. It assumes that all tasks are to be
performed in a cyclical manner and that they complete after a specific
number of steps.
Follow-up Questions:
How to handle more complex workflows that require non-linear execution paths?
Is it possible to dynamically adjust the maximum number of iterations based on the task complexity?