Skip to content

Bindings and composition

Capability bindings connect a neutral port to one configured implementation. Registration verifies conformance evidence. Resolution is deterministic and returns diagnostics instead of selecting the first candidate.

ts
import {
  capabilityIdForPort,
  createCapabilityCandidateCatalog,
  type CapabilityCandidateEvidenceVerifier,
} from "@geekist/llm-core/adapters/catalogue";
import {
  acquireCapabilityBindings,
  registerCapabilityAcquisitionFactory,
  type CapabilityAcquisitionFactoryVerifier,
} from "@geekist/llm-core/adapters/catalogue/runtime";
import type { CapabilityBinding } from "@geekist/llm-core/contracts";
import type { Retriever } from "@geekist/llm-core/retrieval";

declare const retriever: Retriever;
declare const descriptor: CapabilityBinding;
declare const verifyEvidence: CapabilityCandidateEvidenceVerifier;
declare const verifyAcquisitionFactory: CapabilityAcquisitionFactoryVerifier;

const catalog = createCapabilityCandidateCatalog({
  verifyEvidence,
  verifyAcquisitionFactory,
});

const candidate = catalog.register({
  kind: "retriever",
  descriptor,
});

const resolution = catalog.resolve({
  requirements: [
    {
      kind: "retriever",
      bindingId: descriptor.bindingId,
      capabilities: [
        {
          capabilityId: capabilityIdForPort("retriever"),
          versionRange: "1.0.0",
        },
      ],
    },
  ],
});

if (resolution.kind === "unresolved") {
  throw new Error(JSON.stringify(resolution.diagnostics));
}

const factory = registerCapabilityAcquisitionFactory(candidate, {
  kind: "retriever",
  bindingId: descriptor.bindingId,
  acquire: () => ({ port: retriever }),
});

const acquired = await acquireCapabilityBindings(resolution, [factory]);
const binding = acquired.bindings[0];
if (binding?.kind === "retriever") void binding.port.retrieve;

verifyEvidence is a trusted host-composition port, not a predicate over the claim's self-reported result. It resolves the claim's EvidenceRef through authorized storage, verifies the report's integrity and conformance-suite provenance, then checks that the report is bound to the supplied bindingId, port kind, and exact live implementationToken. It returns true only when all of those checks succeed.

descriptor.claims must contain evidence-backed claims; the declarations above assume composition loaded a validated descriptor and a host verifier. Conditional claims also require an explicit evaluateCondition dependency. Exact bindingId selection never falls through to a different implementation, and an unqualified ambiguous request fails.

Keep three things separate:

  • the descriptor and claims are portable configuration;
  • the port is a live implementation value;
  • invocation state records which registered binding was selected.

This is typed capability composition, not a string-keyed service locator.

Register invocation state

After a host accepts a plan, the catalogue runtime front connects a selected capability to execution state. registerCapabilityInvocation validates and freezes InvocationContext. It accepts one typed lifetime: observe a Snapshot, continue a LiveContinuation, resume a RegisteredResumableCheckpoint, continue a ProviderSessionRef, or signal a DurableExecutionHandle. These states are not interchangeable.

Qualify retries

ts
import {
  executeWithQualifiedRetry,
  registerCapabilityInvocation,
  type AnyRegisteredRuntimeCapabilityBinding,
} from "@geekist/llm-core/adapters/catalogue/runtime";
import type { InvocationContext } from "@geekist/llm-core/contracts";
import type { Snapshot } from "@geekist/llm-core/state";

declare const invocationContext: InvocationContext;
declare const snapshot: Snapshot;
declare const binding: AnyRegisteredRuntimeCapabilityBinding;

const invocation = registerCapabilityInvocation({
  invocationContext,
  state: { kind: "paused-snapshot", snapshot },
});

const result = await executeWithQualifiedRetry({
  binding,
  effect: "read-only",
  phase: "before-start",
  call: () => binding.port,
  policy: {
    maxAttempts: 3,
    delayMs: 0,
    retryOn: ["network"],
    guarantee: "read-only",
  },
  classifyFailure: () => "network",
});

console.log(invocation.state?.kind, result);

executeWithQualifiedRetry performs exactly one attempt when no policy is supplied. A multi-attempt policy is closed and bounded, needs a trusted failure classifier, and must cite verified conformance evidence for one guarantee:

GuaranteeRequired meaning
read-onlyThe exact operation is proven not to create a meaningful effect
idempotentRepeating the operation preserves its declared effect
reconciledThe implementation detects or reconciles duplicate effects

Meaningful effects cannot use the read-only guarantee. An operation not proven read-only needs idempotent or reconciled evidence, especially after start. Delayed retry also requires an explicit scheduler. Labels supplied by a caller do not create any of these guarantees.