entorin

M7 primitives — retrieval, skills

Two more protocol-first substrate primitives. Same backend-pluggable discipline as M6.

Two more protocol-first substrate primitives. Same backend-pluggable discipline as M6.

from entorin.retrieval import MCPRetrieval, RetrievalClient
from entorin.skills    import SkillManifest, SkillRuntime

Retrieval

Tenant-scoped, audited query interface returning ranked Chunk(text, score, metadata) records. RetrievalClient wraps any Retrieval backend (MCPRetrieval, your own pgvector / Qdrant / Pinecone) with capability check + audit events + span:

retrieval = RetrievalClient(
    "docs", backend=MCPRetrieval(my_mcp_session), bus=bus,
)
hits = await retrieval.query(ctx, "where are the deploy notes", k=5)
for chunk in hits:
    ...  # chunk.text, chunk.score, chunk.metadata

MCPRetrieval calls one of the MCP server’s tools (canonical query) with {"query", "k", "principal_id", "filter"}. The server scopes the corpus per principal_id. Capability: retrieval.<id>.query.

Pgvector / Qdrant / Pinecone? Implement the four-line Retrieval protocol against your infra; RetrievalClient wraps it the same way.

Skills

Lazy-loaded, manifest-described code units with two dispatch paths (explicit invoke or event-trigger):

manifest = SkillManifest(
    name="audit_run_end",
    version="1.0.0",
    triggers=("run.end", "run.error"),
    required_caps=("audit.write",),
    entry_point="my_pkg.skills:on_run_end",
)

runtime = SkillRuntime(
    bus=bus,
    context_provider=lambda ev: ctx,  # required when triggers are set
)
runtime.register(manifest)

# explicit invoke (no trigger needed):
result = await runtime.invoke("audit_run_end", ctx, payload={"why": "manual"})

Skill bodies are async functions taking (ctx, payload). Substrate emits skill.load once per skill, skill.invoke per call, skill.error on raise; opens an entorin.skill.invoke span carrying entorin.skill_name and entorin.skill_version. Capabilities: skill.<name>.invoke plus everything in manifest.required_caps.

The composed-loop integ test (tests/integ/test_m7_substrate.py) wires both primitives through the same RunContext / EventBus / Ledger.