Skip to main content

Integration package for Dishka DI and AG2 Framework

Project description

AG2 integration for Dishka

Downloads Package version Supported Python versions

Though it is not required, you can use dishka-ag2 integration. It features:

  • APP, SESSION and REQUEST scope management using AG2 beta middleware and @inject
  • AG2Provider for working with BaseEvent, Context, ToolCallEvent and HumanInputRequest in container
  • Automatic injection of dependencies via @inject in supported AG2 hooks

Scope mapping

Dishka scope AG2 lifecycle Description
Scope.APP Root container Lives for the application/container lifetime.
Scope.SESSION on_turn Created once per agent.ask() turn and shared by all nested tool/LLM/HITL calls in that turn.
Scope.REQUEST on_tool_execution, on_llm_call, on_human_input, injected prompt/schema validators Created for each tool execution, LLM call, HITL request, injected dynamic prompt, or injected response validator.

Supported AG2 Features

AG2 feature Scope.APP Scope.SESSION Scope.REQUEST Notes
@agent.tool yes yes yes Main supported path for injected tools.
standalone @tool in Agent(..., tools=[...]) yes yes yes Same lifecycle as @agent.tool.
Toolkit / custom Tool execution yes yes yes Works for actual tool functions if the custom tool forwards middleware in register().
on_llm_call middleware path yes yes yes REQUEST is opened for every model call.
HITL hooks (hitl_hook= / @agent.hitl_hook) yes yes yes HumanInputRequest is available in REQUEST scope.
@agent.prompt yes no yes Dynamic prompts run before middleware is constructed. Use dependencies={CONTAINER_NAME: container} so @inject can open REQUEST from the container.
response_schema validators yes no yes Injected validators can use REQUEST dependencies during reply.content() validation.

See the examples directory for runnable examples:

  • examples/ag2_agent_tool.py - @agent.tool with APP, SESSION and REQUEST.
  • examples/ag2_standalone_tool.py - standalone @tool with tools=[...].
  • examples/ag2_standalone_tool_hitl.py and examples/ag2_standalone_tool_hitl_arg.py - HITL hook injection.
  • examples/ag2_dynamic_prompt.py - @agent.prompt with injected APP/REQUEST dependencies.
  • examples/ag2_response_schema.py - response_schema validators with injected APP/REQUEST dependencies.
  • examples/ag2_toolkit.py - AG2 Toolkit with injected tool functions.
  • examples/ag2_custom_toolset.py - custom AG2 Tool/toolset with injected schemas() and injected tool functions.

Installation

Install using pip

pip install dishka-ag2

Or with uv

uv add dishka-ag2

How to use

  1. Import
from dishka_ag2 import (
    AG2Provider,
    CONTAINER_NAME,
    DishkaAsyncMiddleware,
    DishkaSyncMiddleware,
    FromDishka,
    inject,
)
from dishka import make_async_container, Provider, Scope, provide
  1. Create provider. You can use ToolCallEvent or HumanInputRequest as factory parameters on REQUEST scope for tool/HITL requests, and BaseEvent / Context on SESSION scope.

For @agent.prompt and response_schema validators, REQUEST scope is also supported, but it is opened outside a tool/HITL event. Use request factories that do not require ToolCallEvent or HumanInputRequest in those paths.

from autogen.beta.events import HumanInputRequest, ToolCallEvent

class MyProvider(Provider):
    @provide(scope=Scope.APP)
    def app_counter(self) -> AppCounter:
        return AppCounter()

    @provide(scope=Scope.SESSION)
    def conversation_state(self) -> ConversationState:
        return ConversationState()

    @provide(scope=Scope.REQUEST)
    def tool_request_state(self, event: ToolCallEvent) -> ToolRequestState:
        return ToolRequestState(tool_name=event.name)

    @provide(scope=Scope.REQUEST)
    def audit_log(self, event: HumanInputRequest) -> AuditLog:
        return AuditLog(f"Human was asked: {event.content}")

    @provide(scope=Scope.REQUEST)
    def greeting_service(
        self,
        conversation: ConversationState,
        request: ToolRequestState,
    ) -> GreetingService:
        return GreetingService(conversation=conversation, request=request)
  1. Mark those of your tool parameters which are to be injected with FromDishka[]
