Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions docs/content/docs/agents/agent-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ class AgentConfig(ArbitraryTypeBaseModel, Generic[InjectorT]):
retrievers: RetrieversConfig
injector: Type[InjectorT]
registry: RegistryConfig
prompt_template: Optional[PromptTemplateConfig] = None
chat_prompt_template: Optional[ChatPromptTemplateConfig] = None
system_prompt: str
tools: Optional[list[FunctionToolConfig | LLMToolConfig | AgentToolConfig]] = None
agent_callback_handler: Optional[AgentCallbackHandlerConfig] = None
```
Expand Down Expand Up @@ -81,11 +80,10 @@ class AgentConfig(ArbitraryTypeBaseModel, Generic[InjectorT]):
- `embeddings`: Embedding provider registry configuration
- `model`: Database model registry configuration

#### 7. **prompt_template** / **chat_prompt_template**
- **Type**: `PromptTemplateConfig` or `ChatPromptTemplateConfig`
- **Required**: Exactly one must be provided
- **Description**: Prompt configuration for agent behavior and instructions
- **Validation**: The system ensures exactly one prompt type is configured
#### 7. **system_prompt**
- **Type**: `str`
- **Required**: Yes
- **Description**: The system prompt passed to the agent. May contain `{variable}` placeholders resolved via the agent's `_get_system_prompt_variables()` hook.

#### 8. **tools**
- **Type**: `Optional[list[FunctionToolConfig | LLMToolConfig | AgentToolConfig]]`
Expand Down
70 changes: 43 additions & 27 deletions docs/content/docs/agents/agent-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,12 @@ class ExampleAgent(BaseAgent):
]
```

Those arguments can be accessed by agent like this:
Those arguments can be accessed inside the agent. For example, `_get_system_prompt_variables()` is called before each invocation to resolve `{variable}` placeholders in the system prompt:

```python

def get_answer(self, input_text: str) -> str:
agent_output = self._agent_executor.invoke(
{"input": input_text, "product_type": self.PROMPT_INPUT.product_type}
)
return agent_output["output"]
def _get_system_prompt_variables(self) -> dict:
return {"output_format": self.PROMPT_INPUT.output_format}

```

Expand All @@ -107,38 +104,57 @@ The `BaseToolCallingAgent` implements the standard tool calling pattern, leverag
```python
class BaseToolCallingAgent(BaseAgent):
def get_answer(self, input_text: str) -> str:
# Build and execute the agent
agent_executor = self._build_agent_executor()
response = agent_executor.invoke(
{"input": input_text},
config=self._build_invoke_config()
history = self._injector.chat_history

# Trim history to token budget and append current user message
agent = self._build_agent()
limited_history = self._build_limited_history(history)
input_messages = limited_history + [HumanMessage(content=input_text)]

# Execute the agent with the full message list
result = agent.invoke({"messages": input_messages}, config=self._build_invoke_config())

# Slice off only the new messages produced this turn, then persist them
new_messages = result["messages"][len(limited_history):]
final_message = next(
m for m in reversed(new_messages)
if isinstance(m, AIMessage) and not m.tool_calls
)
return response["output"]
history.add_messages(new_messages)
return final_message.text

def _build_tools(self) -> list[BaseTool]:
"""Convert internal tools to LangChain tools"""
"""Convert internal tools to LangChain BaseTool instances."""
return [tool.as_tool() for tool in self._tools]

def _build_memory(self) -> BaseMemory:
"""Use limited memory for ReAct reasoning"""
return self._injector.chat_limited_memory

def _build_invoke_config(self) -> dict[str, Any]:
"""Configure callback handlers"""
"""Pass callback handler to the agent invocation if one is configured."""
if self._callback_handler:
return {"callbacks": [self._callback_handler]}
return {}

def _build_agent_executor(self) -> AgentExecutor:
"""Create the LangChain agent executor"""
tools = self._build_tools()
agent = create_tool_calling_agent(
tools=tools,
llm=self._llm,
prompt=self._prompt,
def _build_limited_history(self, history: BaseChatMessageHistory) -> list[BaseMessage]:
"""Trim conversation history to MAX_HISTORY_TOKENS using the LLM as the token counter."""
return trim_messages(
history.messages,
strategy="last",
token_counter=self._llm,
max_tokens=MAX_HISTORY_TOKENS,
start_on=HumanMessage,
include_system=True,
allow_partial=False,
)
return AgentExecutor(
agent=agent, tools=tools, verbose=True, memory=self._build_memory(), return_intermediate_steps=True

def _get_system_prompt(self) -> str:
"""Resolve template variables in the system prompt string via _get_system_prompt_variables()."""
return self._system_prompt.format(**self._get_system_prompt_variables())

def _build_agent(self):
"""Build a LangGraph agent with the configured LLM, tools, and system prompt."""
return create_agent(
model=self._llm,
tools=self._build_tools(),
system_prompt=self._get_system_prompt(),
)
```

