loom.ai.inference

Model binding value type shared by the compiler and the engine.

InferenceTarget lives in its own module rather than in loom.ai.config because it is a value type of the pillar: the compiler embeds it in the plan and the engine consumes it, so it is not a config-parsing detail.

Secret containment (data-model invariant 4, FR-018): credentials_ref and options never leave the process in clear text. The mechanism is fail-closed — on construction both values are rewrapped into types msgspec refuses to encode, so msgspec.json.encode (and msgspec.to_builtins, msgspec.msgpack.encode) raise TypeError instead of leaking them, and repr/str redact them. Rejecting the encode was chosen over silent redaction because a plan that reaches a wire encoder with a secret reference aboard is a bug worth surfacing, not smoothing over. Decoding through the config loader is unaffected: msgspec.convert builds the struct from plain values and __post_init__ wraps them afterwards.

Module Attributes

OutputMode

How the engine asks the model for the structured answer.

OUTPUT_MODES

Values InferenceTarget.output_mode accepts, derived from OutputMode.

Classes

InferenceTarget(*, provider, model[, ...])

One resolved model binding for a model role (ai.models.<role>).

_RedactedOptions(raw)

Options mapping that redacts itself and refuses msgspec encoding.

_RedactedRef

Secret reference that redacts itself and refuses msgspec encoding.

loom.ai.inference.OutputMode

How the engine asks the model for the structured answer.

prompted is deliberately absent: the engine strips markdown fences before validating a prompted answer while loom decodes the raw text part, so a fenced answer would pass the engine and fail loom.

This is the single source of truth for the set: adding a member here makes every exhaustive dispatch over it (_spec.build_output_type) fail type checking until it handles the new mode, instead of degrading to a default at run time.

alias of Literal[‘tool’, ‘native’]

loom.ai.inference.OUTPUT_MODES: Final[tuple[OutputMode, ...]] = ('tool', 'native')

Values InferenceTarget.output_mode accepts, derived from OutputMode.

class loom.ai.inference.InferenceTarget(*, provider, model, region=None, endpoint=None, output_mode=None, credentials_ref=None, options=<factory>)[source]

Bases: LoomFrozenStruct

One resolved model binding for a model role (ai.models.<role>).

repr/str show provider, model, region, endpoint and output_mode but never the values of credentials_ref or options — the plan carries this struct, so an unredacted repr in a start-up traceback is the concrete leak path. Encoding the struct with msgspec raises when either secret-bearing field is set (see the module docstring for the rationale).

Parameters:
provider

Provider identifier (bedrock, openai, …).

Type:

str

model

Vendor model id.

Type:

str

region

Region for regional providers such as Bedrock.

Type:

str | None

endpoint

Gateway or compatible endpoint URL.

Type:

str | None

output_mode

How the engine asks the model for the structured answer (tool or native, see OutputMode). None leaves the choice to the engine. Typed str rather than OutputMode because msgspec validates a Literal during the decode, before __post_init__: an unknown value would surface as a raw ValidationError instead of the OUTPUT_MODE_UNKNOWN issue naming the role. The set is enforced by loom.ai.config._validate_model_binding.

Type:

str | None

credentials_ref

Reference resolved by the existing secrets resolver. Never a literal secret (FR-018).

Type:

str | None

options

Vendor-specific settings. Confined here; never reaches the artifact.

Type:

collections.abc.Mapping[str, Any]