import { snippets } from "@/lib/generated/snippets";
import { Snippet } from "@/components/code";
import { Callout, Card, Cards, Steps, Tabs } from "nextra/components";
import UniversalTabs from "@/components/UniversalTabs";

# Dependency Injection

<Callout type="error" emoji="🚨">
  Dependency injection is an **experimental feature** in Hatchet, and is subject
  to change.
</Callout>

Hatchet's Python SDK allows you to inject **_dependencies_** into your tasks, FastAPI style. These dependencies can be either synchronous or asynchronous functions. They are executed before the task is triggered, and their results are injected into the task as parameters.

This behaves almost identically to [FastAPI's dependency injection](https://fastapi.tiangolo.com/tutorial/dependencies/), and is intended to be used in the same way. Dependencies are useful for sharing logic between tasks that you'd like to avoid repeating, or would like to factor out of the task logic itself (e.g. to make testing easier).

<Callout type="warning" emoji="⚠️">
Since dependencies are run before tasks are executed, having many dependencies (or any that take a long time to evaluate) can cause tasks to experience significantly delayed start times, as they must wait for all dependencies to finish evaluating.

</Callout>

## Usage

To add dependencies to your tasks, import `Depends` from the `hatchet_sdk`. Then:

<Snippet
  src={snippets.python.dependency_injection.worker.declare_dependencies}
/>

In this example, we've declared two dependencies: one synchronous and one asynchronous. You can do anything you like in your dependencies, such as creating database sessions, managing configuration, sharing instances of service-layer logic, and more.

Once you've defined your dependency functions, inject them into your tasks as follows:

<Snippet
  src={snippets.python.dependency_injection.worker.inject_dependencies}
/>

<Callout type="warning" emoji="⚠️">
  Important note: Your dependency functions must take two positional arguments:
  the workflow input and the `Context` (the same as any other task).
</Callout>

That's it! Now, whenever your task is triggered, its dependencies will be evaluated, and the results will be injected into the task at runtime for you to use as needed.
