Add your own capability¶
A backend with no matching capability needs a contract of its own. Split the package in two, so a module can import the contract without the driver:
vector_index/contracts.py
"""What a module may import: the caller's Protocol, the reference and the spec."""
import abc
from typing import ClassVar, Protocol
from sandloom.driverkit import CapabilityRef, CapabilitySpec, InfraProvider
class VectorIndex(Protocol):
async def nearest(self, vector: list[float], *, limit: int) -> list[str]: ...
class VectorIndexProvider(InfraProvider, VectorIndex):
capability: ClassVar[str] = "vector_index"
@abc.abstractmethod
async def nearest(self, vector: list[float], *, limit: int) -> list[str]: ...
VECTOR_INDEX: CapabilityRef[VectorIndex] = CapabilityRef("vector_index.v1")
VECTOR_INDEX_SPEC = CapabilitySpec(
name="vector_index",
version="v1",
provider_contract=VectorIndexProvider,
features=frozenset({"exact"}),
stability="experimental",
)
vector_index/driver.py
"""The driver: a module may not import this."""
from vector_index.contracts import VectorIndexProvider
class MemoryVectorIndex(VectorIndexProvider):
contract_version = "v1"
supported_features = frozenset({"exact"})
async def nearest(self, vector: list[float], *, limit: int) -> list[str]:
# "exact": a linear scan of everything, never an approximation.
return ["a", "b"][:limit]
pyproject.toml
[project.entry-points."sandloom.capabilities"]
vector_index = "vector_index.contracts:VECTOR_INDEX_SPEC"
[project.entry-points."sandloom.drivers"]
"vector_index.memory" = "vector_index.driver:MemoryVectorIndex"
- Selecting it:
INFRA={"vector_index":{"default":{"driver":"memory"}}}. - Requiring it from a module:
CapabilityRequirement("vector_index", features=frozenset({"exact"}))indefine_module. Startup then fails, without I/O, if it is missing. -
Calling it from a module: the reference carries the type, as long as your package ships a
py.typedfile. Without one, type checkers seeAny.from sandloom.sdk.infra import capability # sandloom: advanced infra from vector_index.contracts import VECTOR_INDEX nearest = await capability(VECTOR_INDEX).nearest([1.0], limit=5) -
What a module may import:
vector_index.contracts. Importingvector_index.driveror its parentvector_index, which reaches the driver by attribute, fails SANDLOOM-C004, because an entry point names that module. - In production:
stability="experimental"requires the accepted riskexperimental_capability(SANDLOOM-B023). Use"stable"when you keep the contract stable yourself. - Reserved names: the kernel defines
search,document_store,graph_store,workflow,lockandsecrets, so a package cannot declare them.
See also Write a driver and the driver kit.