Welcome to the Agent Methods guide! This section provides an in-depth look at the key methods within the Agent
base class of AgentForge. Understanding these methods is crucial for creating custom agents by subclassing the Agent
class, allowing you to extend and customize agent behaviors effectively.
The Agent
base class provides a robust template for building agents in AgentForge. By subclassing Agent
, you inherit default functionalities and can override methods to tailor agent behaviors to your specific needs.
Why Override Methods?
- Customization: Adapt agent behaviors to perform specific tasks.
- Specialization: Implement unique processing logic or data handling.
- Extensibility: Add new functionalities without altering the base class.
For better understanding, we've grouped the methods into the following categories:
- Core Workflow Method
- Data Loading Methods
- Data Processing Method
- Prompt Generation Method
- LLM Interaction Method
- Result Handling Methods
- Storage Methods
- Customization Hooks
Purpose: The central method that orchestrates the agent's workflow, executing a sequence of steps to generate the final output.
Workflow Steps:
- Load Data:
self.load_data(**kwargs)
- Process Data:
self.process_data()
- Generate Prompt:
self.generate_prompt()
- Run LLM:
self.run_llm()
- Parse Result:
self.parse_result()
- Save to Storage:
self.save_to_storage()
- Build Output:
self.build_output()
- Cleanup: Clears
self.data
to free up memory.
Usage:
- Call
run()
with any necessary keyword arguments. - The method handles error logging and returns the final output or
None
if an error occurs.
Example:
from agentforge.agent import Agent
class CustomAgent(Agent):
pass
agent = CustomAgent()
output = agent.run(user_input="Hello, AgentForge!")
print(output)
These methods handle loading various types of data into the agent.
Purpose: Centralizes the data loading process, orchestrating the loading of agent configurations, persona data, storage initialization, and any additional data.
What It Does:
- Loads Agent Configuration Data:
self.load_agent_data()
- Loads Persona Data:
self.load_persona_data()
- Resolves Storage:
self.resolve_storage()
- Loads Data from Storage:
self.load_from_storage()
- Loads Additional Data:
self.load_additional_data()
- Loads Keyword Arguments:
self.load_kwargs(**kwargs)
When to Override:
- Typically, you don't need to override this method. Instead, override the specific data loading methods as needed.
Purpose: Loads the agent's configuration data, including parameters and prompts, and updates self.data
accordingly.
What It Does:
- Retrieves agent data using the
Config
class. - Updates
self.data
with parameters (params
) and prompt templates (prompts
).
Usage:
- Automatically called by
load_data()
.
Purpose: Loads persona-specific data, enriching the agent's context.
What It Does:
- Checks if personas are enabled in the system settings.
- If enabled, loads persona data and updates
self.data
with persona attributes.
Usage:
- Automatically called by
load_data()
.
Purpose: Initializes the storage system for the agent if storage is enabled in the system settings.
What It Does:
- Checks if storage is enabled.
- If enabled, initializes the storage instance and stores it in
self.agent_data['storage']
.
Usage:
- Automatically called by
load_data()
.
Purpose: Placeholder for loading data from storage systems.
Usage:
- Override this method if your agent needs to load data from a database or file system.
Example Override:
def load_from_storage(self):
collection_name = 'Memories' # Name of the collection in the vector database
query = 'User is thinking about planning a trip' # A text query to search the specified collection
self.data['stored_values'] = self.agent_data['storage'].query_memory(collection_name, query)
Purpose: Placeholder for loading any additional data required by the agent.
Usage:
- Override this method to load custom data necessary for your agent's operation.
Example Override:
def load_additional_data(self):
self.data['timestamp'] = datetime.now().isoformat()
Purpose: Loads variables passed as keyword arguments into self.data
.
What It Does:
- Iterates over
**kwargs
and updatesself.data
with the provided key-value pairs.
Usage:
- Automatically called by
load_data()
.
Example:
def load_kwargs(self, **kwargs):
self.data.update(kwargs)
Purpose: Processes the loaded data before it's used in prompt generation.
Default Behavior: Does nothing by default.
Usage:
- Override this method to implement custom data processing logic.
Example Override:
def process_data(self):
# Convert user input to uppercase
self.data['user_input'] = self.data['user_input'].upper()
Purpose: Renders the prompt templates using the variables loaded in self.data
.
What It Does:
- Retrieves prompt templates from
self.data['prompts']
. - Uses
PromptHandling
to:- Check the format of the prompts.
- Render the prompts with current data.
- Validate the rendered prompts.
- Stores the rendered prompts in
self.prompt
.
Usage:
- Automatically called by
run()
.
When to Override:
- Typically, you don't need to override this method. Only override it if you need custom prompt rendering logic.
Purpose: Executes the language model using the generated prompts.
What It Does:
- Retrieves the LLM instance from
self.agent_data['llm']
. - Retrieves parameters from
self.agent_data.get('params', {})
. - Adds
agent_name
to the parameters. - Calls
generate_text
on the LLM with the prompts and parameters. - Stores the result in
self.result
.
Usage:
- Automatically called by
run()
.
When to Override:
- Typically, you don't need to override this method. Only override it if you need simulate an LLM response.
Example Override:
def run_llm(self):
# Custom LLM execution
self.result = "Simulated LLM output"
Purpose: Parses the raw result from the LLM.
Default Behavior: Does nothing by default.
Usage:
- Override this method to implement custom parsing logic.
Example Override:
def parse_result(self):
self.result = json.loads(self.result)
Purpose: Constructs the final output from the processed data.
Default Behavior:
- Sets
self.output = self.result
Usage:
- Automatically called by
run()
.
When to Override:
- To customize the final output format.
Example Override:
def build_output(self):
self.output = f"Processed Output: {self.result}"
Purpose: Placeholder for saving data to storage.
Default Behavior: Does nothing by default.
Usage:
- Override this method if your agent needs to save data persistently.
Notes:
- The storage instance is available at
self.agent_data['storage']
. - Ensure that storage is enabled in the system settings (
StorageEnabled: true
).
Example Override:
def save_to_storage(self):
data = self.result
metadata = {'timestamp': datetime.now().isoformat()}
self.agent_data['storage'].save_memory(collection_name='Results', data=data, metadata=metadata)
These methods are designed to be overridden to customize agent behavior:
load_from_storage()
load_additional_data()
process_data()
parse_result()
save_to_storage()
build_output()
By overriding these methods, you can inject custom logic at various points in the agent's workflow.
Let's create a custom agent that performs sentiment analysis on user input using an LLM. This example shows how to override methods to customize agent behavior.
# sentiment_agent.py
from agentforge.agent import Agent
class SentimentAgent(Agent):
def process_data(self):
# Clean the user input by stripping leading/trailing whitespace
self.data['cleaned_input'] = self.data['user_input'].strip()
def parse_result(self):
# Simplify the LLM's response to extract the sentiment
response = self.result.lower()
if 'positive' in response:
sentiment = 'Positive'
elif 'negative' in response:
sentiment = 'Negative'
elif 'neutral' in response:
sentiment = 'Neutral'
else:
sentiment = 'Undetermined'
self.result = sentiment
def build_output(self):
# Build the final output message
self.output = f"Sentiment Analysis Result: {self.result}"
Place this YAML file in the .agentforge/prompts/
directory.
Prompts:
System: You are a sentiment analysis assistant.
User: |+
Determine if the sentiment of the following text is Positive, Negative, or Neutral.
Text: "{cleaned_input}"
# run_sentiment_agent.py
from sentiment_agent import SentimentAgent
# Initialize the agent
agent = SentimentAgent()
# User input
user_input = " I absolutely love using AgentForge! "
# Run the agent with the user input
response = agent.run(user_input=user_input)
# Print the output
print(response)
Sentiment Analysis Result: Positive
Overridden Methods:
-
process_data(self)
- Purpose: Cleans the user input before it's used in the prompt.
- What It Does: Strips any leading or trailing whitespace from
self.data['user_input']
and stores it inself.data['cleaned_input']
.
-
parse_result(self)
- Purpose: Parses the LLM's response to extract the sentiment.
- What It Does: Checks the LLM's response for keywords 'positive', 'negative', or 'neutral' and assigns the corresponding sentiment to
self.result
.
-
build_output(self)
- Purpose: Constructs the final output to present to the user.
- What It Does: Formats the output message using the parsed sentiment.
Key Points:
- Custom Data Processing: By cleaning the user input in
process_data
, we ensure the prompt receives properly formatted text. - Prompt Template: Uses
{cleaned_input}
to insert the processed input into the prompt. - Output Construction: Presents a clear and concise result to the user.
- Start Simple: Begin by subclassing
Agent
without overriding any methods. Ensure your basic agent works before adding complexity. - Override as Needed: Only override methods that require custom logic for your agent's purpose.
- Test Each Step: After overriding a method, test your agent to ensure it behaves as expected.
- Use Descriptive Names: Name your agents and variables clearly to enhance readability.
- Leverage Inheritance: Remember that your custom agent inherits all methods from
Agent
. You can callsuper()
to utilize base class functionality.
The Agent
class utilizes additional utilities that assist with tasks such as:
- Prompt Handling: Managed by
self.prompt_handling
. - Logging: Managed by
self.logger
. - Configuration Management: Managed by
self.config
. - Data Storage: Available via
self.agent_data['storage']
if storage is enabled.
For more details, refer to the respective documentation:
By understanding and utilizing these methods, you can create powerful custom agents tailored to your specific needs. The Agent
base class provides a flexible foundation, and by selectively overriding methods, you can extend and customize agent behaviors efficiently.
- Explore More: Check out the Custom Agents Guide for further insights into creating specialized agents.
- Dive into Utilities: Learn about the utility classes and functions in the Utilities Overview.
- Understand Prompts: Review the Agent Prompts Guide to master crafting effective prompts.
Need Help?
If you have questions or need assistance, feel free to reach out:
- Email: [email protected]
- Discord: Join our Discord Server