Skip to Content
Enthusiast 1.3.0 is released 🎉

Builder

The Builder pattern in Enthusiast provides a systematic approach to constructing complex agent instances with all their dependencies. The system consists of an abstract BaseAgentBuilder class that defines the construction interface and a concrete AgentBuilder implementation that handles the specific construction logic.

Overview

The Builder system serves several key purposes:

  • Complex Object Construction: Manages the creation of agents with multiple dependencies
  • Dependency Resolution: Handles the creation and configuration of all agent components
  • Configuration Management: Translates configuration objects into concrete instances
  • Resource Assembly: Coordinates the assembly of tools, memory systems, and services

Base Agent Builder

Abstract Interface

The BaseAgentBuilder defines the contract that all agent builders must implement:

class BaseAgentBuilder(ABC, Generic[ConfigT]): def __init__(self, config: ConfigT, conversation_id: Any, streaming: bool = False): self._llm = None self._embeddings_registry = None self._data_set_id = None self._injector = None self._config = config self.conversation_id = conversation_id self.streaming = streaming def build(self) -> BaseAgent: """Main build method that orchestrates the construction process""" # Build sequence implementation...

Build Process

The main build() method orchestrates the construction process:

def build(self) -> BaseAgent: # 1. Build registries and repositories model_registry = self._build_db_models_registry() self._build_and_set_repositories(model_registry) self._data_set_id = self._repositories.conversation.get_data_set_id(self.conversation_id) # 2. Build core components self._llm = self._build_llm(self._config.llm) self._embeddings_registry = self._build_embeddings_registry() self._injector = self._build_injector() # 3. Build tools and handlers tools = self._build_tools(default_llm=self._llm, injector=self._injector) agent_callback_handler = self._build_agent_callback_handler() prompt_template = self._build_prompt_template() # 4. Create and configure agent agent_instance = self._build_agent(tools, self._llm, prompt_template, agent_callback_handler) self._inject_additional_arguments(agent_instance) return agent_instance

Abstract Methods

The base builder defines several abstract methods that concrete implementations must provide:

Core Construction Methods

@abstractmethod def _build_agent( self, tools: list[BaseTool], llm: BaseLanguageModel, prompt: PromptTemplate | ChatMessagePromptTemplate, callback_handler: BaseCallbackHandler, ) -> BaseAgent: """Build the final agent instance""" pass @abstractmethod def _build_injector(self) -> BaseInjector: """Build the dependency injection container""" pass @abstractmethod def _build_prompt_template(self) -> BasePromptTemplate: """Build the prompt template for the agent""" pass

Registry and Repository Methods

@abstractmethod def _build_llm_registry(self) -> BaseLanguageModelRegistry: """Build the language model registry""" pass @abstractmethod def _build_db_models_registry(self) -> BaseDBModelsRegistry: """Build the database models registry""" pass @abstractmethod def _build_and_set_repositories(self, models_registry: BaseDBModelsRegistry) -> None: """Build and configure data repositories""" pass @abstractmethod def _build_embeddings_registry(self) -> BaseEmbeddingProviderRegistry: """Build the embeddings provider registry""" pass

Component Construction Methods

@abstractmethod def _build_llm(self, llm_config: LLMConfig) -> BaseLanguageModel: """Build the language model instance""" pass @abstractmethod def _build_default_llm(self) -> BaseLanguageModel: """Build the default language model for tools""" pass @abstractmethod def _build_tools(self, default_llm: BaseLanguageModel, injector: BaseInjector) -> list[BaseTool]: """Build all agent tools""" pass @abstractmethod def _build_function_tool(self, config: FunctionToolConfig) -> BaseFunctionTool: """Build function-based tools""" pass @abstractmethod def _build_llm_tool(self, config: LLMToolConfig, default_llm: BaseLanguageModel, injector: BaseInjector) -> BaseLLMTool: """Build LLM-powered tools""" pass @abstractmethod def _build_agent_tool(self, config: AgentToolConfig) -> BaseAgentTool: """Build agent-based tools""" pass

Memory and Callback Methods

@abstractmethod def _build_agent_callback_handler(self) -> Optional[BaseCallbackHandler]: """Build the agent callback handler""" pass @abstractmethod def _build_llm_callback_handlers(self) -> Optional[BaseCallbackHandler]: """Build LLM callback handlers""" pass @abstractmethod def _build_chat_summary_memory(self) -> BaseMemory: """Build summary-based chat memory""" pass @abstractmethod def _build_chat_limited_memory(self) -> BaseMemory: """Build limited chat memory""" pass

Runtime Configuration Injection

The builder automatically injects runtime configuration into constructed agents:

def _inject_additional_arguments(self, agent_instance: BaseAgent) -> None: """Inject runtime configuration from the database""" agent_configuration_id = self._repositories.conversation.get_agent_id(self.conversation_id) runtime_arguments = self._repositories.agent.get_agent_configuration_by_id(agent_configuration_id) agent_instance.set_runtime_arguments(runtime_arguments)

Agent Builder Implementation

Concrete Implementation

The AgentBuilder class provides the concrete implementation of all abstract methods, which will be a default builder for all agents, unless custom one is provided:

Usage Patterns

Basic Usage

# Create builder with configuration builder = AgentBuilder( config=agent_config, conversation_id="conversation_123", streaming=False ) # Build the agent agent = builder.build() # Use the agent response = agent.get_answer("Hello, how can you help me?")

Summary

The Builder system in Enthusiast provides a comprehensive and flexible approach to agent construction:

  • BaseAgentBuilder: Abstract interface defining the construction contract
  • AgentBuilder: Concrete implementation handling all construction details
  • Systematic Construction: Step-by-step assembly of all agent components
  • Configuration-Driven: All construction driven by configuration objects
  • Dependency Management: Automatic resolution and assembly of dependencies
  • Runtime Configuration: Dynamic configuration injection after construction
  • Extensibility: Easy creation of custom builders for specialized agents

By using the Builder pattern, Enthusiast ensures that complex agents are constructed consistently, reliably, and with all necessary dependencies properly configured and connected.

Last updated on