loom.ai.abc¶
Neutral runtime contracts of the AI pillar.
Everything the compiler, the runtime and the HTTP layer share with an engine
lives here, and nothing here imports an engine: the bootstrap resolves the
provider through loom.ai.registry and hands the compiler plain values.
A run may continue a conversation the application loaded (FR-034): the prior
history crosses this boundary as opaque, engine-native bytes inside
Conversation, and the run’s new messages come back the same way on
AgentResult.messages and FinalEvent.messages. Loom defines no
message model and stores no history.
These contracts are experimental and may change within a major line; the
artifact format they serve is not. See loom.ai for the distinction.
Module Attributes
Longest |
|
Output type of an |
|
Per-run output type passed to |
|
Decoded type of a single |
|
Closed five-member tagged union of streaming events (FR-030). |
|
The three health states. |
|
Target of a |
|
Answers which provider tools a model binding admits, by loom tool name. |
|
a pure predicate over an answer. |
Classes
|
Outcome of one run reached through an |
|
One compiled agent, ready to run. |
|
Entry-point target in group |
|
A named agent reached from another use case, bound to this run's caller. |
|
Outcome of a non-streaming agent run. |
|
Resource accounting of one agent run. |
Declares an |
|
|
The conversation a run continues. |
|
Builds per-invocation dependencies for capability calls. |
|
The run failed mid-stream (FR-032). |
|
The run completed; the only variant carrying usage. |
|
Health of one agent engine, shared by every engine (FR-048). |
|
A caller-bound, filtered view of one MCP server's tools. |
|
Minimal MCP session the runtime needs from any client library. |
|
The server's own answer to one |
|
One tool a session's server advertises. |
|
One artefact's own bounded view of one of its |
|
The one shape |
|
Incremental model text. |
|
The model invoked a tool. |
|
A tool invocation completed. |
|
What a |
- loom.ai.abc.CONVERSATION_ID_MAX_LENGTH: Final[int] = 128¶
Longest
conversation_ida run accepts; the value itself is opaque.
- class loom.ai.abc.AnswerT¶
Output type of an
AgentHandle, carried by the annotation on the use-case parameter it fills — never by the marker that fills it.alias of TypeVar(‘AnswerT’)
- class loom.ai.abc.ExpectedT¶
Per-run output type passed to
AgentHandle.run()throughexpect, independent of the handle’s ownAnswerT.alias of TypeVar(‘ExpectedT’)
- class loom.ai.abc.ToolResultT¶
Decoded type of a single
McpHandle.call().alias of TypeVar(‘ToolResultT’)
- class loom.ai.abc.StateShape(*, schema, decoder)[source]¶
Bases:
LoomFrozenStructThe one shape
deps_type/deps_schemacompile to (FR-003).deps_schema,deps_type: <symbol>anddeps_type: dictare three authored spellings of one optional JSON Schema; the compiler resolves all three to this value, never to one of three interchangeable objects. Same idiom as its siblingCompiledOutput, including adecoderfield msgspec cannot itself encode, under the invariantloom.ai.compiler._plandocuments.- schema¶
JSON Schema the artifact’s state must satisfy, or
Noneunder thedeps_type: dictwaiver, where no schema exists and template markers are not validated (FR-006).- Type:
collections.abc.Mapping[str, Any] | None
- decoder¶
Built
msgspecJSON decoder producing the normalised state mapping, orNonealongsideschema is None.- Type:
msgspec.json.Decoder[Any] | None
- class loom.ai.abc.AgentUsage(*, input_tokens, output_tokens, requests, duration_ms, cache_read_tokens=0, cache_write_tokens=0, tool_calls=0, cost=None, details=<factory>)[source]¶
Bases:
LoomFrozenStructResource accounting of one agent run.
Nothing the engine reported is dropped. The counters any engine would plausibly report are named fields; every other field it returned — the audio counters, a provider’s own extras, a field a future engine release adds — rides verbatim in
details, so a new counter reaches the caller without a change here. The engine’s own usage type never crosses this boundary: a second engine fills this struct.- Parameters:
- cache_read_tokens¶
Input tokens served from the provider’s prompt cache, already counted in
input_tokens. A cached token costs a fraction of a fresh one, so comparing models oninput_tokensalone can invert the ranking.- Type:
- cache_write_tokens¶
Input tokens written to the prompt cache, already counted in
input_tokens.- Type:
- cost¶
Run cost in the engine’s currency, or
Nonewhen the engine could not price the model. Absent rather than zero: a zero would silently win a cost comparison.- Type:
decimal.Decimal | None
- details¶
Every field the engine reported that has no named field here, under the engine’s own names. Not disjoint from the named counters: a provider that reports its own
cached_tokensalongside the normalisedcache_read_tokenshas both, so summingdetailsdouble-counts.- Type:
- class loom.ai.abc.Conversation(*, conversation_id, history=None)[source]¶
Bases:
LoomFrozenStructThe conversation a run continues.
- class loom.ai.abc.AgentResult(*, output, usage, interaction_id=None, hook_result=None, messages=None)[source]¶
Bases:
LoomFrozenStructOutcome of a non-streaming agent run.
- Parameters:
output (object)
usage (AgentUsage)
interaction_id (str | None)
hook_result (object | None)
messages (bytes | None)
- usage¶
Resource accounting of the run.
- Type:
- class loom.ai.abc.AgentAnswer(*, output, usage, interaction_id=None)[source]¶
Bases:
LoomFrozenStruct,Generic[AnswerT]Outcome of one run reached through an
AgentHandle.Carries this run’s answer and this run’s own accounting, and nothing else:
usageis scoped to the single call that produced this answer and is never merged with the usage of another call the same handle made, or of the parent run that reached this agent in the first place. A use case that runs the same handle three times gets three independentAgentAnswervalues with three independentusagefields; summing them, if a caller wants a total, is the caller’s own arithmetic.- Parameters:
output (AnswerT)
usage (AgentUsage)
interaction_id (str | None)
- output¶
Decoded answer of this run — the artefact’s declared output shape by default, or the type passed as
expectwhen the run overrode it for this call only.- Type:
- usage¶
Resource accounting of this run only.
- Type:
- class loom.ai.abc.McpHandle(*args, **kwargs)[source]¶
Bases:
ProtocolA caller-bound, filtered view of one MCP server’s tools.
Two paths hand one out, and they differ in where the filter comes from.
AgentHandle.mcp()returns the artefact’s own grant: the very same composed view, over the same shared session and the same include/exclude predicate, that the model’s own toolset runs over — nothing there is re-declared, so it cannot diverge. AnMcp()marker returns a view whose filter is the signature’s owninclude, which may be wider than any agent’s. That is a second, independently declared filter, and the guarantee it carries is not that no wider view exists: it is that the widening is written down in the signature and verified against the server’s real tool list at start-up.Both are views over one shared session, never a second connection, and both run under the same guard — authentication, timeout, span, expiry. Only the deadline’s source differs: the agent path uses its plan’s numbers, and the marker path, which belongs to no plan, uses the server’s own
timeout_ms.- async call(tool, arguments, *, expect)[source]¶
Call tool and decode its structured result into expect.
Two methods exist here instead of one method with an optional
expect— this one andcall_untyped()— because an optional argument would govern two different behaviours from one parameter, which this framework’s rules on multi-behaviour flags forbid, and it would turn the unshaped path into an omission instead of a decision. Typed is what this method commits to; the unshaped path is the separately named, deliberate exception.Loom does not compare
expectagainst the tool’s published output schema — that comparison is JSON Schema subsumption, whose verdict would only be approximate. Decoding the structured result intoexpectis the check, and it is exact: a mismatch names the field and the type that did not fit.- Parameters:
- Returns:
The decoded result.
- Raises:
AgentRunError – With a code naming why the call did not produce a decoded
expect— the tool is outside this grant’s filter, the tool publishes no output schema, the tool reported a failure, the server returned no structured content despite publishing a schema, the structured content did not decode intoexpect, or — on theMcp()marker path, underai.remote_clients: optional— the server this grant names never connected at start-up (TOOL_UNAVAILABLE).- Return type:
- async call_untyped(tool, arguments)[source]¶
Call tool and return the server’s own result, undecoded.
The deliberate exception to
call()’s typed default — for a tool that never publishes an output schema, or for a caller who genuinely wants the server’s own shape.Mapping[str, Any]is admissible here specifically because this signature has nowhere to put a type parameter; it is not a general-purpose escape hatch.- Parameters:
- Returns:
The server’s own structured result, unvalidated and undecoded.
- Raises:
AgentRunError – With a code naming why the call failed — the tool is outside this grant’s filter, the tool reported a failure, the server returned structured content that is not a mapping (a list, a scalar) — a contradiction of the protocol this method returns, distinct from returning no structured content at all, which comes back as
{}— or, on theMcp()marker path underai.remote_clients: optional, the server this grant names never connected at start-up (TOOL_UNAVAILABLE).- Return type:
- class loom.ai.abc.SqlGrantHandle(*args, **kwargs)[source]¶
Bases:
ProtocolOne artefact’s own bounded view of one of its
sqlgrants.Queries the same read-only connection under the same row and byte bounds, and the same plan timeout, that the artefact’s own
sqlcapability enforces for the model — the granted view, not a second one a use case could widen.- async query(statement, *, parameters=None)[source]¶
Run a read-only statement bounded by this grant’s own limits.
- Parameters:
- Returns:
Result rows, each as a column-name-to-value mapping, truncated to this grant’s row and byte bounds.
- Raises:
AgentRunError – With a code naming why the query did not run — the connection is outside this artefact’s grants, or the grant’s own bounds rejected the result.
- Return type:
- class loom.ai.abc.AgentHandle(*args, **kwargs)[source]¶
-
A named agent reached from another use case, bound to this run’s caller.
Filled by the executor when a use case declares one in its
executesignature throughloom.core.use_case.markers.Agent(), and never constructed directly. The type argument this Protocol carries —AgentHandle[SeverityAssessment]on the parameter’s annotation — is what the compiler checks against the named agent’s own declared output at start-up;Agent()itself returns an untyped value, for the same reason every other marker in this vocabulary does.Exactly three arguments cross this boundary on a per-run basis: the prompt, the shape of the answer, and which conversation it continues. Nothing else does. What the agent may reach, what it may cost and which model serves it are decided once — by the artefact and by deployment configuration — and stay there; a per-run argument that changed any of them would be a second place the same policy could drift.
- async run(prompt: str, *, conversation_id: str | None = None, state: object | None = None) AgentAnswer[AnswerT][source]¶
- async run(prompt: str, *, expect: type[ExpectedT], conversation_id: str | None = None, state: object | None = None) AgentAnswer[ExpectedT]
Run the agent once and decode its answer.
Without
expect, the answer is decoded into the artefact’s own declared output shape — this handle’s type argument. Withexpect, that declared shape is a default rather than a ceiling: this run only is decoded intoexpectinstead. The override applies to this call and nothing else; it is never merged with the artefact’s declared shape and never carries over to the handle’s next call.The artefact’s own output check — the retry loop that asks the model to correct a violation of its declared schema — does not run when
expectoverrides the shape. That is forced, not chosen: the check is compiled against the declared schema, so handing it another shape would either fail inside the engine’s own retry loop or invent a verdict loom has no basis for. Validating an overridden shape is the calling code’s job instead, and it is better placed there: holding a typed answer, calling code can act on a bad verdict — for example asking again in a loop it controls — rather than only reporting one.Permissions never travel through this call. What the agent may reach comes from the artefact’s own grants and from the identity already bound to this handle;
expectchanges what comes back, never what the agent is allowed to do.- Parameters:
prompt (str) – Prompt for this run.
expect (type[ExpectedT] | None) – When given, decode this run’s answer into this type instead of the artefact’s declared output. Applies to this run only.
conversation_id (str | None) – Identifier of the conversation this run continues;
Noneruns single-shot.state (object | None) – This run’s state, or
None. Reaches the artefact’s dependency bundle normalised against its declared shape; given against an artefact declaring nodeps_typeordeps_schema, the call is refused rather than dropped silently (FR-010).
- Returns:
The decoded answer, this run’s own usage and its interaction id.
- Raises:
AgentRunError – With
AGENT_RUN_SHAPE_WITH_HOOKwhenexpectis given and the artefact’s output hook command declares the output field — refused before the model is called, since the hook could not be handed an answer shaped byexpect; withSTATE_UNDECLAREDwhenstateis given and the artefact declares no state shape.- Return type:
- async run_text(prompt, *, conversation_id=None, state=None)[source]¶
Run the agent for open prose, pinning this run’s answer to
str.A named spelling of
run(prompt, expect=str)rather than a third overload of it — the name states the form this run asks for, open prose, not the author’s intent, because the form is the only part loom knows. Being a shape pin, this mode runs no output check (run()’s own note onexpectapplies here too: the check is compiled against the artefact’s declared schema and cannot validate another one) and is refused before the model is called under exactly the conditionrun’sexpectis: when the artefact’s output hook command declares theoutputfield, which was compiled against the declared shape and cannot be handedstrinstead.- Parameters:
- Returns:
The model’s own prose, this run’s usage and its interaction id.
- Raises:
AgentRunError – With
AGENT_RUN_SHAPE_WITH_HOOKwhen the artefact’s output hook command declares theoutputfield — refused before the model is called, for the same reasonrun()raises it withexpectgiven; withSTATE_UNDECLAREDfor the same reasonrun()raises it.- Return type:
- mcp(server)[source]¶
Return the artefact’s own filtered view of one
mcpgrant.- Parameters:
server (str) – Server name as the artefact’s own
mcpcapability declares it. Not verified at start-up — only a compiled agent name and its output type are — so a typo here is caught on first call, not before.- Returns:
The grant’s own view, filtered exactly as the model’s is.
- Raises:
AgentRunError – With
MCP_GRANT_UNKNOWNwhen the artefact declares nomcpgrant on that server name.- Return type:
- sql(connection)[source]¶
Return the artefact’s own bounded view of one
sqlgrant.- Parameters:
connection (str) – Connection name as the artefact’s own
sqlcapability declares it. Not verified at start-up, for the same reasonmcp()’sserveris not.- Returns:
A view bounded by that grant’s own row and byte limits, under the plan’s timeout.
- Raises:
AgentRunError – With
SQL_GRANT_UNKNOWNwhen the artefact declares nosqlgrant on that connection name.- Return type:
- class loom.ai.abc.TextDeltaEvent(*, text)[source]¶
Bases:
LoomFrozenStructIncremental model text.
- Parameters:
text (str)
- class loom.ai.abc.ToolCallEvent(*, tool, call_id, arguments)[source]¶
Bases:
LoomFrozenStructThe model invoked a tool.
- arguments¶
Arguments the model supplied.
- Type:
collections.abc.Mapping[str, Any]
- class loom.ai.abc.ToolResultEvent(*, call_id, ok, summary)[source]¶
Bases:
LoomFrozenStructA tool invocation completed.
- class loom.ai.abc.ErrorEvent(*, code, message, interaction_id=None, usage=None)[source]¶
Bases:
LoomFrozenStructThe run failed mid-stream (FR-032).
- Parameters:
code (AgentRunErrorCode)
message (str)
interaction_id (str | None)
usage (AgentUsage | None)
- code¶
Stable run-time failure code; the retry policy reads its class.
- interaction_id¶
Identifier of the admitted run this failure belongs to;
Nonebefore admission.- Type:
str | None
- usage¶
What the failed run had already spent, when the engine knew it. A run that made three model round trips and then failed its output schema still cost money, and a model that fails more must not rank better on cost for it.
Nonewhen nothing was spent or nothing was measurable — a refusal before admission, a run a declared limit killed from outside the engine. Not on the wire: the stream contract putsusageonfinalonly.- Type:
loom.ai.abc.AgentUsage | None
- class loom.ai.abc.FinalEvent(*, output, usage, interaction_id=None, hook_result=None, messages=None)[source]¶
Bases:
LoomFrozenStructThe run completed; the only variant carrying usage.
- Parameters:
output (object)
usage (AgentUsage)
interaction_id (str | None)
hook_result (object | None)
messages (bytes | None)
- usage¶
Resource accounting of the whole run.
- Type:
- loom.ai.abc.AgentEvent = loom.ai.abc.TextDeltaEvent | loom.ai.abc.ToolCallEvent | loom.ai.abc.ToolResultEvent | loom.ai.abc.ErrorEvent | loom.ai.abc.FinalEvent¶
Closed five-member tagged union of streaming events (FR-030).
Exactly one of
finalorerrorterminates every stream (SC-011), andfinalis the only variant carrying usage.Adding a variant requires two independent real consumers (FR-035): a single engine wanting a richer event is not grounds to widen a union every SSE client, test fake and contract suite must understand.
- class loom.ai.abc.AgentEngine(*args, **kwargs)[source]¶
Bases:
ProtocolOne compiled agent, ready to run.
Engines take a single prompt and, optionally, the conversation the run continues: an opaque, engine-native history the application loaded (FR-034). Loom defines no message model and stores no history; an engine that receives
conversation=Noneruns single-shot.- async run(prompt, *, identity, conversation=None, state=None)[source]¶
Run the agent to completion.
- Parameters:
prompt (str) – Caller prompt.
identity (Identity) – Verified caller; every capability call runs as them.
conversation (Conversation | None) – The conversation this run continues;
Noneruns single-shot.state (object | None) – This run’s state, already decoded by whichever boundary received it and normalised against the artefact’s declared shape — never parsed again here (FR-008).
Nonefor an artefact declaring no state, or for a stateful one whose caller supplied none, in which case it carries the shape’s own declared defaults instead of an empty value.
- Returns:
The validated output, the run’s usage and this run’s messages, bounded by
policies.max_history_bytes(Noneabove it).- Return type:
- run_stream(prompt, *, identity, conversation=None, state=None)[source]¶
Run the agent, streaming events.
Returns an async context manager rather than a bare iterator so that closing the stream — and the provider connection behind it — is deterministic on exit instead of being left to the garbage collector.
- Parameters:
prompt (str) – Caller prompt.
identity (Identity) – Verified caller; every capability call runs as them.
conversation (Conversation | None) – The conversation this run continues;
Noneruns single-shot.state (object | None) – This run’s state; see
run()’s ownstatefor what it carries.
- Returns:
An async context manager yielding the event stream.
- Return type:
AbstractAsyncContextManager[AsyncIterator[TextDeltaEvent | ToolCallEvent | ToolResultEvent | ErrorEvent | FinalEvent]]
- loom.ai.abc.HealthState¶
The three health states. Defined beside the struct that carries it so the alias and the field cannot drift apart.
alias of
Literal[‘ok’, ‘degraded’, ‘unavailable’]
- class loom.ai.abc.HealthStatus(*, status, detail=None)[source]¶
Bases:
LoomFrozenStructHealth of one agent engine, shared by every engine (FR-048).
- status¶
"ok","degraded"or"unavailable".- Type:
Literal[‘ok’, ‘degraded’, ‘unavailable’]
- class loom.ai.abc.McpToolInfo(*, name, has_output_schema)[source]¶
Bases:
LoomFrozenStructOne tool a session’s server advertises.
- has_output_schema¶
Whether the server published a schema for this tool’s structured result. A
McpHandlerefuses a typed call on a tool for which this isFalse, before any network call — seeMcpHandle.call().- Type:
- class loom.ai.abc.McpToolCallResult(*, ok, structured=None)[source]¶
Bases:
LoomFrozenStructThe server’s own answer to one
call_tool, protocol-level and undecoded.
- class loom.ai.abc.McpSession(*args, **kwargs)[source]¶
Bases:
ProtocolMinimal MCP session the runtime needs from any client library.
Migration (breaking, from v1.16.1):
list_toolsused to return tool names (tuple[str, ...]) andcall_toolused to return the server’s structured content directly (object). Both shapes shipped, so a third-party session implementing this Protocol has to update both methods.list_toolsnow returnsMcpToolInfoso a caller can see which tools publish an output schema, andcall_toolnow returnsMcpToolCallResultso a caller can see the server’s own failure flag instead of having it silently folded into a successful-looking return. Nothing else about the Protocol moved.- async list_tools()[source]¶
Return the tools the server exposes.
- Returns:
Every tool the server advertises, before any declared filter is applied, each carrying whether it publishes an output schema.
- Return type:
tuple[McpToolInfo, …]
- class loom.ai.abc.ConcurrentMcpSession[source]¶
Bases:
objectDeclares an
McpSessionimplementation already safe for concurrent calls.A JSON-RPC session is one framed stream: two callers writing into it at the same time can interleave their frames, and a caller cancelled mid-call can leave the stream desynchronised for whoever is waiting beside it. That is why a session gets serialised behind one lock by default. A session that already guards its own frames — one that multiplexes concurrent calls by matching each response back to its own request id, rather than writing straight through a single unmatched stream — declares that guarantee by also subclassing this, in addition to implementing
McpSession, and the runtime leaves it unwrapped.This class carries no members: subclassing it is the declaration. A session that does not subclass it is treated exactly as every
McpSessionwas before this class existed — wrapped and serialised — because not declaring the guarantee is the safe default, never a failure.A subclass keeping this promise must (a) tolerate overlapping calls by matching each response back to its own request id — the multiplexing that makes the guarantee true in the first place — and (b) must not shield a call from its own caller’s cancellation the way the runtime’s locked wrapper does: with no shared frame to desynchronise, there is nothing left to drain, and shielding would only stop the plan’s own
tool_timeout_msfrom bounding the call.
- class loom.ai.abc.ToolsetContext(*args, **kwargs)[source]¶
Bases:
ProtocolWhat a
kind: pythonfactory may reach while building its toolset.A build-time object: the engine hands it to the factory once, at start-up, and nothing keeps it alive afterwards. A factory resolves the remotes it needs in its body and keeps the session on the toolset it returns; it must not call
remote()lazily from a tool at run time.remote()is bounded to themcpgrants of the same agent: it returns the worker’s shared session for a server the agent’s own artifact declared, and nothing else. Calls made through that session go to the shared connection directly, so they bypass theinclude/excludefilter of themcpgrant.- property container: LoomContainer¶
Application container the factory may resolve services from.
- remote(server)[source]¶
Return the agent’s shared session for one of its
mcpservers.- Parameters:
server (str) – Server name as the agent’s
mcpgrant declares it.- Returns:
The session the agent’s own
mcptoolset runs over.- Raises:
AgentCompilationError – When the agent has no
mcpgrant on that server.- Return type:
- loom.ai.abc.ToolsetFactory¶
Target of a
kind: pythoncapability, validated at compile time.Called exactly once at build as
factory(context, **params): the first positional is aToolsetContext, and the artifact’sparamsarrive as keyword arguments. A factory declares its own named parameters, with defaults, and returns the engine-facing toolset. The parameter names are checked against the signature at compile time. It is a plainCallablealias rather than a Protocol because a Protocol fixing**paramswould reject every factory that names them.
- class loom.ai.abc.DepsFactory(*args, **kwargs)[source]¶
Bases:
ProtocolBuilds per-invocation dependencies for capability calls.
Singleton services are captured once at build;
Identityis supplied per invocation so every capability call runs as the caller (FR-043). The bundle also carries the invocation’sstate, alongside the verified caller and the container, never instead of them: a capability call readsidentityandcontaineroff the bundle the same way regardless of whetherstateis present.- build(identity, container, state=None)[source]¶
Build the dependency bundle for one invocation.
- Parameters:
identity (Identity) – Verified caller of this invocation.
container (LoomContainer) – Application container holding the singleton services.
state (Mapping[str, Any] | None) – The invocation’s state, a mapping normalised against the artefact’s declared shape, or
Nonefor an artefact that declares no state or a call that supplies none.
- Returns:
The engine-facing dependency bundle.
- Return type:
- loom.ai.abc.NativeToolSupport¶
Answers which provider tools a model binding admits, by loom tool name.
Supplied by an engine as an optional
native_tool_supportattribute and read withgetattr, so the compiler learns what a binding admits without importing an engine. May raiseAgentCompilationErrorwhen the provider SDK is missing.alias of
Callable[[InferenceTarget],frozenset[str]]
- loom.ai.abc.OutputCheck¶
a pure predicate over an answer.
Called once per attempt inside the engine’s own output-retry loop, with the mapping the engine parsed from the model’s answer — never loom’s decoded object, so nothing is decoded twice. Returns
Noneto accept the answer unchanged, or the text the model must read to correct itself, which drives a real retry bounded by the artifact’spolicies.retries.The return contract is the inverse of the usual predicate convention, which is why this alias is published rather than left for an author to spell: it is the one name in this module carrying
Mapping[str, Any], because the payload shape is the artifact’s own declared schema, which loom cannot type statically.A returned mapping is never substituted for the answer: the engine decodes the model’s own bytes independently of what this callable returns, so a check that builds and returns a different mapping has that mapping discarded. Synchronous and dependency-free, because any side effect inside the retry loop would run once per attempt.
- Type:
Target of an
output_checkreference
- class loom.ai.abc.AgentEngineProvider(*args, **kwargs)[source]¶
Bases:
ProtocolEntry-point target in group
loom.ai.engines.- LOOM_AI_ENGINE_API¶
Handshake version, checked with
getattron load — never withisinstance.- Type:
ClassVar[int]
- native_tool_support¶
Optional
NativeToolSupport, read withgetattr; an engine that serves nonativegrant omits it.
- create_engine(plan, *, deps, container)[source]¶
Build one engine for one compiled plan.
Called exactly once per plan by the runtime, never per request.
- Parameters:
plan (object) – The compiled
AgentPlan. Typed asobjecthere because the plan struct is built in phase 4; the parameter narrows toAgentPlanthen (recorded decision).deps (DepsFactory) – Per-invocation dependency factory.
container (LoomContainer) – Application container.
- Returns:
The engine serving this plan.
- Return type: