Files
cleveragents-core/docs/reference/acms_backends.md
T
freemo 025d379946
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / quality (pull_request) Successful in 17s
CI / build (pull_request) Successful in 15s
CI / typecheck (pull_request) Successful in 33s
CI / security (pull_request) Successful in 42s
CI / unit_tests (pull_request) Successful in 2m36s
CI / docker (pull_request) Successful in 40s
CI / integration_tests (pull_request) Successful in 3m17s
CI / coverage (pull_request) Successful in 4m21s
CI / lint (push) Successful in 12s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 16s
CI / security (push) Successful in 30s
CI / typecheck (push) Successful in 33s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m36s
CI / docker (push) Successful in 40s
CI / integration_tests (push) Successful in 3m57s
CI / coverage (push) Successful in 5m22s
CI / benchmark-publish (push) Has been cancelled
CI / benchmark-regression (pull_request) Successful in 25m12s
feat(acms): add text, vector, and graph backend protocol implementations
Implemented the Backend Abstraction Layer (BAL) for the Advanced Context
Management System, following the specification in docs/specification.md
Section ACMS > Backend Abstraction Layer and ADR-014.

Key additions:

- TextBackend protocol with search(query, scope, max_results) returning
  list[TextResult], and TextResult frozen dataclass (uko_uri, content,
  score, metadata fields)
- VectorBackend protocol with similarity_search(embedding, scope, top_k)
  returning list[VectorResult], and VectorResult frozen dataclass
- GraphBackend protocol with sparql_query(query, scope),
  get_triples(subject), and traverse(start, depth) methods returning
  GraphResult frozen dataclass (triples, metadata fields)
- In-memory stub backends (InMemoryTextBackend, InMemoryVectorBackend,
  InMemoryGraphBackend) that validate arguments and return empty results,
  serving as development placeholders and test doubles
- DI container registration as configurable Singletons with provider
  selection via override_providers()
- Behave BDD feature (35 scenarios / 83 steps) covering protocol
  compliance, argument validation, result immutability, and DI resolution
- Robot Framework smoke tests (6 tests) for integration verification
- ASV benchmarks for stub query overhead and instantiation time
- Reference documentation at docs/reference/acms_backends.md

Design decisions:
- Used @runtime_checkable Protocol for structural subtyping, consistent
  with existing ResourceHandler pattern
- Used frozen dataclasses (not Pydantic) for result types to minimize
  overhead in the hot path of context assembly
- scope parameter typed as frozenset[str] for immutability and hashability
- Stubs registered as default Singletons; production backends swap via DI

ISSUES CLOSED: #498
2026-03-03 03:29:31 +00:00

5.4 KiB

ACMS Backend Abstraction Layer

The Backend Abstraction Layer (BAL) provides a uniform interface to heterogeneous data stores used by the Advanced Context Management System. Context strategies query text, vector, and graph backends through protocol-defined APIs, enabling backend implementations to be swapped without changing strategy code.

Architecture

Strategy ──► ScopedView ──► Backend Protocol ──► Physical Store
                │
                └── resource_filter (scope)

Each backend type has a Protocol (structural subtyping) and a corresponding frozen result dataclass. Strategies never instantiate backends directly — they receive scoped views from the Context Assembly Pipeline via dependency injection.

Protocol Contracts

TextBackend

Full-text search over indexed resource content.

Method Signature Returns
search (query: str, *, scope: frozenset[str], max_results: int = 20) list[TextResult]

Preconditions:

  • query must be a non-empty string.
  • max_results must be a positive integer.

Postconditions:

  • Returns results ordered by descending score.
  • Results are restricted to resources whose ULIDs appear in scope.

VectorBackend

Embedding similarity search over chunked resource content.

Method Signature Returns
similarity_search (embedding: list[float], *, scope: frozenset[str], top_k: int = 20) list[VectorResult]

Preconditions:

  • embedding must be a non-empty list of floats.
  • top_k must be a positive integer.

Postconditions:

  • Returns results ordered by descending score (cosine similarity).
  • Results are restricted to resources whose ULIDs appear in scope.

GraphBackend

Knowledge-graph queries and traversals over UKO triples.

Method Signature Returns
sparql_query (query: str, *, scope: frozenset[str]) GraphResult
get_triples (subject: str) GraphResult
traverse (start: str, *, depth: int = 2) GraphResult

Preconditions:

  • query and subject and start must be non-empty strings.
  • depth must be a non-negative integer.

Postconditions:

  • sparql_query restricts results to resources in scope.
  • traverse returns triples discovered within depth hops of start.

Result Types

All result types are frozen (immutable) dataclasses.

TextResult

Field Type Description
uko_uri str UKO URI of the matching information unit (non-empty)
content str Matched text content
score float Relevance score, 0.0 -- 1.0
metadata dict[str, str] Backend-specific metadata (default: empty)

VectorResult

Field Type Description
uko_uri str UKO URI of the matching information unit (non-empty)
content str Text content of matched chunk
score float Cosine similarity, 0.0 -- 1.0
metadata dict[str, str] Backend-specific metadata (default: empty)

GraphResult

Field Type Description
triples list[tuple[str, str, str]] (subject, predicate, object) triples
metadata dict[str, str] Backend-specific metadata (default: empty)

Extension Points

Implementing a Custom Backend

To add a new backend (e.g., Tantivy for text search):

  1. Create a class that satisfies the corresponding Protocol (e.g., TextBackend).
  2. Implement all protocol methods with proper argument validation.
  3. Register the backend in the DI container by overriding the provider:
from cleveragents.application.container import override_providers

override_providers(text_backend=TantivyTextBackend(index_path="/data/tantivy"))

In-Memory Stubs

The following stubs are provided for development and testing:

Stub Protocol Behaviour
InMemoryTextBackend TextBackend Returns empty list; validates args
InMemoryVectorBackend VectorBackend Returns empty list; validates args
InMemoryGraphBackend GraphBackend Returns empty GraphResult; validates args

Stubs are registered as the default providers in the DI container. They can be overridden at runtime for production or per-test via override_providers().

DI Container Registration

Backends are registered as singletons in the DI container (cleveragents.application.container.Container):

text_backend = providers.Singleton(InMemoryTextBackend)
vector_backend = providers.Singleton(InMemoryVectorBackend)
graph_backend = providers.Singleton(InMemoryGraphBackend)

To swap to a production backend, override the provider before first use:

container = get_container()
container.text_backend.override(providers.Singleton(TantivyTextBackend))

Module Locations

Module Purpose
cleveragents.domain.models.acms.backends Protocol definitions and result dataclasses
cleveragents.domain.models.acms.stubs In-memory stub implementations
cleveragents.application.container DI container backend registration