Expand Down
21 changes: 2 additions & 19 deletions docs/content/docs/agents/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,9 @@ def build(self) -> BaseAgent:
# 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)
agent_instance = self._build_agent(tools, self._llm, agent_callback_handler)
self._inject_additional_arguments(agent_instance)

return agent_instance
Expand All @@ -77,7 +76,6 @@ def _build_agent(
self,
tools: list[BaseTool],
llm: BaseLanguageModel,
prompt: PromptTemplate | ChatMessagePromptTemplate,
callback_handler: BaseCallbackHandler,
) -> BaseAgent:
"""Build the final agent instance"""
Expand All @@ -87,11 +85,6 @@ def _build_agent(
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
Expand Down Expand Up @@ -152,7 +145,7 @@ def _build_agent_tool(self, config: AgentToolConfig) -> BaseAgentTool:
pass
```

#### Memory and Callback Methods
#### Callback Methods

```python
@abstractmethod
Expand All @@ -164,16 +157,6 @@ def _build_agent_callback_handler(self) -> Optional[BaseCallbackHandler]:
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
Expand Down
58 changes: 20 additions & 38 deletions docs/content/docs/agents/injector.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,7 @@ class BaseInjector(ABC):

@property
@abstractmethod
def chat_summary_memory(self) -> BaseMemory:
pass

@property
@abstractmethod
def chat_limited_memory(self) -> BaseMemory:
def chat_history(self) -> BaseChatMessageHistory:
pass
```

Expand All @@ -58,14 +53,12 @@ class Injector(BaseInjector):
document_retriever: BaseVectorStoreRetriever[DocumentChunk],
product_retriever: BaseProductRetriever,
repositories: RepositoriesInstances,
chat_summary_memory: SummaryChatMemory,
chat_limited_memory: LimitedChatMemory,
chat_history: BaseChatMessageHistory,
):
super().__init__(repositories)
self._document_retriever = document_retriever
self._product_retriever = product_retriever
self._chat_summary_memory = chat_summary_memory
self._chat_limited_memory = chat_limited_memory
self._chat_history = chat_history

@property
def document_retriever(self) -> BaseVectorStoreRetriever[DocumentChunk]:
Expand All @@ -76,12 +69,8 @@ class Injector(BaseInjector):
return self._product_retriever

@property
def chat_summary_memory(self) -> SummaryChatMemory:
return self._chat_summary_memory

@property
def chat_limited_memory(self) -> LimitedChatMemory:
return self._chat_limited_memory
def chat_history(self) -> BaseChatMessageHistory:
return self._chat_history
```

## Available Resources
Expand All @@ -94,9 +83,9 @@ The document retriever provides access to document content through vector search

The product retriever provides access to product information:

### 3. Chat Memory Systems
### 3. Chat History

The injector provides access to two types of memory systems Summary Chat Memory and Limited Chat Memory:
The injector provides access to the persistent conversation history via `chat_history: BaseChatMessageHistory`. See [Memory](./memory.md) for details on token limiting and persistence.


### 4. Repository Access
Expand Down Expand Up @@ -150,15 +139,14 @@ class ExampleTool(BaseLLMTool):
Agents receive the injector during construction and can access all resources:

```python
class ExampleAgent(BaseAgent):
def _build_agent_executor(self) -> AgentExecutor:
tools = self._build_tools()
agent = create_tool_calling_agent(
tools=tools,
llm=self._llm,
prompt=self._prompt,
)
return AgentExecutor(agent=agent, tools=tools, memory=self.injector.chat_limited_memory)
class ExampleAgent(BaseToolCallingAgent):
def get_answer(self, input_text: str) -> str:
# Fetch relevant documents before invoking the agent
# and inject them as additional context into the user message
docs = self._injector.document_retriever.find_content_matching_query(input_text)
context = "\n".join(doc.content for doc in docs)
enriched_input = f"{input_text}\n\nContext:\n{context}"
return super().get_answer(enriched_input)

```

Expand All @@ -173,16 +161,14 @@ def _build_injector(self) -> BaseInjector:
# Build individual components
document_retriever = self._build_document_retriever()
product_retriever = self._build_product_retriever()
chat_summary_memory = self._build_chat_summary_memory()
chat_limited_memory = self._build_chat_limited_memory()

chat_history = self._build_chat_history()

# Create injector with all components
return self._config.injector(
product_retriever=product_retriever,
document_retriever=document_retriever,
repositories=self._repositories,
chat_summary_memory=chat_summary_memory,
chat_limited_memory=chat_limited_memory,
chat_history=chat_history,
)
```

Expand All @@ -206,12 +192,8 @@ class CustomInjector(BaseInjector):
return self._build_custom_product_retriever()

@property
def chat_summary_memory(self) -> BaseMemory:
return self._build_custom_summary_memory()

@property
def chat_limited_memory(self) -> BaseMemory:
return self._build_custom_limited_memory()
def chat_history(self) -> BaseChatMessageHistory:
return self._build_custom_chat_history()

@property
def custom_service(self) -> CustomService:
Expand Down
Loading
Loading