Developing Agents
Learn how to implement custom Agent logic for your Genbase Kits by extending the BaseAgent class.
While Genbase provides built-in agents like TaskerAgent, you can create custom Agents within your Kit to implement specialized logic, control conversation flow more precisely, or manage unique internal states for your Profiles.
When to Create a Custom Agent
Consider creating a custom agent when:
- You need fine-grained control over the interaction flow beyond what built-in agents offer.
- The agent needs to maintain specific internal state or memory across multiple turns within a Profile session.
- You require complex decision-making logic about when to call LLMs versus Tools.
- You want to implement custom parsing of user input or formatting of outputs.
- You need specialized Internal Tools specific to the agent's logic.
If your Profile primarily involves straightforward task execution based on user requests (like running a sequence of predefined Tools), a built-in agent like TaskerAgent might be sufficient.
Implementation Basics
- Location: Place your custom agent Python code within the
agents/directory of your Kit. - Inheritance: Your custom agent class must inherit from
engine.services.agents.base_agent.BaseAgent. - Core Methods:
- Implement the
@property def agent_type(self) -> str:method. This must return the uniquenameyou assign to this agent definition in yourkit.yaml'sagents:section. - Implement the
async def process_request(self, context: AgentContext, profile_data: ProfileMetadataResult) -> Dict[str, Any]:method. This is the main entry point where your agent receives user input and orchestrates the response.
- Implement the
- Registration: Declare your custom agent in the
agents:section of yourkit.yamlfile, providing a uniquenameand theclassname. Link it to one or more Profiles using theagent:field within theprofiles:section. (See kit.yaml Reference).
Example (agents/my_custom_agent.py):
Corresponding kit.yaml Snippet:
Using BaseAgent Capabilities
Your custom agent inherits useful methods and properties from BaseAgent:
self.set_context(...): Define the system prompt and which tools (Kit-defined, Provided, Internal) are available as tools for the LLM. UseIncludeOptionsfor fine-grained control.self.create(...): Make calls to the configured LLM. Handles message history automatically. Can execute tool calls requested by the LLM ifrun_tools=True.self.create_structured(...): Call the LLM expecting a Pydantic model as output.self.run_tool(name, params): Manually execute a specific Kit Tool or Provided Tool.self.add_message(...): Manually add messages (user, assistant, tool) to the chat history for the current session.self.get_messages(): Retrieve the current chat history list.self.utils: AccessAgentUtilsfor file operations within the Module's workspace (read_file,write_file,list_files, etc.).self.get_store(collection_name): Get aProfileStoreServiceinstance to store/retrieve key-value data specific to this module, profile, and a named collection.self.tool_manager: (Advanced) Interact with the manager for Internal Tools defined on the agent class itself.
State Management
For simple state within a single process_request call, use local variables. For state that needs to persist across multiple turns within the same chat session, use agent instance variables (self.my_state). For state that needs to persist across different sessions or different profiles within the same Module, use the ProfileStoreService (self.get_store(...)).
Developing custom agents gives you maximum flexibility in defining how users interact with your Kit's capabilities. Remember to clearly define the agent's purpose and link it correctly in your kit.yaml.