Home / Projects / Orchestrata Ultimate / Decisions / ADR index / ADR-0112
ADR-0112: Tools reaches Redis and embeddings through contracts protocols, not kernel imports
| field | value |
|---|---|
| Status | Accepted — Accepted (ruling, Mohamed, 2026-10-19, verbatim: "all" — ratifying recommendation R2 option B of reports/project-analysis-2026-10-19.md) |
| Date | 2026-10-19 |
| Register | factory (docs/adr, 4-digit ids) |
| Source | docs/adr/0112-tools-reaches-redis-and-embeddings-through-contracts-protocols-not-kernel-imports.md — permalink at 80c7135f0 (unchanged on master since that commit) |
| Wiki register entry | ADR-0112 (wiki status: Accepted) |
The record
Status: Accepted (ruling, Mohamed, 2026-10-19, verbatim: "all" — ratifying recommendation R2 option B of reports/project-analysis-2026-10-19.md) · Date: 2026-10-19
Context
The component DAG (packages/tools/design/boundaries.json) draws tools depending on
contracts, knowledge_graph, governance — that row describes the codetools release
(package: codetools). The landed packages/tools/pyproject.toml also declares
orchestrata-kernel, and two modules import kernel at module level (MEASURED):
packages/tools/src/orchestrata_tools/schedule_cron_tool.py:76—from orchestrata_kernel.core.redis_factory import create_async_redis; the only use is the default client construction in the factory at lines 1423–1425 (redis_client if redis_client is not None else create_async_redis(host=host, port=port, db=db)), so the caller-side injection seam already exists.packages/tools/src/orchestrata_tools/search.py:52—from orchestrata_kernel.memory.embedding_service import EmbeddingService; constructed bare at line 1573 (embeddings = EmbeddingService()).
Both are retarget artifacts, not design: D-T2's map rewrote the frozen
core.redis_factory → orchestrata_kernel.core.redis_factory and memory.embedding →
orchestrata_kernel.memory.embedding_service; D-T3 flagged the edge as exceeding the
drawn DAG and parked it "as a boundaries.json data follow-up, not silently absorbed".
This ADR is that follow-up (report finding F4, recommendation R2 option B).
Decision (Mohamed, verbatim: "all" — R2 option B)
The two call sites stop importing kernel and go through contracts protocols:
orchestrata_contracts.protocols.redis_factory.RedisFactory— a structuralProtocolwhose call returnsredis.asyncio.Redisfor an explicit(host, port, db)triple. Redis types areTYPE_CHECKING-only imports (from __future__ import annotations), so contracts gains no runtime third-party dependency andboundaries.jsonneeds no edit.orchestrata_contracts.protocols.embedding_port.EmbeddingPort— thecompute_embedding(text) -> list[float]/cosine_similarity(a, b) -> float/search(query, candidates, limit, min_similarity) -> list[tuple[str, float]]surface, pure-Python types, no dependencies.
Tools keeps the drawn DAG and stays bootable standalone:
schedule_cron_tool.py's factory gains aredis_factory: RedisFactory | Noneseam; the default buildsredis.asyncio.Redis(host=..., port=..., db=...)directly from the explicit parameters the tool already carries (redis is a declared tools dependency; the RUL-003 raise-when-missing behaviour is preserved by the caller's existing parameter checks, verified in the brief's done-check).search.py's engine gains anembedding: EmbeddingPort | Noneseam; the default is a real, deterministic hash-projection implementation local to tools (the kernelEmbeddingServicesurface, minimal — not a fake: RUL-002 bans fakes, not real code), documented as the tools-local default.- Kernel — or integration at boot — supplies the canonical implementations
(
EmbeddingService, the pooled redis factory) through the seams. packages/tools/pyproject.tomldropsorchestrata-kernel. The parity tests'_ALLOWED_ROOTSlists (test_frozen_parity_t01/t02) droporchestrata_kernel, so a reintroduced kernel import fails the parity gate — the deterministic negative check.
Alternatives rejected
- Amend the boundary file to draw tools → kernel (option A) — teaches every later lift that a retarget may invent an edge; the split exists so Redis and embeddings are reached through a contract, which is what session's design already claims for itself.
- Lazy import or shim around the kernel call — invented code that hides the edge instead of removing it (D-T3's own reasoning).
Consequences
boundaries.json's drawn DAG and the landed package agree again: tools imports only
contracts, knowledge_graph, governance. The boundary checker passes with no
tools → kernel edge; the tools parity suite passes with kernel removed from
_ALLOWED_ROOTS. Kernel's implementation is injected at boot by integration
(ADR-0113's composition root), never imported by tools.
Provenance
Mohamed's in-session ruling 2026-10-19 ("all") on recommendation R2 of
reports/project-analysis-2026-10-19.md (finding F4). Retarget history: D-T2/D-T3,
packages/tools/design/decisions.md. Implementation: a sonnet dispatch brief under the
RUL-037 M3 routing, fence packages/tools/** + packages/contracts/protocols/*.
Related ADRs
- Also mentioned: ADR-0113
Rulings cited
- RUL-003: RUL-003 — Env config from the active env profile, read at call time — no hardcoding, no literal infra defaults
- RUL-002: RUL-002 — No mocking — real infra, real implementations only
- RUL-037: RUL-037 — Every agent writes Python only as files through the guarded tools; enforced on every channel, never promised
Specs cited
None (or no spec page exists for the ones named).