Dependency Injection#
What is Dependency Injection?#
Dependency Injection (DI) is a design pattern used to pass complex objects or services into your tools at runtime, rather than hardcoding them or re-instantiating them repeatedly. This keeps your tools pure, testable, and completely decoupled from external resource management.
Dependencies#
The key difference between Variables and Dependencies is their intended use case. Variables are designed to pass lightweight, serializable state (like strings, flags, or configuration IDs) between the LLM, tools, and agents. Dependencies, on the other hand, are meant for complex objects that have specific behaviors and lifecycle management, such as database connections, HTTP sessions, or clients for external APIs.
Agent Dependencies#
If a dependency is required across all conversations for a specific agent, you can provide it directly when initializing the agent.
Conversation Dependencies#
If a dependency is only relevant for a single conversation, you can inject it dynamically when calling the ask method.
Mixed Dependencies#
When you provide both agent-level and conversation-level dependencies, the framework automatically merges them. If there is a key collision, the dependencies provided during the ask call take precedence and override the agent's default dependencies.
Context Dependency Access#
The simplest way to access your dependencies inside a tool is through the Context object. By adding an argument annotated with Context, the framework injects the current execution context, which includes the .dependencies dictionary.
Accessing Dependencies with Inject#
Instead of passing the entire context object, you can explicitly request specific dependencies directly in your tool's function signature. This approach clarifies your tool's requirements and automatically handles validation.
Use the Inject annotation to pull a dependency from the context dictionary by its key. By default, Inject looks for a key that matches the argument's name.
If your argument name differs from the dependency key, you can provide the exact key explicitly:
LLM Tool Schema
Dependency injection annotations (like Inject and Depends) do not affect the tool schema provided to the LLM. They are purely an internal framework mechanism for injecting dependencies into your functions.
Dependencies with Default Values#
Sometimes a dependency might not be provided by the user. You can define fallback behaviors directly within the Inject annotation using either default or default_factory. Without a default, a missing dependency will raise a ValidationError.
Static Defaults#
Use default for simple, immutable fallback values.
Dynamic Defaults#
For mutable objects or dependencies that need to be instantiated at runtime, use default_factory. The framework ensures that the factory function is called when the dependency is missing.