@agent.tool
@inject
async def greet_user(
    name: str,
    greeting: FromDishka[GreetingService],
    counter: FromDishka[AppCounter],
) -> str:
    count = counter.increment()
    result = await greeting.greet(name)
    return result
  1. Setup dishka integration: create container with AG2Provider() and pass it to DishkaAsyncMiddleware or DishkaSyncMiddleware via Middleware
from autogen.beta import Agent
from autogen.beta.middleware import Middleware

container = make_async_container(MyProvider(), AG2Provider())

agent = Agent(
    "assistant",
    prompt="Use tools to greet users.",
    middleware=[
        Middleware(DishkaAsyncMiddleware, container=container),
    ],
)
  1. Run the agent and close the container when done
async def main() -> None:
    try:
        reply = await agent.ask("Greet Connor and Sara.")
        print(reply.body)
    finally:
        await container.close()

AG2Provider context types

AG2Provider registers the following AG2 types as context dependencies, so you can use them as factory parameters:

Type Scope Description
BaseEvent SESSION Initial event that started the turn
Context SESSION AG2 context for the current turn
ToolCallEvent REQUEST Event for the current tool invocation
HumanInputRequest REQUEST Event for the current HITL request

Full example

import asyncio

from autogen.beta import Agent
from autogen.beta.events import ToolCallEvent
from autogen.beta.middleware import Middleware
from autogen.beta.testing import TestConfig
from dishka import Provider, Scope, make_async_container, provide

from dishka_ag2 import AG2Provider, DishkaAsyncMiddleware, FromDishka, inject


class AppCounter:
    def __init__(self) -> None:
        self._value = 0

    def increment(self) -> int:
        self._value += 1
        return self._value


class MyProvider(Provider):
    @provide(scope=Scope.APP)
    def app_counter(self) -> AppCounter:
        return AppCounter()


provider = MyProvider()
container = make_async_container(provider, AG2Provider())

agent = Agent(
    "assistant",
    prompt="Use tools to count.",
    config=TestConfig(
        ToolCallEvent(name="count", arguments="{}"),
        ToolCallEvent(name="count", arguments="{}"),
        "Done.",
    ),
    middleware=[
        Middleware(DishkaAsyncMiddleware, container=container),
    ],
)


@agent.tool
@inject
async def count(
    counter: FromDishka[AppCounter],
) -> str:
    value = counter.increment()
    return f"count={value}"


async def main() -> None:
    try:
        reply = await agent.ask("Count twice.")
        print(reply.body)
    finally:
        await container.close()


if __name__ == "__main__":
    asyncio.run(main())

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dishka_ag2-0.1.tar.gz (131.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dishka_ag2-0.1-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file dishka_ag2-0.1.tar.gz.

File metadata

  • Download URL: dishka_ag2-0.1.tar.gz
  • Upload date:
  • Size: 131.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dishka_ag2-0.1.tar.gz
Algorithm Hash digest
SHA256 90de3f5938c45512828ce41d7bd6ad6c7987f934dc084b83914dc95a7db2a5a6
MD5 27bd05ed486d54096970beba72cfe557
BLAKE2b-256 3e0efe1af6ebd536fb6347eb05b4caf5f03f983b3324ee9c1719e4493bd49bec

See more details on using hashes here.

File details

Details for the file dishka_ag2-0.1-py3-none-any.whl.

File metadata

  • Download URL: dishka_ag2-0.1-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dishka_ag2-0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 252d2c7d59ee90dd25bb8af29d88daeb6309e871abc4a19c74808eb343aadd0d
MD5 3c6a6e739f009b8668690ca52b7c4232
BLAKE2b-256 649149b950b59ed3d8f5cd10ff1fd7d89d067e6fda1638aed1fc9a5fc9b70b7d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page