How to Create Injectable Dependencies
In this guide, we will explore how to create injectable dependencies for your agents. Injectable dependencies allow you to modularize your agent's functionality and make your code more maintainable. This is done by creating a factory that extends AgentDependencyFactory
and registering it with the AgentDependencyRegistry
.
Prerequisites
Before you begin, make sure you have completed the Getting Started with the Agents SDK tutorial and you are familiar with How to Configure Agents.
Step 1: Add a dependency to the project
To scaffold a new dependency, you can run the following command in your project directory:
rag_agents new-dependency "my_dependency"
This will create a new file my_dependency.py
in the dependencies
directory of your project.
Step 2: Creating the Dependency Factory
Next, you need to create a factory that extends AgentDependencyFactory
and implements the create
method. The create
method takes a configuration object as input and returns an instance of the dependency class.
Open the my_dependency.py
file and paste the following code:
from pydantic import BaseModel
from zav.agents_sdk import AgentDependencyFactory, AgentDependencyRegistry
class MyDependencyConfig(BaseModel):
foo: int
bar: bool
class MyDependency:
def __init__(self, foo: int, bar: bool):
self.foo = foo
self.bar = bar
def do_something(self):
return f"Foo: {self.foo}, Bar: {self.bar}"
class MyDependencyFactory(AgentDependencyFactory):
@classmethod
def create(cls, my_dependency_config: MyDependencyConfig) -> MyDependency:
return MyDependency(foo=config.foo, bar=config.bar)
AgentDependencyRegistry.register(MyDependencyFactory)
In this example, MyDependencyFactory
extends AgentDependencyFactory
and implements the create
method. The create
method takes a MyDependencyConfig
object and returns an instance of MyDependency
.
Step 3: Using the Dependency in an Agent
Once the dependency factory is registered, you can use the dependency in your agent by declaring it as a parameter in the agent's __init__
method. The SDK will automatically inject the dependency when the agent is created.
Here is an example of an agent that uses the MyDependency
dependency:
from typing import List, Optional
from zav.agents_sdk import ChatAgent, ChatAgentFactory, ChatMessage
@ChatAgentFactory.register()
class MyAgent(ChatAgent):
agent_name = "my_agent"
def __init__(self, my_dependency: MyDependency):
self.my_dependency = my_dependency
async def execute(self, conversation: List[ChatMessage]) -> Optional[ChatMessage]:
result = self.my_dependency.do_something()
return ChatMessage(sender="bot", content=result)
In this example, the MyAgent
class declares a my_dependency
parameter in its __init__
method. The SDK will automatically inject an instance of MyDependency
when the agent is created.
Step 4: Configuring the Dependency
The initialization of the dependency happens when the create
method of the AgentDependencyFactory
is called. The parameters passed to the create
method are extracted from the AgentSetup
(e.g. from the agent_setups.json
when running locally) as well as the request parameters. The rules of how the parameters are extracted are the same as for the agent initialization. Refer to the How to Configure Agents guide for more information on how to configure agents.
Here is an example of an agent_setups.json
file with the configuration for the MyDependency
dependency:
{
"my_agent": {
"agent_identifier": "my_agent",
"agent_name": "my_agent",
"llm_client_configuration": {
"vendor": "openai",
"vendor_configuration": {},
"model_configuration": {
"name": "gpt-4",
"type": "chat",
"temperature": 0.0
}
},
"agent_configuration": {
"my_dependency_config": {
"foo": 42,
"bar": true
}
}
}
}
In this example, the agent_configuration
section contains the configuration for the MyDependency
dependency. The SDK will pass this configuration to the create
method of the MyDependencyFactory
. For this case, the response of calling the MyAgent
agent will be Foo: 42, Bar: True
.