# Depends

The `Depends` mechanism allows you to calculate and inject dependencies dynamically at execution time.

The key difference with [Dependency Injection](https://docs.ag2.ai/0.13.2/docs/beta/context/inject) is their execution model. `Inject` is used to retrieve static objects or configurations that have already been created (like an existing database connection or API key). `Depends`, on the other hand, executes a callable function _during_ the tool's invocation to resolve the dependency.

Under the hood, `Depends` uses the exact same mechanism and design philosophy as [FastAPI's dependency injection system](https://fastapi.tiangolo.com/tutorial/dependencies/).

## Side-execution

You can use `Depends` to execute side-effects before your tool runs—even if your tool doesn't actually need the return value of the dependency. This is extremely useful for things like authentication, logging, or permission verification.

To do this, simply declare the dependency in your tool's signature. The framework will execute it, and you can safely ignore the injected value.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>``` | ```<br>from typing import Annotated<br>from autogen.beta import Depends, tool<br>def verify_permissions(user_id: int) -> None:<br>    # Perform complex verification here<br>    # Raises an exception if permissions are invalid<br>    raise PermissionDenied(user_id)<br>@tool<br>def delete_user(<br>    user_id: int,<br>    # The dependency is executed, acting as a gatekeeper<br>    auth: Annotated[None, Depends(verify_permissions)]<br>) -> str:<br>    return f"User {user_id} deleted."<br>``` |

Sync/Async

`Depends` can be used with both synchronous and asynchronous functions.

## Depends with yield

Just like in [FastAPI](https://fastapi.tiangolo.com/), you can create dependencies that use `yield` instead of `return`. This allows you to execute "teardown" or "cleanup" code _after_ the tool has finished executing.

This is the recommended approach for managing resource lifecycles, such as opening and closing database sessions or file handlers.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>``` | ```<br>def get_db_session():<br>    print("Opening database session...")<br>    session = "db_session_object"<br>    # The tool execution happens here<br>    yield session<br>    # This runs after the tool finishes<br>    print("Closing database session...")<br>@tool<br>def fetch_records(<br>    db: Annotated[str, Depends(get_db_session)],<br>) -> str:<br>    return "Records fetched."<br>``` |

### Combining Depends and Inject

A powerful pattern is to combine `Depends` with `Inject`. You can use `Inject` to retrieve a static configuration or persistent resource (like a database connection pool), and then use `Depends` to manage a short-lived resource (like a database session) based on that configuration.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>``` | ```<br>from typing import Annotated<br>from autogen.beta import Depends, Inject, tool, Agent<br>def get_db_session(<br>    db_pool: Annotated[Pool, Inject("database_pool")],<br>) -> Session:<br>    session = db_pool.acquire()<br>    yield session<br>    session.release()<br>@tool<br>def fetch_records(<br>    db_session: Annotated[object, Depends(get_db_session)],<br>) -> str:<br>    return "Records fetched."<br>agent = Agent(<br>    "TestAgent",<br>    tools=[fetch_records],<br>    dependencies={"database_pool": Pool()},<br>)<br>``` |

## Dependencies caching

By default, if multiple parameters in your tool (or multiple sub-dependencies) depend on the exact same `Depends` function, the framework will only execute that function **once** per tool call. The result is cached and reused for any subsequent injections within that specific execution step.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>``` | ```<br>def get_expensive_config() -> dict:<br>    print("Calculating config...") # This will only print once!<br>    return {"timeout": 30}<br>def get_timeout(<br>    config: Annotated[dict, Depends(get_expensive_config)],<br>) -> int:<br>    return config["timeout"]<br>@tool<br>def process_data(<br>    timeout: Annotated[int, Depends(get_timeout)],<br>    # cached dependency<br>    config: Annotated[dict, Depends(get_expensive_config)],<br>) -> str:<br>    return "Done"<br>``` |

If you explicitly want the dependency to be re-calculated every single time it is injected, you can disable the cache by passing `use_cache=False`:

|     |     |
| --- | --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>``` | ```<br>@tool<br>def random_tool(<br>    val1: Annotated[int, Depends(get_random_number, use_cache=False)],<br>    val2: Annotated[int, Depends(get_random_number, use_cache=False)]<br>) -> str:<br>    # val1 and val2 will be different numbers<br>    pass<br>``` |

## Dependencies Overrides

During testing, you often need to mock or override complex dependencies (like replacing a production database with a mock test database).

You can easily override any `Depends` function at the agent level using the `dependency_provider`. When the agent executes, it will automatically route all requests for the original dependency to your override function.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>``` | ```<br>from autogen.beta import Agent, tool<br>def get_production_db():<br>    raise Exception("Do not call this in tests!")<br>@tool<br>def read_data(db: Annotated[object, Depends(get_production_db)]) -> str:<br>    return "Data"<br>agent = Agent("TestAgent", tools=[read_data])<br># Create a mock function<br>def get_test_db():<br>    return "mock_database"<br># Override the production dependency with the test dependency<br>agent.dependency_provider.override(get_production_db, get_test_db)<br># When the tool is called, it will use `get_test_db` instead<br>await agent.ask("Read some data")<br>``` |

To override `Inject` dependencies, you can just set `dependencies={...}` in the `ask` call.

|     |     |
| --- | --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>``` | ```<br>agent = Agent("TestAgent", tools=[read_data])<br># Override the production `Inject` dependency with the test dependency<br>await agent.ask(<br>    "Read some data",<br>    dependencies={"database_pool": Pool()},<br>)<br>``` |
