Skip to content

Add dependency injection system #11

@DaviddeBest-TNO

Description

@DaviddeBest-TNO

Goal

Allow KI handler functions to declare dependencies (e.g. database connections, HTTP clients) that are automatically injected by the framework at call time — similar to FastAPI's dependency injection system.

Motivation

Currently handlers only receive (binding_set, info). Any external resource (DB connection, config, HTTP client) must be a global or closure. DI makes handlers testable and decoupled.

Design

Use a Depends() marker in Annotated type hints:

from typing import Annotated
from src import Depends

def get_db() -> MyDatabase:
    return MyDatabase(url="...")

@kb.answer_ki(name="...", graph_pattern="...")
def handler(
    binding_set: list[PersonBinding],
    info: KnowledgeInteractionInfo,
    db: Annotated[MyDatabase, Depends(get_db)],
) -> list[PersonBinding]:
    return db.query(binding_set)

Behaviour

  • The framework inspects handler signatures at registration time, identifies Depends()-annotated parameters, and resolves them at call time.
  • Dependency factories are sync-only for now (async support deferred to a later issue).
  • Dependency factories can themselves declare Depends() parameters — nested/transitive resolution is supported.
  • Caching is configurable via Depends(factory, cache=True/False):
    • cache=True (default): factory is called once per handling-loop call and the result is reused across nested dependencies in the same call.
    • cache=False: factory is called fresh every time it is needed.

Out of scope

  • Async dependency factories (document this as a known limitation, to be addressed in a follow-up issue).
  • Request-scoped caching beyond a single KI call.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions