Skip to main content

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.