loom.ai.compiler¶
Agent compiler: offline, multi-error compilation of authored artifacts.
Turns a decoded AgentSpecV1 into an immutable
AgentPlan — the only artifact-derived input every downstream stage
reads (FR-014). Compilation is fully offline: no network, no credentials, no
entry-point loading, and every problem found across every phase (and every
spec, in AgentCompiler.compile_all()) is reported at once through a
single AgentCompilationError with stable
AgentErrorCode values.
Example
>>> compiler = AgentCompiler(
... config=ai_config, registry=registry, supported_kinds=kinds
... )
>>> plan = compiler.compile(spec, source_path="agents/triage.agent.yaml")
- class loom.ai.compiler.AgentCompiler(*, config, registry, supported_kinds, sql=None, native_tools=None)[source]¶
Bases:
objectCompiles authored agent artifacts into immutable plans.
Runs every validation phase over every spec, accumulates all the issues found and raises a single
AgentCompilationError, so a generator sees the whole picture at once (FR-011, SC-003).- Parameters:
config (AiConfig) – Deployment configuration of the AI pillar.
registry (UseCaseRegistry) – Use-case registry the
usecasegrants resolve against.supported_kinds (frozenset[str]) – Capability kinds the configured engine serves, resolved by the bootstrap and passed as a plain value — the compiler never imports an engine.
sql (SqlConfig | None) – Data-layer configuration;
Nonefails everysqlgrant withSQL_CONFIG_MISSINGinstead of skipping silently.native_tools (NativeToolSupport | None) – Oracle answering which provider tools a model binding admits; resolved from the engine by the bootstrap, never imported here.
- compile(spec, *, source_path=None)[source]¶
Validate one spec statically and return its immutable plan.
Performs no network access, requires no model credentials and spends no tokens.
- Parameters:
spec (AgentSpecV1) – Decoded artifact to compile.
source_path (str | None) – Artifact provenance; when given, every issue points at it as its
component.
- Returns:
The compiled plan.
- Raises:
AgentCompilationError – Aggregating one issue per problem found.
- Return type:
- compile_all(specs)[source]¶
Compile a whole application, accumulating issues across specs.
Duplicate agent names are an application-level fault: a single spec is always unique by itself, so
AGENT_NAME_DUPLICATEcan only be detected — and is only reported — here.- Parameters:
specs (Sequence[AgentSpecV1 | DecodedSpec]) – Decoded artifacts of the application. Passing the
DecodedSpecvalues as returned byload_specskeeps each artifact’s path, which a./skill library resolves against; a bareAgentSpecV1has no path.- Returns:
One plan per spec, in input order.
- Raises:
AgentCompilationError – Aggregating every issue of every spec.
- Return type:
- class loom.ai.compiler.AgentPlan(*, name, description, instructions, state=None, spec_version, inference, output, output_check=None, capabilities=(), policies, on_output=None, conversation=None, metadata, source_path=None)[source]¶
Bases:
LoomFrozenStructImmutable compiled agent, the only input to every downstream stage.
- Parameters:
name (str)
description (str)
instructions (tuple[CompiledInstruction, ...])
state (StateShape | None)
spec_version (int)
inference (InferenceTarget)
output (CompiledOutput)
output_check (Callable[[Mapping[str, Any]], str | None] | None)
capabilities (tuple[CompiledUsecaseCapability | CompiledSqlCapability | CompiledMcpCapability | CompiledSkillsCapability | CompiledPythonCapability | CompiledA2ACapability | CompiledNativeCapability, ...])
policies (PolicySpec)
on_output (CompiledOutputHook | None)
conversation (CompiledConversation | None)
source_path (str | None)
- instructions¶
Instruction blocks the agent follows, in authored order; never published.
- state¶
Shape of the artifact’s declared state, or
Nonewhen the artifact declares neitherdeps_typenordeps_schema.- Type:
loom.ai.abc.StateShape | None
- inference¶
Resolved model binding; one binding, no fallback (FR-019a).
- output¶
Structured-output contract with its built decoder.
- output_check¶
Resolved predicate over the answer the engine parsed, when the artifact declares
output_check;Noneotherwise.- Type:
collections.abc.Callable[[collections.abc.Mapping[str, Any]], str | None] | None
- capabilities¶
Compiled capabilities with resolved handles.
- Type:
tuple[loom.ai.compiler._plan.CompiledUsecaseCapability | loom.ai.compiler._plan.CompiledSqlCapability | loom.ai.compiler._plan.CompiledMcpCapability | loom.ai.compiler._plan.CompiledSkillsCapability | loom.ai.compiler._plan.CompiledPythonCapability | loom.ai.compiler._plan.CompiledA2ACapability | loom.ai.compiler._plan.CompiledNativeCapability, …]
- policies¶
Validated execution limits.
- on_output¶
Output hook, when the artifact declares one.
- Type:
- conversation¶
Conversation loader, when the artifact declares one.
- Type:
- metadata¶
Free-form string labels carried alongside the agent.
- Type:
- class loom.ai.compiler.CompiledA2ACapability(*, agent, url, headers_ref=None, auth=None, include=(), exclude=())[source]¶
Bases:
LoomFrozenStructRemote-agent grant, resolved against
ai.a2a_agents.The card is fetched in
__aenter__and the filter applied against the skills it really advertises — one of the declared exceptions to “strings die at compile” (invariant 3).- Parameters:
- headers_ref¶
Reference to deployment-resolved headers; never a secret. Applied to every request the client makes, the card fetch included.
- Type:
str | None
- auth¶
Named authentication strategy, mutually exclusive with
headers_ref;Nonewhen the agent needs no credential.- Type:
- class loom.ai.compiler.CompiledNativeCapability(*, tool)[source]¶
Bases:
LoomFrozenStructProvider tool granted to an agent, already checked against its model.
The plan carries the stable loom name and not the engine’s class: the compiler never imports an engine, and the name was validated against the binding before reaching here.
- Parameters:
tool (str)
- class loom.ai.compiler.CompiledConversation(*, usecase, use_case, accepted)[source]¶
Bases:
LoomFrozenStructUse case executed before a run that carries a
conversation_id.The compiler proves that every required, user-supplied name of the use case’s Input is one of
CONVERSATION_CONTEXT_FIELDSand that the Input declaresconversation_id, so the loader always knows which conversation to load.acceptedis the run-time filter, computed once asCompiledOutputHook.acceptedis.
- class loom.ai.compiler.CompiledInstruction(*, text, name=None, template=None)[source]¶
Bases:
LoomFrozenStructOne instruction block in authored order, projected onto the plan.
A bare-string artifact and a one-block artifact compile to the same single-element tuple, so nothing downstream branches on which of the two forms an artifact declared (FR-003’s instruction-side counterpart).
- class loom.ai.compiler.CompiledMcpCapability(*, server, transport='http', url=None, headers_ref=None, auth=None, timeout_ms=20000, command=None, args=(), env=(), include=(), exclude=())[source]¶
Bases:
LoomFrozenStructMCP server grant, resolved against
ai.mcp_servers.The artifact names a server; the plan carries the resolved handle — the transport with its address or command, the credential reference and the deadline — so nothing downstream re-reads configuration. The URL or the command resolves in
__aenter__, over the network or by spawning a subprocess: it is one of the declared exceptions to “strings die at compile” (invariant 3), and so is the filter, which is applied against the server’s real tool list.Configuration already proved the fields coherent with the transport, so
urlis set exactly underhttpandcommandexactly understdio; the engine narrows by transport, never by field.- Parameters:
- auth¶
Named authentication strategy, mutually exclusive with
headers_ref;Nonewhen the server needs no credential.- Type:
- env¶
Environment handed to the subprocess as key-sorted pairs, so the plan stays a hashable value whatever order the operator wrote.
- class loom.ai.compiler.CompiledOutput(*, schema, decoder)[source]¶
Bases:
LoomFrozenStructStructured-output contract with a decoder built at compile time.
Interpreting the schema per response would be per-item reflection, so the decoder is constructed exactly once, at compile (research R-004, invariant 5). The decode is strict: unknown fields are rejected, which is what makes returning the validated bytes unchanged safe.
- schema¶
JSON Schema object handed to the model.
- Type:
collections.abc.Mapping[str, Any]
- decoder¶
Built
msgspecJSON decoder producing the answer type.- Type:
msgspec.json.Decoder[Any]
- class loom.ai.compiler.CompiledOutputHook(*, usecase, use_case, accepted)[source]¶
Bases:
LoomFrozenStructUse case executed once per completed run, resolved and proven feedable.
The compiler proves that every required, user-supplied name of the use case’s Input is one of
HOOK_OUTPUT_FIELDorHOOK_CONTEXT_FIELDS, so the runtime never discovers a missing field at the end of a run.acceptedis computed here, once, frommsgspec.structs.fields: the runtime filters the offered dict to it beforefrom_payloadso a strict Command works without per-run reflection.- use_case¶
Registered use-case type, as
CompiledUsecaseCapability.use_casescarries them.- Type:
type[loom.core.engine.compilable.Compilable]
- class loom.ai.compiler.CompiledPythonCapability(*, factory_ref, factory, params=<factory>)[source]¶
Bases:
LoomFrozenStructApplication toolset factory resolved to an importable callable.
- factory¶
Imported factory, called once at build as
factory(context, **params)with aToolsetContextfirst.- Type:
- params¶
Keyword arguments the artifact declared for the factory. The names bind to the factory’s signature (checked at compile); the values are decoded YAML carried as-is.
- Type:
collections.abc.Mapping[str, Any]
- class loom.ai.compiler.CompiledRemoteAuth(*, kind, settings=())[source]¶
Bases:
LoomFrozenStructAuthentication strategy of one remote endpoint, resolved to name and settings.
One struct serves both outbound transports, MCP servers and A2A agents, as the one registry that builds it does: the strategy contract is
httpx.Auth, which knows nothing of either protocol.kindis separated from the rest of theauthblock once, here, so the engine never re-reads configuration to find out which strategy to build. The settings are carried as ordered pairs rather than a mapping because the plan is a frozen, hashable value.
- class loom.ai.compiler.CompiledSkillsCapability(*, library, directory, names)[source]¶
Bases:
LoomFrozenStructSkill library resolved to a directory and a selected set of skill names.
Both globs and the library reference die at compile: the plan carries the absolute directory and the exact skill names granted, so the engine loads them without re-interpreting the artifact.
- class loom.ai.compiler.CompiledSqlCapability(*, connection, config, max_rows, max_result_bytes)[source]¶
Bases:
LoomFrozenStructRead-only SQL access resolved to its connection configuration.
- Parameters:
connection (str)
config (SqlConnectionConfig)
max_rows (int)
max_result_bytes (int)
- config¶
Validated read-only connection configuration.
- class loom.ai.compiler.CompiledUsecaseCapability(*, keys, use_cases)[source]¶
Bases:
LoomFrozenStructGranted business operations resolved against the use-case registry.
- loom.ai.compiler.mcp_connection(capability)[source]¶
Return the connection identity of one
mcpgrant, its filters cleared.A worker opens one client per MCP connection and every agent granted it works over that one client, so what makes two grants the same client is every fact the connection is made of — transport, address, credential reference, deadline, subprocess command, arguments and environment.
includeandexcludeare per-agent views over the same connection, so they are emptied here and applied by the agent’s own toolset instead.- Parameters:
capability (CompiledMcpCapability) – Compiled grant of one agent.
- Returns:
The same grant with
includeandexcludeemptied. It is hashable, so it doubles as the key a shared client is stored under and as the capability that client is built from.- Return type:
Example:
assert mcp_connection(read_only) == mcp_connection(read_write)