Skip to main content
The assembled TaiApp facade. One Protocol per feature (see tai42_contract.app.facets), composed into a single TaiApp protocol that exposes them as namespaces (app.tools, app.agents, …). The app members are partitioned across the sub-protocols — each lives in exactly one, save the shared leaf names store (versioning + presets + tool_meta) and register/get (webhook_verifiers + channels). The runtime forwarding handle is tai42_app (see tai42_contract.app.handle).

AppAccounts

tai42_contract.app.facets.integrations.AppAccounts
Read access to the CURRENT epoch’s live identity/accounts provider instances. An accounts-provider plugin ships login routes that need the SAME provider instance the epoch built and probed (its resolved config, cached discovery/JWKS, injected settings). Rather than a module-level holder — which a failed epoch build would leave pointing at a half-built generation — the plugin’s routes resolve the live instance here. The contract exposes only this read; the runtime forwards it to the current epoch, so the contract never learns about epochs.

Members

active_provider

tai42_contract.app.facets.integrations.AppAccounts.active_provider
The provider the CURRENT epoch instantiated under name, or None when none is active. An AccountsProvider is an IdentityProvider. None means no provider is active under that name — the name is not configured, or a build is mid-flight. Parameters

AppAdmin

tai42_contract.app.facets.runtime.AppAdmin
In-process admin operations: MCP binding, tool reload, config reload.

Members

reload_mcp

tai42_contract.app.facets.runtime.AppAdmin.reload_mcp
Rebind the MCP server titled title and return its status. Parameters

deregister_mcp

tai42_contract.app.facets.runtime.AppAdmin.deregister_mcp
Remove the MCP server titled title and return its status. Parameters

reload_config

tai42_contract.app.facets.runtime.AppAdmin.reload_config
Re-init the process config in place and return the reload report.

tool_reloader

tai42_contract.app.facets.runtime.AppAdmin.tool_reloader
Register an async (action, name) -> dict reloader for kind. Parameters

run_tool_reload

tai42_contract.app.facets.runtime.AppAdmin.run_tool_reload
Run the registered kind reloader for action on name. Parameters

reload_failed_mcps

tai42_contract.app.facets.runtime.AppAdmin.reload_failed_mcps
Retry every MCP that failed to bind and return their statuses.

list_failed_mcps

tai42_contract.app.facets.runtime.AppAdmin.list_failed_mcps
List the MCPs that failed to bind.

live_mcp_status

tai42_contract.app.facets.runtime.AppAdmin.live_mcp_status
Snapshot the in-process MCP-binding state.

live_manifest

tai42_contract.app.facets.runtime.AppAdmin.live_manifest
The manifest currently live in this process.

AppAgents

tai42_contract.app.facets.execution.AppAgents
The agent-provider namespace (app.agents).

Members

agent

tai42_contract.app.facets.execution.AppAgents.agent
Register an Agent subclass under name and auto-register its JSON run tool. tags are the run tool’s native tags, set on its constructed tool object. meta is generic registration metadata threaded onto the same constructed run-tool object (naming no consumer concept — a registrant attaches any generic tai42/* key, e.g. a crash-resume flag the run-dispatch seam reads). The decorator returns the class unchanged, so the decorated symbol keeps its concrete subclass type. Parameters

get_agent

tai42_contract.app.facets.execution.AppAgents.get_agent
Fetch a registered agent instance by name; raise if missing. Parameters

all_agents

tai42_contract.app.facets.execution.AppAgents.all_agents
Return every registered agent keyed by registration name. The result is a shallow copy, so a caller iterating it cannot mutate the live registry. The preset bind kernel reads the keys to detect an agent base (the run tool binds under the registration name).

AppBackends

tai42_contract.app.facets.execution.AppBackends
The backend-provider namespace (app.backends).

Members

register_backend

tai42_contract.app.facets.execution.AppBackends.register_backend
Register the Backend provider; usable bare or as a decorator factory.

backend

tai42_contract.app.facets.execution.AppBackends.backend
The registered backend provider, or None when none is registered.

AppBackup

tai42_contract.app.facets.runtime.AppBackup
Registry for named backup sections and the run of one section’s export/import. A plugin (or the host itself, the first consumer) registers a section under name by supplying an exporter() that returns a JSON-safe payload and an importer(payload) that applies it and returns a section report. sections() lists the registered sections for the UI. export_section / import_section run one section’s exporter/importer by name and raise loudly on an unknown name — never a silent no-op.

Members

register_section

tai42_contract.app.facets.runtime.AppBackup.register_section
Register a backup section’s exporter/importer under name. Parameters

sections

tai42_contract.app.facets.runtime.AppBackup.sections
List the registered backup sections.

export_section

tai42_contract.app.facets.runtime.AppBackup.export_section
Run one section’s exporter by name and return its payload. Parameters

import_section

tai42_contract.app.facets.runtime.AppBackup.import_section
Apply payload via one section’s importer by name and return its report. Parameters

AppChannels

tai42_contract.app.facets.messaging.AppChannels
The channel registry namespace (app.channels) and inbound-answer ladder.

Members

register

tai42_contract.app.facets.messaging.AppChannels.register
Register a Channel under name. A channel plugin calls this through the tai42_app handle when its import-only channel_modules entry loads. Registering a name already taken raises loudly — a silent overwrite could swap the medium a live ask is delivered on. Parameters

get

tai42_contract.app.facets.messaging.AppChannels.get
Fetch a registered channel by name; raise loudly on an unknown name. Resolution happens when ask is called with channel=name, BEFORE any interaction state is written, so an unknown name surfaces as a loud failure, never a question silently delivered nowhere. Parameters

names

tai42_contract.app.facets.messaging.AppChannels.names
Every registered channel name, for the channels catalog route.

handle_inbound_answer

tai42_contract.app.facets.messaging.AppChannels.handle_inbound_answer
Resolve one inbound participant reply against its pending ask. This is the ONE shared inbound-answer ladder every correlated channel calls instead of hand-rolling its own “forward → interpret 2xx/404/400 → release/bridge/keep” sequence. Returns an InboundAnswerResult: the outcome the channel maps to its transport ack, plus the door’s retry_reason/retry_field when it rejected the answer’s content, so a channel that owns its correction surface can render the door’s specific message. A channel computes its own opaque correlation_key for the participant’s address, provides the answer value to forward to the door, its CorrelationStore, and an InboundBridge of the fields a bridged turn needs. SEAM SYMMETRY (bridge.params ↔ answer params): the InboundBridge may carry opaque channel enrichment in params — the answer-path counterpart of a conversation entry’s params. The ladder threads it BOTH ways so enrichment is never dropped on either arm: the answer is forwarded to the ask’s callback door as {"answer": answer, "params": params} (params present only when set), landing on params for the asking flow to read beside answer; and on the BRIDGE arm the same params are passed to accept as its entry params. The ladder:
  • No pending ask on the key -> InboundAnswerOutcome.NO_CORRELATION with NO side effect: the CALLER bridges the reply as a normal turn (the ladder never bridges on a miss, exactly as each channel did by hand).
  • The door accepts (2xx) -> release the correlation, return InboundAnswerOutcome.FORWARDED.
  • The door returns 404 (the ask was withdrawn/expired/cancelled) -> release, bridge the reply as a fresh turn, return InboundAnswerOutcome.BRIDGED.
  • The door returns 400 on a LIVE ask -> read the door’s retry_in_place (default True): True keeps the correlation, notifies the participant what’s expected, fires ONE operator event, returns InboundAnswerOutcome.RETRY_KEPT; False (a hard mismatch) releases, notifies the participant the question is closed, fires the event, bridges the reply, returns InboundAnswerOutcome.BRIDGED.
  • Anything else (401/413/5xx, or a transport fault) -> do NOT release; raise AnswerForwardError so the channel’s webhook redelivery re-runs the ladder. The answer is never silently lost.
The callback host is pinned to the platform’s configured public base before the forward; a stored callback whose host does not match is released and treated as InboundAnswerOutcome.NO_CORRELATION. Parameters

record_send_receipt

tai42_contract.app.facets.messaging.AppChannels.record_send_receipt
Post an out-of-band delivery receipt for a notify_user send back onto its originating trace. The send is a notify_user channel send with no conversation record. The tier-2 counterpart to the conversation bridge’s record_delivery_status: a channel’s delivery-status webhook calls this when the bridge does not own the outbound id (record_delivery_status raised LookupError). It resolves the id through the TTL’d send-receipt index and, on a hit, emits a delivery_receipt event into the recorded trace (a FAILED receipt at ERROR level), so the originating trace shows delivered-vs-accepted for its sends. errors carries any provider error detail for the event input. Returns True when the id was a known send (event emitted), False when it is not — so the webhook keeps its genuinely-unknown-id log only on a False. A no-op returning False where the send-receipt store is unconfigured. Parameters

AppClients

tai42_contract.app.facets.runtime.AppClients
Pooled async client lifecycle for the process.

Members

client_ctx

tai42_contract.app.facets.runtime.AppClients.client_ctx
Yield a connected client as an async context manager. Pooled per loop + connection params, or one-shot when fresh=True. settings is a kit ClientSettings whose client_kwargs() supplies the connection key. Parameters

shutdown_clients

tai42_contract.app.facets.runtime.AppClients.shutdown_clients
Close every live client pool for the running loop.

AppConfig

tai42_contract.app.facets.runtime.AppConfig
Access to the process config manager.

Members

config_manager

tai42_contract.app.facets.runtime.AppConfig.config_manager
The process config manager.

AppConnectors

tai42_contract.app.facets.integrations.AppConnectors
Registration and credential resolution for connector providers.

Members

register_connector

tai42_contract.app.facets.integrations.AppConnectors.register_connector
Register a connector provider from its pure descriptor data. Called for every manifest connectors entry at boot/reload, and by any code holding the handle (a connector is pure data, so this is a plain call, not a decorator). Parameters

token_store

tai42_contract.app.facets.integrations.AppConnectors.token_store
The connector token store (single-namespace, keyed by connection_id).

resolve_connection_auth

tai42_contract.app.facets.integrations.AppConnectors.resolve_connection_auth
Resolve the credential a connection injects, for the CURRENT caller. The facade accessor an in-process plugin uses to read a skeleton-resolved credential (OAuth token / static env / static headers) without importing the skeleton — refreshing an expired OAuth token under the connection lock. Async because resolution performs I/O (the OAuth refresh under the connection lock); callers await it. Returns None when the connection injects nothing. GUARANTEE (enforced by the skeleton implementation): (1) it RAISES a loud constant-message error when NO execution identity is bound — the fail-close raise fires as the awaited coroutine runs, BEFORE resolving, so an identity-less door never gets creds injected; and (2) connection_id is a REFERENCE supplied by operator settings, NEVER session-supplied, so a session can neither reach an identity-less door’s creds nor name another connection. The contract carries no logic — the skeleton owns the fail-close enforcement. Parameters

AppConversations

tai42_contract.app.facets.messaging.AppConversations
The conversation bridge’s entry surface for medium adapters. Inbound messages arrive via accept, out-of-band delivery receipts via record_delivery_status. Routing-row CRUD, the turn engine and the API door are not part of this facet.

Members

accept

tai42_contract.app.facets.messaging.AppConversations.accept
Accept one inbound channel message, persist it, and return its message_id (a uuid4). Routed to the door=channel route matching (channel, our_identity); the turn runs as that route’s execution key and answers back over the same channel. Idempotent on (channel, provider_message_id) — a redelivery returns the existing message_id and starts no second turn. Raises when no route matches. client_address is the conversation identity (its thread and transcript). cap_key is the party the per-address turn cap holds accountable, which the door composes: a provider channel passes its attested address (the two match), a door that mints its own visitor id passes a key the platform does NOT mint — its network client bucket — so the cap bounds spend the visitor cannot reset. Required and non-blank; a door that omits it is refused, never defaulted. params are optional entry parameters the door captured with the conversation entry, delivered verbatim to a tool target’s payload under params; None/empty leaves the payload unchanged. The door validates them with validate_entry_params before accept. params is ALSO the opaque-enrichment seam for the channel-specific inbound context that has no shared shape — a tapped reply/list id, a template button payload, a referral, the reply-to context of the message the participant quoted, a contact card or a reaction — which a channel adapter encodes as string entries a route reads deliberately; the platform adds no typed field for those. form is an optional structured participant submission (an ask-less form’s answers) riding WITH the required rendered text — the text stays the whole turn every consumer sees, while a tool target’s start_expr may map the structured copy from the payload’s form key (present only when the inbound carried one). The platform bounds it as pure transport (validate_inbound_form) and attaches no meaning and NO TRUST to the contents: participant-shaped data, never schema-conformant. attachments is the STRUCTURED media the participant sent WITH the message — the inbound counterpart of an outbound answer’s media — as MediaItem (image/document/video/audio; a channel resolves a sticker to image/video, a voice note to audio). location is a LocationElement the participant shared. Both are machine-consumable content with a shared cross-channel shape, so they are typed fields (not params): they land in a tool target’s payload under the stable attachments / location keys, present only when the inbound carried them, so a form-/media-unaware target still sees the whole turn as text. None leaves the payload unchanged. locale is the participant’s BCP 47 language tag the channel resolved from its native inbound (a per-message language hint), captured onto the turn’s subject so the rendering layer resolves every text template and list format against it — flows and state templates never select a language. It seeds a first-contact person’s stored locale and, absent a stored operator override, is the turn’s resolved locale; None means the channel supplied none (no silent default to any language). Parameters

record_delivery_status

tai42_contract.app.facets.messaging.AppConversations.record_delivery_status
Ingest a channel’s out-of-band delivery receipt for an outbound message. provider_message_id is one of the ids a prior notify returned, resolved to the answer record through the outbound-id reverse index. FAILED marks the record failed; DELIVERED confirms a provisional record. Raises when the id resolves to no record. Parameters

pending_messages

tai42_contract.app.facets.messaging.AppConversations.pending_messages
The thread’s participant messages accepted after after and not yet carried into a turn. The accepted records with origin="client" and inbound_kind="message" on thread_id whose acceptance follows the after message, in acceptance order, each a PendingMessage. Read-only and in-process (it reads the same thread index the turn engine batches over), bounded by the thread’s FIFO depth. A body running inside a turn asks this — with after the turn’s own lead message_id — to learn whether a newer message is waiting, so it can yield (raise TurnSupersededError) before an expensive or irreversible step. Outside a turn there is nothing pending by definition. An unknown thread_id reads as an empty list; a record already left accepted is not pending. Parameters

register_target_validator

tai42_contract.app.facets.messaging.AppConversations.register_target_validator
Register a bind validator for routes whose target is of target_kind. A plugin calls this through the tai42_app handle when its module loads. Route creation consults every registered validator for the route’s target kind AFTER the target exists but BEFORE the route is written; a validator returning any message lines refuses the creation with them (a 422), so a defect the target carries — a flow reading a state no binding supplies — is caught at bind, never deferred to run time. Registering two validators for one kind raises loudly. Parameters

AppExtensions

tai42_contract.app.facets.execution.AppExtensions
The tool-extension provider namespace (app.extensions).

Members

extension

tai42_contract.app.facets.execution.AppExtensions.extension
Register a tool-extension factory under name (default: the function’s own name). Usable bare or with arguments. requires_body_locality marks an extension whose wrapper only works in the process running the tool body it wraps — e.g. a proxy layer that routes the body’s egress through a task-scoped contextvar, visible only where the body executes. The flag is stored as registration metadata the apply site reads to order a stacked combo: a locality-requiring extension must bind INSIDE any execution-relocating extension (ExtensionKind.relocates_execution), so its wrapper travels with the body to the worker. Bound outside a relocating layer, the wrapper stays behind in the submitting process and silently does not apply. Parameters

available_extensions

tai42_contract.app.facets.execution.AppExtensions.available_extensions
List registered extension modules as [{"name", "kind"}].

AppHttp

tai42_contract.app.facets.routing.AppHttp
The HTTP application facet: middleware, route registration, and mount introspection.

Members

middleware

tai42_contract.app.facets.routing.AppHttp.middleware
Register a middleware on the application. Parameters

custom_route

tai42_contract.app.facets.routing.AppHttp.custom_route
Register a Starlette handler AND its self-describing route metadata. The metadata is the single source of truth the OpenAPI 3.1 emitter and its coverage gate consume, so every registration MUST describe itself:
  • summary — a one-line operation summary (required, non-empty).
  • tags — at least one OpenAPI tag grouping the route (required).
  • response_model — the pydantic model (any BaseModel, RootModel included) describing the success body. Required — there is no default, so a route cannot silently omit it. By default the model is wrapped in the {"data": ...} success envelope; a route that answers a RAW top-level body passes enveloped=False (see below). None is legal ONLY together with a non-blank no_body_reason: the two states are mutually exclusive — a route declares a typed body OR a reasoned no-body, never both and never neither.
  • enveloped — whether the JSON success body is wrapped in the {"data": <response_model>} envelope (the default, True) or is the model’s schema DIRECTLY at the top level (False, a raw non-enveloped body). enveloped=False REQUIRES a response_model: an unwrapped body still needs a real model, so a bare None under it is a registration error.
  • no_body_reason — the required-when-response_model is None justification for a route that serves no {"data": <model>} JSON body (a redirect, a raw/streaming/asset response, a vendor webhook 200, or a raw non-enveloped body the envelope emitter cannot describe). Passing it alongside a response_model, or omitting it when response_model is None, is a registration error.
  • request_model — the pydantic model of the request body; required for any route that reads a body, omitted (None) otherwise.
  • query_model — the pydantic model whose fields are published as in: query parameters for ANY method, additive to request_model. A read door’s request_model already emits as query, so this is the only way a WRITE-method door documents the query it reads at the edge; None (the default) publishes no query model.
  • authed — whether the route requires the api key; emitted as the security requirement. None (the default) defers to the runtime: a core route resolves to True, a declared plugin route to the negation of its tai-plugin.yml public flag. Passing an explicit bool from a declared plugin route module is a registration error — the declaration is the single source of that decision.
  • destructive — whether the route mutates in a way flagged as destructive (default False); emitted as x-destructive.
  • action — the route’s authorization character (a RouteAction); None (the default) lets the surface derive the grantable class from the HTTP methods.
  • declared — the route’s behavioral OpenAPI properties (a DeclaredRouteMetadata): its reload_gated / reads_body / error statuses / success status. A route in the /api/* spec surface declares these (the operations adapter passes its operation’s metadata, a native handler passes its own); None (the default) records trivial defaults for a route outside the spec surface, whose behavioral metadata is never emitted.
The handler’s narrative docstring becomes the operation description, and the reload-gate 503 response is derived from the handler body. Parameters

use_raw_path_key

tai42_contract.app.facets.routing.AppHttp.use_raw_path_key
Match already-registered routes under path_prefix against the raw (undecoded) request path. A path parameter whose values carry / (a state record’s {key}, addressed as one percent-encoded segment) stays ONE segment instead of splitting once the ASGI server has decoded %2F; the matched parameters are decoded once after the match. Called AFTER the routes are registered, over their shared prefix, so it covers a family of doors at one seam. A no-op where no route table is served (the offline spec harness). Parameters

mount_base

tai42_contract.app.facets.routing.AppHttp.mount_base
The resolved absolute mount base of the declared plugin route module importing now. /api/ + the item’s mount base, no trailing slash (e.g. /api/channels/telegram). Callable ONLY while a declared plugin route module imports — the mount binding is present then. A module captures this value at import for later use (a startup hook building an external webhook URL, a login descriptor’s self-referential path) so a remapped base is followed instead of a hardcoded default. Called with no binding present — a core or operator-authored module — it raises: those modules own no declared mount.

AppInteractions

tai42_contract.app.facets.messaging.AppInteractions
The interactions namespace (app.interactions) — the ask facade and answer check.

Members

check_answer

tai42_contract.app.facets.messaging.AppInteractions.check_answer
Validate answer against question — the ONE answer check every door reaches. question is a QuestionFormat (the answer format plus its payload — no stored request needed). Returns None when the answer conforms; raises AnswerMismatchError (carrying the failing field’s dotted path when the fault locates to one) otherwise. The answer door, the callback door, a resumed run’s visit and plugins all validate through this one callable so every surface applies identical rules per format. Parameters

assert_resume_authorized

tai42_contract.app.facets.messaging.AppInteractions.assert_resume_authorized
Authorise the caller to resume (or deliver an outcome for) interaction_id — or raise. A driver’s continuation face and cross-driver chain-delivery tool call this with the id they are about to resume/deliver-to, BEFORE producing any outcome, because those tools are dispatchable by name at the run-tool door and the MCP edge. Authorised only inside the platform’s own resume of that run: it passes iff the ambient run-authorization context names interaction_id directly (the resume origin) OR the interaction’s stored run delivery identity matches the ambient one (a cross-driver chain re-entry of the same run). Raises ParkResumeUnauthorizedError for an external caller (no origin) or an id belonging to another run — never a mere presence test. Parameters

assert_delivery_authorized

tai42_contract.app.facets.messaging.AppInteractions.assert_delivery_authorized
Authorise a door delivery-address tool to fire for completion_id — or raise. A door’s out-of-band delivery address is a registered tool the platform’s delivery ladder fires; the tool calls this at entry with the payload’s completion_id before delivering anything. It passes iff the ambient delivery-fire context is set AND equals completion_id — a None id and a call outside any fire never pass. Raises ParkDeliveryUnauthorizedError otherwise, so a caller naming the address tool directly at the run-tool door or the MCP edge delivers nothing. Parameters

redelivery_horizon_seconds

tai42_contract.app.facets.messaging.AppInteractions.redelivery_horizon_seconds
The platform’s redelivery retention horizon in seconds. The continuation-due record ages out at it and the reaper caps its redelivery backoff at it, so no resume redelivery fires past it. A resuming driver derives its own resolution-record retention from this value rather than a hard-coded guess.

visit

tai42_contract.app.facets.messaging.AppInteractions.visit
The bound, Visit-typed shared-visit callable. The ONE seam every door drives a parkable run through: it runs the cancel / resume / take / start order once for every caller (checks everything before doing anything, cancels, resumes or takes at most one action besides cancel, starts the target when nothing was resumed, normalises what came back), and returns a VisitOutcome. A door resolves its own jqs to plain values and hands them in; the generic list_parked / resume_parked / cancel_parked below are thin wrappers over this same seam.

park_answer

tai42_contract.app.facets.messaging.AppInteractions.park_answer
The ONE park-answer shape a direct door hands back for a VisitOutcome. A plain result is the tool’s own value; an asks outcome is the caller ask entries the run parked ({"asks": [entry, ...]}); a parked outcome is the suspended sentinel; none is None. Both the synchronous run-tool door and the background submit’s terminal record shape a park through this ONE callable, so a poller of either door reads identical bytes and can tell a caller-ask park (answerable through resume_parked) from a user-ask park. It never reveals a wrapped secret — the sync door reveals those on the result kind itself and every recorder masks its own copy. Parameters

normalise_started

tai42_contract.app.facets.messaging.AppInteractions.normalise_started
Classify a raw start return into a started VisitOutcome over the ambient subject. The same normalisation visit applies to what its start returned — caller asks, a re-park, or a final result — exposed for a door that already ran its start INSIDE its own visit (a hook fire whose visit owns the run) and only needs the return classified, so its record carries the same park answer both direct doors return. Parameters

list_parked

tai42_contract.app.facets.messaging.AppInteractions.list_parked
Every parked interaction on the current run’s subject — the full parked entries. Reads the ambient run’s subject candidates and returns the union over its subject keys, de-duplicated, each a ParkedEntry with its id, status (asking/running/finished/failed) and the question/answer fields a state-backed entry carries. The same rows a door-contract jq reads as $parked.

list_parked_for

tai42_contract.app.facets.messaging.AppInteractions.list_parked_for
Every parked interaction on context’s subject — the same entries as list_parked. A parkable-driving door fetches this over its OWN StateContext once and feeds the list to the door-contract evaluator as $parked, keeping the contract evaluation a pure function of an injected list rather than an ambient read. A None context has no subject and returns an empty list. Parameters

current_fire_identity

tai42_contract.app.facets.messaging.AppInteractions.current_fire_identity
The ambient execution identity as the (user_id, fingerprint) pair a fire forwards, or None. A background task tool dispatched from within a door fire forwards this pair onto its worker job so the deferred fire re-binds the SAME authority; None when no identity (or no per-mint fingerprint) is bound, so nothing is forwarded and the deferred fire fails closed on any credential seam rather than under a substituted principal.

bound_execution_identity_for_fire

tai42_contract.app.facets.messaging.AppInteractions.bound_execution_identity_for_fire
An async with binding execution_key’s live-grant identity for a receiver-less door fire. A scheduled fire has no live caller, so the door stores the firing identity (the execution key’s user_id and its per-mint fingerprint) at create and binds it here at fire, so a run that async-parks can rebind its continuation and a to="caller" resume acts under the same authority. Homed beside the door’s other kit-reachable seams so a backend plugin binds a scheduled fire’s identity without importing the skeleton. Raises when the key no longer carries authority — the fire fails closed, never under a substituted principal. Parameters

resume_parked

tai42_contract.app.facets.messaging.AppInteractions.resume_parked
Resume a parked caller ask with payload, or TAKE its waiting outcome when omitted. With payload given it resumes the asking caller ask interaction_id and returns the resumed run’s normalised outcome; with payload omitted it TAKES a finished entry’s waiting outcome (kind="result") or re-raises a failed one as ParkableRunFailedError. A live inline receiver, so the resumed run’s terminal is returned inline rather than delivered out of band. Parameters

cancel_parked

tai42_contract.app.facets.messaging.AppInteractions.cancel_parked
Whole-chain kill every parked interaction named in ids on the current run’s subject. Each id is torn down through the one teardown seam (its run and every run it linked above it close for good, delivering FAILED once to a door that started it); returns a VisitOutcome naming the ids cancelled. An id outside the run’s own parked list raises ParkedEntryGoneError with nothing cancelled. Parameters

ask

tai42_contract.app.facets.messaging.AppInteractions.ask
The bound, Ask-typed ask callable. An in-process plugin asks a human without importing the skeleton: await tai42_app.interactions.ask(question, ..., mode="async", expiry_at=...). The return shape is the Ask contract’s: mode="sync" returns the typed answer, mode="async" returns a SuspendedInteraction. Its full call signature is the Ask Protocol’s, including the per-ask on_mismatch digression policy and mismatch_notice retry text a channel-delivered ask carries. A facade EXPOSURE of the skeleton helper through the already-typed Protocol — no new ask semantics.

AppLifecycle

tai42_contract.app.facets.runtime.AppLifecycle
Startup, shutdown, reload, and post-swap lifecycle hook registration.

Members

on_startup

tai42_contract.app.facets.runtime.AppLifecycle.on_startup
Register func to run at process startup (usable as a decorator). Parameters

on_shutdown

tai42_contract.app.facets.runtime.AppLifecycle.on_shutdown
Register func to run at process shutdown (usable as a decorator). Parameters

on_reload

tai42_contract.app.facets.runtime.AppLifecycle.on_reload
Register a handler re-run after every in-place re-init (reload_config). For example, dynamic tool loaders that on_startup ran once. Parameters

on_post_swap

tai42_contract.app.facets.runtime.AppLifecycle.on_post_swap
Register an establisher for a loop-affine background loop (a periodic poll or sweep). Run on the real serving loop at boot and after every epoch swap — never on the throwaway build-thread loop the per-epoch handlers run on — so the loop it spawns attaches to the serving loop and retires with its generation. Parameters

on_fleet_op_applied

tai42_contract.app.facets.runtime.AppLifecycle.on_fleet_op_applied
Register a handler fired after any worker-bus op applies in this process. Also fired after the reconnect self-resync reload. Unlike its zero-arg siblings, the handler takes ONE argument — the op name — so it can act on some ops and skip others (a query op carries no state change to react to). Parameters

wait_until_ready

tai42_contract.app.facets.runtime.AppLifecycle.wait_until_ready
Block until this process’s first boot self-resync has completed. That is the point at which the tool registry is fully built and stable for the run. A backend runtime that forks a child (or otherwise consumes queued work) per job awaits this before its work loop accepts anything: the boot self-resync rebuilds the tool registry non-atomically, so a worker that dequeued and forked mid-rebuild would run the job against a half-built registry. The latch is one-way — it resolves once and stays resolved, so a later bus reconnect (which re-runs the self-resync while the app is already live) never un-readies the process.

AppMonitoring

tai42_contract.app.facets.runtime.AppMonitoring
Registration and access for the process monitoring backend.

Members

register_monitoring

tai42_contract.app.facets.runtime.AppMonitoring.register_monitoring
Register the monitoring backend builder, or return a decorator when builder is omitted. Parameters

active

tai42_contract.app.facets.runtime.AppMonitoring.active
The active monitoring backend (impl type behind the contract protocol).

AppPresets

tai42_contract.app.facets.authoring.AppPresets
The presets namespace (app.presets) — the typed view + the bind kernel. store is the PresetStore-typed view over app.versioning.store (kind="preset"). bind is the kernel BOTH tiers (ephemeral and versioned) build their live tool through, so its typed-schema behavior reaches both.

Members

bind

tai42_contract.app.facets.authoring.AppPresets.bind
Return a FastMCP tool transform of base_tool as a new named tool. Built in ONE Tool.from_tool call: each fixed_kwargs key is baked as a HIDDEN, FIXED constant (removed from the exposed schema; a caller that passes it is rejected — it cannot be overridden at runtime) while the REMAINING arguments keep the base tool’s real typed schema (names, types, descriptions). tags sets the transformed tool’s native tags. An output_schema (an object JSON Schema) is baked into an agent base’s response_format (forcing structured output) or advertised + validated on a plain tool base. bind is async because it must resolve the base Tool object (via app.tools.get_tool(base_tool)) to feed the transform. Parameters

create

tai42_contract.app.facets.authoring.AppPresets.create
Create a versioned preset in-process and return its record view. The in-process authoring seam beside the HTTP create door: it runs the same content path (name pre-checks, combo/schema/bind validation, input-schema support, the base tool’s write validator, store write THEN register, and the rebind fan-out) and returns the same record shape, so the two doors cannot drift. A body its base tool cannot accept, a colliding name, or an input_schema over a base tool with no registered support is a loud error that persists nothing. The caller-authorization tier fence is OFF — the registration-tier fence authorizes a request principal at the HTTP doors; an in-process caller authorizes its own callers and passes only the base tools it is entitled to author — while every content check stays on. Parameters

save_version

tai42_contract.app.facets.authoring.AppPresets.save_version
Save a new version of an existing preset in-process and return the version row. The in-process sibling of the HTTP save-version door, running the identical content path and returning the same shape. Omitted fields carry the active value forward (input_schema via the CARRY_FORWARD sentinel; output_schema only when output_schema_provided is True). A body that cannot bind is a loud error that commits nothing; the tier fence is OFF for the reason create states. Parameters

register_write_validator

tai42_contract.app.facets.authoring.AppPresets.register_write_validator
Register the write validator for base_tool (one per base tool; duplicate registration raises). A base-tool plugin calls this through the tai42_app handle when its tool module loads. The validator runs on every write that persists a body — create / save-version / rollback — and in the dry-run validate verdict, so a body its base tool cannot accept is a loud 400 that never persists. A base tool with no registered validator gets no extra check. Parameters

register_input_schema_support

tai42_contract.app.facets.authoring.AppPresets.register_input_schema_support
Declare that base_tool ACCEPTS a per-preset input schema (one per base tool; duplicate raises). A base-tool plugin calls this through the tai42_app handle when its tool module loads. A preset that sets an input_schema over a base tool with no registered support is a loud authoring error at the shared preset-authoring chokepoint, never a silently-ignored schema. Parameters

input_schema_support

tai42_contract.app.facets.authoring.AppPresets.input_schema_support
The input-schema support base_tool declared, or None if it declared none. When None, the base tool’s typed schema is fixed. Parameters

register_registration_tier

tai42_contract.app.facets.authoring.AppPresets.register_registration_tier
Declare the authz tier required to author a preset over base_tool (one per base tool). Governs create/save/rollback/rename; duplicate registration raises. Default authoring is the presets’ own write action; a base tool with no declaration keeps that default. A base tool declaring fenced requires the admin fence to author a preset over it. The shared preset-authoring chokepoint reads this and enforces it BEFORE any store write on every authoring door. Parameters

registration_tier

tai42_contract.app.facets.authoring.AppPresets.registration_tier
The authoring authz tier base_tool declared, or None if it declared none. When None, authoring keeps the presets’ default write action. Parameters

get_active_versioned_body

tai42_contract.app.facets.authoring.AppPresets.get_active_versioned_body
One preset’s active (version, body) read TOGETHER in one query. The version-aware sibling of store.get_active_body: it captures the active version pointer and the body it points at atomically, so a consumer that needs the version beside the body never risks a skewed second read across a concurrent activation. Raises PresetNotFoundError for an unknown preset. Parameters

used_by

tai42_contract.app.facets.authoring.AppPresets.used_by
The other presets whose active bodies compose preset name as a tool, sorted. Computed over the active preset population (a body’s composed tool names intersected with the population, self excluded), so it answers “which saved presets depend on this one” for a rename/delete dependents pass. Raises PresetNotFoundError for a name that is not a known preset. Parameters

register_seed

tai42_contract.app.facets.authoring.AppPresets.register_seed
Declare a default preset the platform seeds at import time. A plugin calls this through the tai42_app handle when its module loads. The declared seeds are applied by the startup/reload seed applier — created when absent, a preset already present left untouched. Declaring two seeds under the same name raises loudly — a silent overwrite could drop one plugin’s default under another’s. Parameters

store

tai42_contract.app.facets.authoring.AppPresets.store
The typed preset view over app.versioning.store (kind="preset").

AppSandboxes

tai42_contract.app.facets.execution.AppSandboxes
The sandbox-provider namespace (app.sandboxes).

Members

register_sandbox

tai42_contract.app.facets.execution.AppSandboxes.register_sandbox
Register the Sandbox provider (decorator form, returning the class unchanged). One provider backs the slot; a second registration is a conflict the runtime rejects loudly.

sandbox

tai42_contract.app.facets.execution.AppSandboxes.sandbox
The registered provider, or None — status/introspection ONLY. Never gate execution on this nullable read; acquire through require_sandbox, the every-door guarantee (a None property is how per-consumer checks drift).

require_sandbox

tai42_contract.app.facets.execution.AppSandboxes.require_sandbox
Return the registered provider from the ONE raising acquisition chokepoint. Raise SandboxUnavailableError (naming TAI_MCP_SANDBOX and sandbox_module) when none is registered. EVERY consumer acquires through here.

sandbox_policy

tai42_contract.app.facets.execution.AppSandboxes.sandbox_policy
Return the skeleton-resolved SandboxPolicy. This is the plugin-reachable READ of the SAME policy the skeleton binds to the kit at the session-create chokepoint. Available REGARDLESS of whether a provider is registered (it reads operator config, not a provider). Mirrors the ask / resolve_connection_auth facade accessors that let an in-process plugin read a skeleton-resolved value without importing the skeleton; a consumer building a policied spec reads the network default and scrub_transcript here. Implemented in the skeleton, which resolves the policy once and returns the SAME value it binds to the kit.

AppStates

tai42_contract.app.facets.states.AppStates
The subject-keyed state store namespace (app.states). The door-agnostic contract every door and tool reads and writes a subject’s document through. The store takes a full StateSubject and refuses anything less; subject resolution happens once per door, never here. Every write door supplies a WriteOrigin carrying only what a consumer knows — the platform completes it (door/actor/turn_id) at this chokepoint, so the audit ledger is never optional or forgeable. While the states component’s database is unbound every method raises StatesNotConfiguredError (501), never an empty read.

Members

list_declarations

tai42_contract.app.facets.states.AppStates.list_declarations
Every declared state.

get_declaration

tai42_contract.app.facets.states.AppStates.get_declaration
The declaration named name, or None when none is declared. Parameters

put_declaration

tai42_contract.app.facets.states.AppStates.put_declaration
Declare or re-declare a state and return the stored declaration. An additive re-declare (new optional fields, new subject kinds) is applied in place; a change that would remove or narrow a field while records exist raises NonAdditiveRedeclareError (erase the records first), and removing a subject kind still present in records raises DeclarationInUseError. Never a silent overwrite. Parameters

delete_declaration

tai42_contract.app.facets.states.AppStates.delete_declaration
Delete a state with its records and attachments. Raises DeclarationInUseError when a consumer still binds it. Parameters

stats

tai42_contract.app.facets.states.AppStates.stats
Counts for a state — records, subjects by kind, consumers — for the listing. Parameters

list_templates

tai42_contract.app.facets.states.AppStates.list_templates
Every stored platform template document.

get_template

tai42_contract.app.facets.states.AppStates.get_template
The template document named name, or None when none is stored. The read a consumer’s own sibling document validates against. Parameters

put_template

tai42_contract.app.facets.states.AppStates.put_template
Store a template document and return it (replace required to overwrite an existing name). Runs every registered attach validator over each live attachment before the write, so a consumer’s data-dependent check still fires here; a raise leaves the stored document untouched. Overwriting an existing name without replace raises TemplateExistsError. Parameters

delete_template

tai42_contract.app.facets.states.AppStates.delete_template
Delete a template document. Raises TemplateInUseError while it is still attached. Parameters

list_attachments

tai42_contract.app.facets.states.AppStates.list_attachments
Attachment rows filtered by state, by template, or every attachment when both are None. What the attachments listing and the Consumers tab read. Each row carries state, template, path, parameters and declarations. Parameters

attach

tai42_contract.app.facets.states.AppStates.attach
Attach template on state at body.path, recomposing the effective schema in one transaction. Stores the resolved parameters and declarations. Runs every registered attach validator before the write; a raise refuses the door with the validator’s message. Overlapping fragments raise AttachConflictError. Parameters

update_attachment_declarations

tai42_contract.app.facets.states.AppStates.update_attachment_declarations
Replace an attachment’s declaration values, recomposing the effective schema before the write. Re-runs every registered attach validator and reconciler before the write. options is a per-operation directive bag passed to the reconcilers for THIS operation only, never stored or served back (None is an empty bag). Parameters

detach

tai42_contract.app.facets.states.AppStates.detach
Remove an attachment and recompose the state’s effective schema. Parameters

read

tai42_contract.app.facets.states.AppStates.read
The record for subject (resolving a fold to its canonical subject), or None when none exists. An unknown person or a target mismatch is a refusal, never an empty document. Parameters

replace

tai42_contract.app.facets.states.AppStates.replace
Replace subject’s whole document with data and return the new record. Parameters

merge

tai42_contract.app.facets.states.AppStates.merge
Shallow top-level merge patch into subject’s document and return the new record. Parameters

apply

tai42_contract.app.facets.states.AppStates.apply
Apply an op batch to subject’s document under the effective schema. Refuses a whole-path write over a composing path (RegimeViolationError) before the ledger insert, stamps _trace under a traced attachment, and records one state_writes row with the touched paths and the completed origin. A replayed op_id returns applied=False without re-writing; guarded ops land in skipped. Parameters

eval_template_jq

tai42_contract.app.facets.states.AppStates.eval_template_jq
Evaluate an input-purpose template_jq program name for subject and return its value. The program’s jq runs over the subject’s record, params supplying its declared parameters. name resolves across the state’s attached templates (unqualified → the declaring template; <attachment>.<name> → that attachment’s template). An unknown name is a StateNotFoundError; an ambiguous unqualified name, an update-purpose name, an undeclared param or an evaluation failure is a ValueValidationError. A read; no write is recorded. Parameters

apply_template_jq

tai42_contract.app.facets.states.AppStates.apply_template_jq
Apply an update-purpose template_jq program name to subject. Its jq maps the record subtree (its .) with $input bound to a template-relative op batch, rebased under the attachment path and applied through the same chokepoint as apply — so regimes, the composing-shape guard, trace stamping and op_id idempotency all hold. name resolves as for eval_template_jq. An unknown name is a StateNotFoundError; an ambiguous unqualified name, an input-purpose name, an evaluation failure or a wrong-shaped return is a ValueValidationError. Parameters

erase

tai42_contract.app.facets.states.AppStates.erase
Erase subject’s record, recording the write. Parameters

fold

tai42_contract.app.facets.states.AppStates.fold
Fold subject into into and return the resulting canonical document. mode decides how the documents combine. A self-fold, a cycle, a conflicting re-fold, or a merge whose result fails the schema raises SubjectFoldError; a retried fold to the same target is a quiet no-op. Parameters

list_subjects

tai42_contract.app.facets.states.AppStates.list_subjects
A keyset page of subjects for state (optionally one kind). {"subjects": [...], "next_cursor": <cursor|None>}. Parameters tai42_contract.app.facets.states.AppStates.search
A keyset page of records whose document contains filters. {"matches": [...], "next_cursor": <cursor|None>}. Parameters

writes

tai42_contract.app.facets.states.AppStates.writes
One keyset page of the audit trail for subject, newest first. The items (each a write with its completed origin and touched paths) plus the next_cursor that pages the trail like list_subjects/search page theirs (the last row’s id when the page is full, else None). Parameters

prune_expired

tai42_contract.app.facets.states.AppStates.prune_expired
Delete records past their state’s retention_days and return the per-state deletion counts.

context

tai42_contract.app.facets.states.AppStates.context
The ambient StateContext the current door deposited. None outside a door (an api write completes from the request principal instead).

register_consumer_lister

tai42_contract.app.facets.states.AppStates.register_consumer_lister
Register a lister for consumer kind (flow / hook / schedule / agent). A plugin calls this through the tai42_app handle when its module loads; consumers unions every registered lister. Registering two listers for one kind raises loudly. Parameters

consumers

tai42_contract.app.facets.states.AppStates.consumers
Everything that binds state — the union of every registered consumer lister — for the Consumers tab. Parameters

register_template_seed

tai42_contract.app.facets.states.AppStates.register_template_seed
Declare a platform template document the platform seeds at import time. A plugin calls this through the tai42_app handle when its module loads. The startup/reload seed applier creates it when absent and leaves a template already present untouched. Declaring two seeds under one name raises loudly. Parameters

register_attach_validator

tai42_contract.app.facets.states.AppStates.register_attach_validator
Register a data-dependent attach validator. A plugin calls this through the tai42_app handle when its module loads. The validator receives the template document, an attachment’s declaration values, and the state’s effective schema, and RAISES to refuse; it runs before every attach, update_attachment_declarations and put_template(replace=True) write, so a consumer’s checks fire at the platform’s declarations doors, the States page included. Parameters

register_attach_reconciler

tai42_contract.app.facets.states.AppStates.register_attach_reconciler
Register a pre-write attach reconciler. A plugin calls this through the tai42_app handle when its module loads. The reconciler receives a AttachReconcileContext — the template, the operation, the previous and new declarations, the attach options, and a record door bound to the state — inside every attach and update_attachment_declarations write, after the validators and before the write. It RAISES to refuse the attach (naming the records the new declarations orphan) or writes resolutions through the context’s record door and returns, letting the attach commit with those writes. Parameters

AppStorage

tai42_contract.app.facets.execution.AppStorage
The storage-provider namespace (app.storage).

Members

register_storage

tai42_contract.app.facets.execution.AppStorage.register_storage
Register the Storage provider; usable bare or as a decorator factory.

resource_manager

tai42_contract.app.facets.execution.AppStorage.resource_manager
The active resource manager (impl type; loads/renders content over storage).

AppSubApp

tai42_contract.app.facets.runtime.AppSubApp
Access to the sub-app MCP router.

Members

mcp_sub_app_router

tai42_contract.app.facets.runtime.AppSubApp.mcp_sub_app_router
The router for mounted sub-app MCP servers.

AppToolMeta

tai42_contract.app.facets.authoring.AppToolMeta
The tool-metadata namespace (app.tool_meta) — the organizational overlay over any live tool. The overlay is a folder tree plus a per-tool row (display name, folder placement, tags, badges, a hidden override). store is the ToolMetaStore view the routes and the preset lifecycle cascade read and write. patch is the in-process edit seam beside the HTTP PATCH door.

Members

store

tai42_contract.app.facets.authoring.AppToolMeta.store
The tool-metadata overlay store the routes and preset cascade read and write.

patch

tai42_contract.app.facets.authoring.AppToolMeta.patch
Patch a tool’s overlay row in-process and return its record. The in-process sibling of the HTTP PATCH door, running the same operation so validation is identical (an unknown folder_id is a loud error). Only the arguments given are written: folder_id places the tool, and a tags list REPLACES the whole tag set (array values are set replacements, not merges). tags=None leaves the tag set untouched; folder_id=None leaves the placement untouched. Parameters

AppTools

tai42_contract.tools.AppTools
Tool + toolkit registration / lookup surface.

Members

tool_title

tai42_contract.tools.AppTools.tool_title
Return the human-facing title of the tool implemented by func. Parameters

get_tool

tai42_contract.tools.AppTools.get_tool
Return the assembled tool registered under key. Parameters

get_tools

tai42_contract.tools.AppTools.get_tools
Return every assembled tool keyed by name.

get_client_tools

tai42_contract.tools.AppTools.get_client_tools
Return the client-facing tool objects, restricted to names when given. Parameters

run_tool

tai42_contract.tools.AppTools.run_tool
Execute the tool registered under key with arguments and return its result. offload_sync runs a synchronous tool body off the event loop in a worker thread. continues_chain is an in-process seam keyword ONLY (no request model, MCP argument, or tool argument sets it): when given, the dispatch’s call frame SETS the ambient call chain to it rather than pushing key, so a continuation runner restores a parked run’s chain on the one dispatch that resumes it. extras is likewise an in-process seam keyword ONLY (no request model, MCP argument, or tool argument sets it): the mapping a door carries into the run it starts. It is set on the dispatch’s call frame — ambient and read-only for THAT frame, so the started tool reads it through extras and every nested frame starts empty. A visit checks the keys against the target’s declaration before the run; None binds an empty mapping. Parameters

extras

tai42_contract.tools.AppTools.extras
The ambient door extras mapping the current run was started with (empty when none). A door carries author-configured extras into a run; a tool reads the keys it declared (@app.tools.tool(extras_keys=...)) here. The mapping is read-only and scoped to the started target’s own frame — every nested dispatch reads an empty mapping, so nothing leaks down. No request model, MCP argument, or tool argument can set it.

declared_extras

tai42_contract.tools.AppTools.declared_extras
The door extras keys tool name is declared to read (empty when it declares none). A preset inherits its base tool’s declared keys. The visit checks a door’s extras against this set before starting the target and refuses an undeclared key. Parameters

remove_tool

tai42_contract.tools.AppTools.remove_tool
Remove the tool registered under name. Parameters

register_tool_info

tai42_contract.tools.AppTools.register_tool_info
Register base tool name’s extension combos, attaching each combo stack to the base. Parameters

unregister_tool_info

tai42_contract.tools.AppTools.unregister_tool_info
Drop the registered tool-info for name. Parameters

unregister_tool_base

tai42_contract.tools.AppTools.unregister_tool_base
Unregister base tool tool_name and return the names removed. Parameters

tool_refs_extractor

tai42_contract.tools.AppTools.tool_refs_extractor
Return the tool-references extractor base tool name registered, or None when it declared none. Parameters

register_rename_referee

tai42_contract.tools.AppTools.register_rename_referee
Register a ToolRenameReferee consulted before a tool rename. A plugin holding tool-name references calls this through the tai42_app handle when its module loads. Every registered referee is asked for the old name on a rename; any non-empty answer blocks the rename and its descriptions name the holders. Registering the same provider object twice raises loudly — a double registration is a plugin bug, never a silent duplicate consult. Parameters

register_delete_referee

tai42_contract.tools.AppTools.register_delete_referee
Register a ToolDeleteReferee consulted before a preset delete. A plugin holding resources keyed on a preset/tool name (e.g. per-node state bindings that reference a preset) calls this through the tai42_app handle when its module loads. Every registered referee is asked for the name on a delete; a referee cascades its own cleanup and returns empty to allow, or returns non-empty descriptions to VETO — any non-empty answer blocks the delete and names the holders. Registering the same provider object twice raises loudly — a double registration is a plugin bug, never a silent duplicate consult. Parameters

register_detach_referee

tai42_contract.tools.AppTools.register_detach_referee
Register a StateTemplateDetachReferee consulted before a state-template detach. A holder of door bindings that name templates (e.g. per-node state bindings, or the platform’s own preset/route/hook/schedule bindings) calls this through the tai42_app handle when its module loads. Every registered referee is asked for the (state, template) on a detach; any non-empty answer blocks the detach and its descriptions name the referencing bindings. Registering the same provider object twice raises loudly — a double registration is a bug, never a silent duplicate consult. Parameters

register_tier

tai42_contract.tools.AppTools.register_tier
Declare base_tool’s registration tier (a RouteAction). The authorization character enforced everywhere the tier is consulted. A fenced or secret tier gates BOTH authoring a preset over the base tool (admin-only) AND running the tool: a fenced/secret tool runs only for an administrator, at every execution door, and a preset authored over it inherits that fence at run time. read/write carry no execution gate. This is the programmatic form of @app.tools.tool(tier=...); both write the one shared registry (also read on the authoring side as app.presets.registration_tier). One declaration per base tool; a duplicate raises loudly. Parameters

tier

tai42_contract.tools.AppTools.tier
The registration tier base_tool declared, or None when it declared none. None means no execution fence; authoring keeps the presets’ default write action. Parameters

AppVersioning

tai42_contract.app.facets.authoring.AppVersioning
The generic versioned-document store namespace (app.versioning). This is the platform persistence primitive — append-only versions + an active pointer + rollback over an opaque JSONB body, discriminated by kind. Direct consumers (e.g. AC policies under kind="ac_policy") reach it here; presets reach it through AppPresets, never as a new kind.

Members

store

tai42_contract.app.facets.authoring.AppVersioning.store
The append-only versioned-document store backing this namespace.

AppWebhookVerifiers

tai42_contract.app.facets.messaging.AppWebhookVerifiers
The webhook-verifier registry namespace (app.webhook_verifiers).

Members

register

tai42_contract.app.facets.messaging.AppWebhookVerifiers.register
Register a WebhookVerifier under name. A provider plugin calls this through the tai42_app handle when its import-only webhook_verifier_modules entry loads. Registering a name already taken raises loudly — a silent overwrite could swap a topic’s verifier out from under a live binding. Parameters

get

tai42_contract.app.facets.messaging.AppWebhookVerifiers.get
Fetch a registered verifier by name; raise loudly on an unknown name. Resolution happens when a verifier is bound to a public webhook door, so an unknown name surfaces at bind time as a loud failure, never a silently-unverified door. Parameters

DeclaredRouteMetadata

tai42_contract.app.facets.routing.DeclaredRouteMetadata
The behavioral OpenAPI properties a route DECLARES. A route registered through the operations adapter supplies this from its operation’s metadata + declared error classes; a native /api/* handler passes it explicitly at its custom_route registration. Its reload_gated / reads_body / error statuses / success status feed the emitted spec and the coverage/parity gates. additional_success_statuses names further 2xx codes one method may answer besides success_status; each is emitted as its own success response. Attributes

PendingMessage

tai42_contract.app.facets.messaging.PendingMessage
One participant message accepted on a thread but not yet carried into a turn. The projection AppConversations.pending_messages returns, so a body running inside a turn can learn a newer message is waiting and stop before an irreversible step. message_id is the accepted record’s id, text its verbatim inbound text, accepted_at the epoch seconds it was accepted at (the thread index’s own score). Frozen. Attributes

RouteAction

tai42_contract.app.facets.routing.RouteAction

TaiApp

tai42_contract.app.TaiApp
The assembled facade — per-feature sub-protocols exposed as namespaces.

Members

tools

tai42_contract.app.TaiApp.tools
Tool and toolkit registration and lookup.

agents

tai42_contract.app.TaiApp.agents
Agent registration and access.

backends

tai42_contract.app.TaiApp.backends
Task backend registration and access.

sandboxes

tai42_contract.app.TaiApp.sandboxes
Sandbox-provider registration and access.

storage

tai42_contract.app.TaiApp.storage
Storage-provider registration and access.

connectors

tai42_contract.app.TaiApp.connectors
Connector-provider registration and credential resolution.

accounts

tai42_contract.app.TaiApp.accounts
Read access to the current epoch’s live identity/accounts providers.

webhook_verifiers

tai42_contract.app.TaiApp.webhook_verifiers
Inbound webhook verifier registration and lookup.

channels

tai42_contract.app.TaiApp.channels
Channel registration and lookup.

conversations

tai42_contract.app.TaiApp.conversations
Inbound-message and delivery-status entry surface for medium adapters.

monitoring

tai42_contract.app.TaiApp.monitoring
Monitoring backend registration and access.

extensions

tai42_contract.app.TaiApp.extensions
Tool-extension factory registration and lookup.

interactions

tai42_contract.app.TaiApp.interactions
The ask interactions facade.

http

tai42_contract.app.TaiApp.http
HTTP middleware, route registration, and mount introspection.

clients

tai42_contract.app.TaiApp.clients
Pooled async client lifecycle for the process.

lifecycle

tai42_contract.app.TaiApp.lifecycle
Startup, shutdown, reload, and post-swap lifecycle hook registration.

admin

tai42_contract.app.TaiApp.admin
In-process admin operations (binding, tool reload, config reload).

config

tai42_contract.app.TaiApp.config
Access to the process config manager.

backup

tai42_contract.app.TaiApp.backup
Named backup-section registration and export/import.

sub_app

tai42_contract.app.TaiApp.sub_app
Access to the sub-app router.

versioning

tai42_contract.app.TaiApp.versioning
The generic versioned-document store.

presets

tai42_contract.app.TaiApp.presets
The presets namespace (typed view plus bind kernel).

tool_meta

tai42_contract.app.TaiApp.tool_meta
The tool-metadata overlay over any live tool.

states

tai42_contract.app.TaiApp.states
The subject-keyed state store.

tai42_app

tai42_contract.app.tai42_app

AppAccounts

tai42_contract.app.facets.integrations.AppAccounts
Read access to the CURRENT epoch’s live identity/accounts provider instances. An accounts-provider plugin ships login routes that need the SAME provider instance the epoch built and probed (its resolved config, cached discovery/JWKS, injected settings). Rather than a module-level holder — which a failed epoch build would leave pointing at a half-built generation — the plugin’s routes resolve the live instance here. The contract exposes only this read; the runtime forwards it to the current epoch, so the contract never learns about epochs.

Members

active_provider

tai42_contract.app.facets.integrations.AppAccounts.active_provider
The provider the CURRENT epoch instantiated under name, or None when none is active. An AccountsProvider is an IdentityProvider. None means no provider is active under that name — the name is not configured, or a build is mid-flight. Parameters

AppAdmin

tai42_contract.app.facets.runtime.AppAdmin
In-process admin operations: MCP binding, tool reload, config reload.

Members

reload_mcp

tai42_contract.app.facets.runtime.AppAdmin.reload_mcp
Rebind the MCP server titled title and return its status. Parameters

deregister_mcp

tai42_contract.app.facets.runtime.AppAdmin.deregister_mcp
Remove the MCP server titled title and return its status. Parameters

reload_config

tai42_contract.app.facets.runtime.AppAdmin.reload_config
Re-init the process config in place and return the reload report.

tool_reloader

tai42_contract.app.facets.runtime.AppAdmin.tool_reloader
Register an async (action, name) -> dict reloader for kind. Parameters

run_tool_reload

tai42_contract.app.facets.runtime.AppAdmin.run_tool_reload
Run the registered kind reloader for action on name. Parameters

reload_failed_mcps

tai42_contract.app.facets.runtime.AppAdmin.reload_failed_mcps
Retry every MCP that failed to bind and return their statuses.

list_failed_mcps

tai42_contract.app.facets.runtime.AppAdmin.list_failed_mcps
List the MCPs that failed to bind.

live_mcp_status

tai42_contract.app.facets.runtime.AppAdmin.live_mcp_status
Snapshot the in-process MCP-binding state.

live_manifest

tai42_contract.app.facets.runtime.AppAdmin.live_manifest
The manifest currently live in this process.

AppAgents

tai42_contract.app.facets.execution.AppAgents
The agent-provider namespace (app.agents).

Members

agent

tai42_contract.app.facets.execution.AppAgents.agent
Register an Agent subclass under name and auto-register its JSON run tool. tags are the run tool’s native tags, set on its constructed tool object. meta is generic registration metadata threaded onto the same constructed run-tool object (naming no consumer concept — a registrant attaches any generic tai42/* key, e.g. a crash-resume flag the run-dispatch seam reads). The decorator returns the class unchanged, so the decorated symbol keeps its concrete subclass type. Parameters

get_agent

tai42_contract.app.facets.execution.AppAgents.get_agent
Fetch a registered agent instance by name; raise if missing. Parameters

all_agents

tai42_contract.app.facets.execution.AppAgents.all_agents
Return every registered agent keyed by registration name. The result is a shallow copy, so a caller iterating it cannot mutate the live registry. The preset bind kernel reads the keys to detect an agent base (the run tool binds under the registration name).

AppBackends

tai42_contract.app.facets.execution.AppBackends
The backend-provider namespace (app.backends).

Members

register_backend

tai42_contract.app.facets.execution.AppBackends.register_backend
Register the Backend provider; usable bare or as a decorator factory.

backend

tai42_contract.app.facets.execution.AppBackends.backend
The registered backend provider, or None when none is registered.

AppBackup

tai42_contract.app.facets.runtime.AppBackup
Registry for named backup sections and the run of one section’s export/import. A plugin (or the host itself, the first consumer) registers a section under name by supplying an exporter() that returns a JSON-safe payload and an importer(payload) that applies it and returns a section report. sections() lists the registered sections for the UI. export_section / import_section run one section’s exporter/importer by name and raise loudly on an unknown name — never a silent no-op.

Members

register_section

tai42_contract.app.facets.runtime.AppBackup.register_section
Register a backup section’s exporter/importer under name. Parameters

sections

tai42_contract.app.facets.runtime.AppBackup.sections
List the registered backup sections.

export_section

tai42_contract.app.facets.runtime.AppBackup.export_section
Run one section’s exporter by name and return its payload. Parameters

import_section

tai42_contract.app.facets.runtime.AppBackup.import_section
Apply payload via one section’s importer by name and return its report. Parameters

AppChannels

tai42_contract.app.facets.messaging.AppChannels
The channel registry namespace (app.channels) and inbound-answer ladder.

Members

register

tai42_contract.app.facets.messaging.AppChannels.register
Register a Channel under name. A channel plugin calls this through the tai42_app handle when its import-only channel_modules entry loads. Registering a name already taken raises loudly — a silent overwrite could swap the medium a live ask is delivered on. Parameters

get

tai42_contract.app.facets.messaging.AppChannels.get
Fetch a registered channel by name; raise loudly on an unknown name. Resolution happens when ask is called with channel=name, BEFORE any interaction state is written, so an unknown name surfaces as a loud failure, never a question silently delivered nowhere. Parameters

names

tai42_contract.app.facets.messaging.AppChannels.names
Every registered channel name, for the channels catalog route.

handle_inbound_answer

tai42_contract.app.facets.messaging.AppChannels.handle_inbound_answer
Resolve one inbound participant reply against its pending ask. This is the ONE shared inbound-answer ladder every correlated channel calls instead of hand-rolling its own “forward → interpret 2xx/404/400 → release/bridge/keep” sequence. Returns an InboundAnswerResult: the outcome the channel maps to its transport ack, plus the door’s retry_reason/retry_field when it rejected the answer’s content, so a channel that owns its correction surface can render the door’s specific message. A channel computes its own opaque correlation_key for the participant’s address, provides the answer value to forward to the door, its CorrelationStore, and an InboundBridge of the fields a bridged turn needs. SEAM SYMMETRY (bridge.params ↔ answer params): the InboundBridge may carry opaque channel enrichment in params — the answer-path counterpart of a conversation entry’s params. The ladder threads it BOTH ways so enrichment is never dropped on either arm: the answer is forwarded to the ask’s callback door as {"answer": answer, "params": params} (params present only when set), landing on params for the asking flow to read beside answer; and on the BRIDGE arm the same params are passed to accept as its entry params. The ladder:
  • No pending ask on the key -> InboundAnswerOutcome.NO_CORRELATION with NO side effect: the CALLER bridges the reply as a normal turn (the ladder never bridges on a miss, exactly as each channel did by hand).
  • The door accepts (2xx) -> release the correlation, return InboundAnswerOutcome.FORWARDED.
  • The door returns 404 (the ask was withdrawn/expired/cancelled) -> release, bridge the reply as a fresh turn, return InboundAnswerOutcome.BRIDGED.
  • The door returns 400 on a LIVE ask -> read the door’s retry_in_place (default True): True keeps the correlation, notifies the participant what’s expected, fires ONE operator event, returns InboundAnswerOutcome.RETRY_KEPT; False (a hard mismatch) releases, notifies the participant the question is closed, fires the event, bridges the reply, returns InboundAnswerOutcome.BRIDGED.
  • Anything else (401/413/5xx, or a transport fault) -> do NOT release; raise AnswerForwardError so the channel’s webhook redelivery re-runs the ladder. The answer is never silently lost.
The callback host is pinned to the platform’s configured public base before the forward; a stored callback whose host does not match is released and treated as InboundAnswerOutcome.NO_CORRELATION. Parameters

record_send_receipt

tai42_contract.app.facets.messaging.AppChannels.record_send_receipt
Post an out-of-band delivery receipt for a notify_user send back onto its originating trace. The send is a notify_user channel send with no conversation record. The tier-2 counterpart to the conversation bridge’s record_delivery_status: a channel’s delivery-status webhook calls this when the bridge does not own the outbound id (record_delivery_status raised LookupError). It resolves the id through the TTL’d send-receipt index and, on a hit, emits a delivery_receipt event into the recorded trace (a FAILED receipt at ERROR level), so the originating trace shows delivered-vs-accepted for its sends. errors carries any provider error detail for the event input. Returns True when the id was a known send (event emitted), False when it is not — so the webhook keeps its genuinely-unknown-id log only on a False. A no-op returning False where the send-receipt store is unconfigured. Parameters

AppClients

tai42_contract.app.facets.runtime.AppClients
Pooled async client lifecycle for the process.

Members

client_ctx

tai42_contract.app.facets.runtime.AppClients.client_ctx
Yield a connected client as an async context manager. Pooled per loop + connection params, or one-shot when fresh=True. settings is a kit ClientSettings whose client_kwargs() supplies the connection key. Parameters

shutdown_clients

tai42_contract.app.facets.runtime.AppClients.shutdown_clients
Close every live client pool for the running loop.

AppConfig

tai42_contract.app.facets.runtime.AppConfig
Access to the process config manager.

Members

config_manager

tai42_contract.app.facets.runtime.AppConfig.config_manager
The process config manager.

AppConnectors

tai42_contract.app.facets.integrations.AppConnectors
Registration and credential resolution for connector providers.

Members

register_connector

tai42_contract.app.facets.integrations.AppConnectors.register_connector
Register a connector provider from its pure descriptor data. Called for every manifest connectors entry at boot/reload, and by any code holding the handle (a connector is pure data, so this is a plain call, not a decorator). Parameters

token_store

tai42_contract.app.facets.integrations.AppConnectors.token_store
The connector token store (single-namespace, keyed by connection_id).

resolve_connection_auth

tai42_contract.app.facets.integrations.AppConnectors.resolve_connection_auth
Resolve the credential a connection injects, for the CURRENT caller. The facade accessor an in-process plugin uses to read a skeleton-resolved credential (OAuth token / static env / static headers) without importing the skeleton — refreshing an expired OAuth token under the connection lock. Async because resolution performs I/O (the OAuth refresh under the connection lock); callers await it. Returns None when the connection injects nothing. GUARANTEE (enforced by the skeleton implementation): (1) it RAISES a loud constant-message error when NO execution identity is bound — the fail-close raise fires as the awaited coroutine runs, BEFORE resolving, so an identity-less door never gets creds injected; and (2) connection_id is a REFERENCE supplied by operator settings, NEVER session-supplied, so a session can neither reach an identity-less door’s creds nor name another connection. The contract carries no logic — the skeleton owns the fail-close enforcement. Parameters

AppConversations

tai42_contract.app.facets.messaging.AppConversations
The conversation bridge’s entry surface for medium adapters. Inbound messages arrive via accept, out-of-band delivery receipts via record_delivery_status. Routing-row CRUD, the turn engine and the API door are not part of this facet.

Members

accept

tai42_contract.app.facets.messaging.AppConversations.accept
Accept one inbound channel message, persist it, and return its message_id (a uuid4). Routed to the door=channel route matching (channel, our_identity); the turn runs as that route’s execution key and answers back over the same channel. Idempotent on (channel, provider_message_id) — a redelivery returns the existing message_id and starts no second turn. Raises when no route matches. client_address is the conversation identity (its thread and transcript). cap_key is the party the per-address turn cap holds accountable, which the door composes: a provider channel passes its attested address (the two match), a door that mints its own visitor id passes a key the platform does NOT mint — its network client bucket — so the cap bounds spend the visitor cannot reset. Required and non-blank; a door that omits it is refused, never defaulted. params are optional entry parameters the door captured with the conversation entry, delivered verbatim to a tool target’s payload under params; None/empty leaves the payload unchanged. The door validates them with validate_entry_params before accept. params is ALSO the opaque-enrichment seam for the channel-specific inbound context that has no shared shape — a tapped reply/list id, a template button payload, a referral, the reply-to context of the message the participant quoted, a contact card or a reaction — which a channel adapter encodes as string entries a route reads deliberately; the platform adds no typed field for those. form is an optional structured participant submission (an ask-less form’s answers) riding WITH the required rendered text — the text stays the whole turn every consumer sees, while a tool target’s start_expr may map the structured copy from the payload’s form key (present only when the inbound carried one). The platform bounds it as pure transport (validate_inbound_form) and attaches no meaning and NO TRUST to the contents: participant-shaped data, never schema-conformant. attachments is the STRUCTURED media the participant sent WITH the message — the inbound counterpart of an outbound answer’s media — as MediaItem (image/document/video/audio; a channel resolves a sticker to image/video, a voice note to audio). location is a LocationElement the participant shared. Both are machine-consumable content with a shared cross-channel shape, so they are typed fields (not params): they land in a tool target’s payload under the stable attachments / location keys, present only when the inbound carried them, so a form-/media-unaware target still sees the whole turn as text. None leaves the payload unchanged. locale is the participant’s BCP 47 language tag the channel resolved from its native inbound (a per-message language hint), captured onto the turn’s subject so the rendering layer resolves every text template and list format against it — flows and state templates never select a language. It seeds a first-contact person’s stored locale and, absent a stored operator override, is the turn’s resolved locale; None means the channel supplied none (no silent default to any language). Parameters

record_delivery_status

tai42_contract.app.facets.messaging.AppConversations.record_delivery_status
Ingest a channel’s out-of-band delivery receipt for an outbound message. provider_message_id is one of the ids a prior notify returned, resolved to the answer record through the outbound-id reverse index. FAILED marks the record failed; DELIVERED confirms a provisional record. Raises when the id resolves to no record. Parameters

pending_messages

tai42_contract.app.facets.messaging.AppConversations.pending_messages
The thread’s participant messages accepted after after and not yet carried into a turn. The accepted records with origin="client" and inbound_kind="message" on thread_id whose acceptance follows the after message, in acceptance order, each a PendingMessage. Read-only and in-process (it reads the same thread index the turn engine batches over), bounded by the thread’s FIFO depth. A body running inside a turn asks this — with after the turn’s own lead message_id — to learn whether a newer message is waiting, so it can yield (raise TurnSupersededError) before an expensive or irreversible step. Outside a turn there is nothing pending by definition. An unknown thread_id reads as an empty list; a record already left accepted is not pending. Parameters

register_target_validator

tai42_contract.app.facets.messaging.AppConversations.register_target_validator
Register a bind validator for routes whose target is of target_kind. A plugin calls this through the tai42_app handle when its module loads. Route creation consults every registered validator for the route’s target kind AFTER the target exists but BEFORE the route is written; a validator returning any message lines refuses the creation with them (a 422), so a defect the target carries — a flow reading a state no binding supplies — is caught at bind, never deferred to run time. Registering two validators for one kind raises loudly. Parameters

AppExtensions

tai42_contract.app.facets.execution.AppExtensions
The tool-extension provider namespace (app.extensions).

Members

extension

tai42_contract.app.facets.execution.AppExtensions.extension
Register a tool-extension factory under name (default: the function’s own name). Usable bare or with arguments. requires_body_locality marks an extension whose wrapper only works in the process running the tool body it wraps — e.g. a proxy layer that routes the body’s egress through a task-scoped contextvar, visible only where the body executes. The flag is stored as registration metadata the apply site reads to order a stacked combo: a locality-requiring extension must bind INSIDE any execution-relocating extension (ExtensionKind.relocates_execution), so its wrapper travels with the body to the worker. Bound outside a relocating layer, the wrapper stays behind in the submitting process and silently does not apply. Parameters

available_extensions

tai42_contract.app.facets.execution.AppExtensions.available_extensions
List registered extension modules as [{"name", "kind"}].

AppHttp

tai42_contract.app.facets.routing.AppHttp
The HTTP application facet: middleware, route registration, and mount introspection.

Members

middleware

tai42_contract.app.facets.routing.AppHttp.middleware
Register a middleware on the application. Parameters

custom_route

tai42_contract.app.facets.routing.AppHttp.custom_route
Register a Starlette handler AND its self-describing route metadata. The metadata is the single source of truth the OpenAPI 3.1 emitter and its coverage gate consume, so every registration MUST describe itself:
  • summary — a one-line operation summary (required, non-empty).
  • tags — at least one OpenAPI tag grouping the route (required).
  • response_model — the pydantic model (any BaseModel, RootModel included) describing the success body. Required — there is no default, so a route cannot silently omit it. By default the model is wrapped in the {"data": ...} success envelope; a route that answers a RAW top-level body passes enveloped=False (see below). None is legal ONLY together with a non-blank no_body_reason: the two states are mutually exclusive — a route declares a typed body OR a reasoned no-body, never both and never neither.
  • enveloped — whether the JSON success body is wrapped in the {"data": <response_model>} envelope (the default, True) or is the model’s schema DIRECTLY at the top level (False, a raw non-enveloped body). enveloped=False REQUIRES a response_model: an unwrapped body still needs a real model, so a bare None under it is a registration error.
  • no_body_reason — the required-when-response_model is None justification for a route that serves no {"data": <model>} JSON body (a redirect, a raw/streaming/asset response, a vendor webhook 200, or a raw non-enveloped body the envelope emitter cannot describe). Passing it alongside a response_model, or omitting it when response_model is None, is a registration error.
  • request_model — the pydantic model of the request body; required for any route that reads a body, omitted (None) otherwise.
  • query_model — the pydantic model whose fields are published as in: query parameters for ANY method, additive to request_model. A read door’s request_model already emits as query, so this is the only way a WRITE-method door documents the query it reads at the edge; None (the default) publishes no query model.
  • authed — whether the route requires the api key; emitted as the security requirement. None (the default) defers to the runtime: a core route resolves to True, a declared plugin route to the negation of its tai-plugin.yml public flag. Passing an explicit bool from a declared plugin route module is a registration error — the declaration is the single source of that decision.
  • destructive — whether the route mutates in a way flagged as destructive (default False); emitted as x-destructive.
  • action — the route’s authorization character (a RouteAction); None (the default) lets the surface derive the grantable class from the HTTP methods.
  • declared — the route’s behavioral OpenAPI properties (a DeclaredRouteMetadata): its reload_gated / reads_body / error statuses / success status. A route in the /api/* spec surface declares these (the operations adapter passes its operation’s metadata, a native handler passes its own); None (the default) records trivial defaults for a route outside the spec surface, whose behavioral metadata is never emitted.
The handler’s narrative docstring becomes the operation description, and the reload-gate 503 response is derived from the handler body. Parameters

use_raw_path_key

tai42_contract.app.facets.routing.AppHttp.use_raw_path_key
Match already-registered routes under path_prefix against the raw (undecoded) request path. A path parameter whose values carry / (a state record’s {key}, addressed as one percent-encoded segment) stays ONE segment instead of splitting once the ASGI server has decoded %2F; the matched parameters are decoded once after the match. Called AFTER the routes are registered, over their shared prefix, so it covers a family of doors at one seam. A no-op where no route table is served (the offline spec harness). Parameters

mount_base

tai42_contract.app.facets.routing.AppHttp.mount_base
The resolved absolute mount base of the declared plugin route module importing now. /api/ + the item’s mount base, no trailing slash (e.g. /api/channels/telegram). Callable ONLY while a declared plugin route module imports — the mount binding is present then. A module captures this value at import for later use (a startup hook building an external webhook URL, a login descriptor’s self-referential path) so a remapped base is followed instead of a hardcoded default. Called with no binding present — a core or operator-authored module — it raises: those modules own no declared mount.

AppInteractions

tai42_contract.app.facets.messaging.AppInteractions
The interactions namespace (app.interactions) — the ask facade and answer check.

Members

check_answer

tai42_contract.app.facets.messaging.AppInteractions.check_answer
Validate answer against question — the ONE answer check every door reaches. question is a QuestionFormat (the answer format plus its payload — no stored request needed). Returns None when the answer conforms; raises AnswerMismatchError (carrying the failing field’s dotted path when the fault locates to one) otherwise. The answer door, the callback door, a resumed run’s visit and plugins all validate through this one callable so every surface applies identical rules per format. Parameters

assert_resume_authorized

tai42_contract.app.facets.messaging.AppInteractions.assert_resume_authorized
Authorise the caller to resume (or deliver an outcome for) interaction_id — or raise. A driver’s continuation face and cross-driver chain-delivery tool call this with the id they are about to resume/deliver-to, BEFORE producing any outcome, because those tools are dispatchable by name at the run-tool door and the MCP edge. Authorised only inside the platform’s own resume of that run: it passes iff the ambient run-authorization context names interaction_id directly (the resume origin) OR the interaction’s stored run delivery identity matches the ambient one (a cross-driver chain re-entry of the same run). Raises ParkResumeUnauthorizedError for an external caller (no origin) or an id belonging to another run — never a mere presence test. Parameters

assert_delivery_authorized

tai42_contract.app.facets.messaging.AppInteractions.assert_delivery_authorized
Authorise a door delivery-address tool to fire for completion_id — or raise. A door’s out-of-band delivery address is a registered tool the platform’s delivery ladder fires; the tool calls this at entry with the payload’s completion_id before delivering anything. It passes iff the ambient delivery-fire context is set AND equals completion_id — a None id and a call outside any fire never pass. Raises ParkDeliveryUnauthorizedError otherwise, so a caller naming the address tool directly at the run-tool door or the MCP edge delivers nothing. Parameters

redelivery_horizon_seconds

tai42_contract.app.facets.messaging.AppInteractions.redelivery_horizon_seconds
The platform’s redelivery retention horizon in seconds. The continuation-due record ages out at it and the reaper caps its redelivery backoff at it, so no resume redelivery fires past it. A resuming driver derives its own resolution-record retention from this value rather than a hard-coded guess.

visit

tai42_contract.app.facets.messaging.AppInteractions.visit
The bound, Visit-typed shared-visit callable. The ONE seam every door drives a parkable run through: it runs the cancel / resume / take / start order once for every caller (checks everything before doing anything, cancels, resumes or takes at most one action besides cancel, starts the target when nothing was resumed, normalises what came back), and returns a VisitOutcome. A door resolves its own jqs to plain values and hands them in; the generic list_parked / resume_parked / cancel_parked below are thin wrappers over this same seam.

park_answer

tai42_contract.app.facets.messaging.AppInteractions.park_answer
The ONE park-answer shape a direct door hands back for a VisitOutcome. A plain result is the tool’s own value; an asks outcome is the caller ask entries the run parked ({"asks": [entry, ...]}); a parked outcome is the suspended sentinel; none is None. Both the synchronous run-tool door and the background submit’s terminal record shape a park through this ONE callable, so a poller of either door reads identical bytes and can tell a caller-ask park (answerable through resume_parked) from a user-ask park. It never reveals a wrapped secret — the sync door reveals those on the result kind itself and every recorder masks its own copy. Parameters

normalise_started

tai42_contract.app.facets.messaging.AppInteractions.normalise_started
Classify a raw start return into a started VisitOutcome over the ambient subject. The same normalisation visit applies to what its start returned — caller asks, a re-park, or a final result — exposed for a door that already ran its start INSIDE its own visit (a hook fire whose visit owns the run) and only needs the return classified, so its record carries the same park answer both direct doors return. Parameters

list_parked

tai42_contract.app.facets.messaging.AppInteractions.list_parked
Every parked interaction on the current run’s subject — the full parked entries. Reads the ambient run’s subject candidates and returns the union over its subject keys, de-duplicated, each a ParkedEntry with its id, status (asking/running/finished/failed) and the question/answer fields a state-backed entry carries. The same rows a door-contract jq reads as $parked.

list_parked_for

tai42_contract.app.facets.messaging.AppInteractions.list_parked_for
Every parked interaction on context’s subject — the same entries as list_parked. A parkable-driving door fetches this over its OWN StateContext once and feeds the list to the door-contract evaluator as $parked, keeping the contract evaluation a pure function of an injected list rather than an ambient read. A None context has no subject and returns an empty list. Parameters

current_fire_identity

tai42_contract.app.facets.messaging.AppInteractions.current_fire_identity
The ambient execution identity as the (user_id, fingerprint) pair a fire forwards, or None. A background task tool dispatched from within a door fire forwards this pair onto its worker job so the deferred fire re-binds the SAME authority; None when no identity (or no per-mint fingerprint) is bound, so nothing is forwarded and the deferred fire fails closed on any credential seam rather than under a substituted principal.

bound_execution_identity_for_fire

tai42_contract.app.facets.messaging.AppInteractions.bound_execution_identity_for_fire
An async with binding execution_key’s live-grant identity for a receiver-less door fire. A scheduled fire has no live caller, so the door stores the firing identity (the execution key’s user_id and its per-mint fingerprint) at create and binds it here at fire, so a run that async-parks can rebind its continuation and a to="caller" resume acts under the same authority. Homed beside the door’s other kit-reachable seams so a backend plugin binds a scheduled fire’s identity without importing the skeleton. Raises when the key no longer carries authority — the fire fails closed, never under a substituted principal. Parameters

resume_parked

tai42_contract.app.facets.messaging.AppInteractions.resume_parked
Resume a parked caller ask with payload, or TAKE its waiting outcome when omitted. With payload given it resumes the asking caller ask interaction_id and returns the resumed run’s normalised outcome; with payload omitted it TAKES a finished entry’s waiting outcome (kind="result") or re-raises a failed one as ParkableRunFailedError. A live inline receiver, so the resumed run’s terminal is returned inline rather than delivered out of band. Parameters

cancel_parked

tai42_contract.app.facets.messaging.AppInteractions.cancel_parked
Whole-chain kill every parked interaction named in ids on the current run’s subject. Each id is torn down through the one teardown seam (its run and every run it linked above it close for good, delivering FAILED once to a door that started it); returns a VisitOutcome naming the ids cancelled. An id outside the run’s own parked list raises ParkedEntryGoneError with nothing cancelled. Parameters

ask

tai42_contract.app.facets.messaging.AppInteractions.ask
The bound, Ask-typed ask callable. An in-process plugin asks a human without importing the skeleton: await tai42_app.interactions.ask(question, ..., mode="async", expiry_at=...). The return shape is the Ask contract’s: mode="sync" returns the typed answer, mode="async" returns a SuspendedInteraction. Its full call signature is the Ask Protocol’s, including the per-ask on_mismatch digression policy and mismatch_notice retry text a channel-delivered ask carries. A facade EXPOSURE of the skeleton helper through the already-typed Protocol — no new ask semantics.

AppLifecycle

tai42_contract.app.facets.runtime.AppLifecycle
Startup, shutdown, reload, and post-swap lifecycle hook registration.

Members

on_startup

tai42_contract.app.facets.runtime.AppLifecycle.on_startup
Register func to run at process startup (usable as a decorator). Parameters

on_shutdown

tai42_contract.app.facets.runtime.AppLifecycle.on_shutdown
Register func to run at process shutdown (usable as a decorator). Parameters

on_reload

tai42_contract.app.facets.runtime.AppLifecycle.on_reload
Register a handler re-run after every in-place re-init (reload_config). For example, dynamic tool loaders that on_startup ran once. Parameters

on_post_swap

tai42_contract.app.facets.runtime.AppLifecycle.on_post_swap
Register an establisher for a loop-affine background loop (a periodic poll or sweep). Run on the real serving loop at boot and after every epoch swap — never on the throwaway build-thread loop the per-epoch handlers run on — so the loop it spawns attaches to the serving loop and retires with its generation. Parameters

on_fleet_op_applied

tai42_contract.app.facets.runtime.AppLifecycle.on_fleet_op_applied
Register a handler fired after any worker-bus op applies in this process. Also fired after the reconnect self-resync reload. Unlike its zero-arg siblings, the handler takes ONE argument — the op name — so it can act on some ops and skip others (a query op carries no state change to react to). Parameters

wait_until_ready

tai42_contract.app.facets.runtime.AppLifecycle.wait_until_ready
Block until this process’s first boot self-resync has completed. That is the point at which the tool registry is fully built and stable for the run. A backend runtime that forks a child (or otherwise consumes queued work) per job awaits this before its work loop accepts anything: the boot self-resync rebuilds the tool registry non-atomically, so a worker that dequeued and forked mid-rebuild would run the job against a half-built registry. The latch is one-way — it resolves once and stays resolved, so a later bus reconnect (which re-runs the self-resync while the app is already live) never un-readies the process.

AppMonitoring

tai42_contract.app.facets.runtime.AppMonitoring
Registration and access for the process monitoring backend.

Members

register_monitoring

tai42_contract.app.facets.runtime.AppMonitoring.register_monitoring
Register the monitoring backend builder, or return a decorator when builder is omitted. Parameters

active

tai42_contract.app.facets.runtime.AppMonitoring.active
The active monitoring backend (impl type behind the contract protocol).

AppPresets

tai42_contract.app.facets.authoring.AppPresets
The presets namespace (app.presets) — the typed view + the bind kernel. store is the PresetStore-typed view over app.versioning.store (kind="preset"). bind is the kernel BOTH tiers (ephemeral and versioned) build their live tool through, so its typed-schema behavior reaches both.

Members

bind

tai42_contract.app.facets.authoring.AppPresets.bind
Return a FastMCP tool transform of base_tool as a new named tool. Built in ONE Tool.from_tool call: each fixed_kwargs key is baked as a HIDDEN, FIXED constant (removed from the exposed schema; a caller that passes it is rejected — it cannot be overridden at runtime) while the REMAINING arguments keep the base tool’s real typed schema (names, types, descriptions). tags sets the transformed tool’s native tags. An output_schema (an object JSON Schema) is baked into an agent base’s response_format (forcing structured output) or advertised + validated on a plain tool base. bind is async because it must resolve the base Tool object (via app.tools.get_tool(base_tool)) to feed the transform. Parameters

create

tai42_contract.app.facets.authoring.AppPresets.create
Create a versioned preset in-process and return its record view. The in-process authoring seam beside the HTTP create door: it runs the same content path (name pre-checks, combo/schema/bind validation, input-schema support, the base tool’s write validator, store write THEN register, and the rebind fan-out) and returns the same record shape, so the two doors cannot drift. A body its base tool cannot accept, a colliding name, or an input_schema over a base tool with no registered support is a loud error that persists nothing. The caller-authorization tier fence is OFF — the registration-tier fence authorizes a request principal at the HTTP doors; an in-process caller authorizes its own callers and passes only the base tools it is entitled to author — while every content check stays on. Parameters

save_version

tai42_contract.app.facets.authoring.AppPresets.save_version
Save a new version of an existing preset in-process and return the version row. The in-process sibling of the HTTP save-version door, running the identical content path and returning the same shape. Omitted fields carry the active value forward (input_schema via the CARRY_FORWARD sentinel; output_schema only when output_schema_provided is True). A body that cannot bind is a loud error that commits nothing; the tier fence is OFF for the reason create states. Parameters

register_write_validator

tai42_contract.app.facets.authoring.AppPresets.register_write_validator
Register the write validator for base_tool (one per base tool; duplicate registration raises). A base-tool plugin calls this through the tai42_app handle when its tool module loads. The validator runs on every write that persists a body — create / save-version / rollback — and in the dry-run validate verdict, so a body its base tool cannot accept is a loud 400 that never persists. A base tool with no registered validator gets no extra check. Parameters

register_input_schema_support

tai42_contract.app.facets.authoring.AppPresets.register_input_schema_support
Declare that base_tool ACCEPTS a per-preset input schema (one per base tool; duplicate raises). A base-tool plugin calls this through the tai42_app handle when its tool module loads. A preset that sets an input_schema over a base tool with no registered support is a loud authoring error at the shared preset-authoring chokepoint, never a silently-ignored schema. Parameters

input_schema_support

tai42_contract.app.facets.authoring.AppPresets.input_schema_support
The input-schema support base_tool declared, or None if it declared none. When None, the base tool’s typed schema is fixed. Parameters

register_registration_tier

tai42_contract.app.facets.authoring.AppPresets.register_registration_tier
Declare the authz tier required to author a preset over base_tool (one per base tool). Governs create/save/rollback/rename; duplicate registration raises. Default authoring is the presets’ own write action; a base tool with no declaration keeps that default. A base tool declaring fenced requires the admin fence to author a preset over it. The shared preset-authoring chokepoint reads this and enforces it BEFORE any store write on every authoring door. Parameters

registration_tier

tai42_contract.app.facets.authoring.AppPresets.registration_tier
The authoring authz tier base_tool declared, or None if it declared none. When None, authoring keeps the presets’ default write action. Parameters

get_active_versioned_body

tai42_contract.app.facets.authoring.AppPresets.get_active_versioned_body
One preset’s active (version, body) read TOGETHER in one query. The version-aware sibling of store.get_active_body: it captures the active version pointer and the body it points at atomically, so a consumer that needs the version beside the body never risks a skewed second read across a concurrent activation. Raises PresetNotFoundError for an unknown preset. Parameters

used_by

tai42_contract.app.facets.authoring.AppPresets.used_by
The other presets whose active bodies compose preset name as a tool, sorted. Computed over the active preset population (a body’s composed tool names intersected with the population, self excluded), so it answers “which saved presets depend on this one” for a rename/delete dependents pass. Raises PresetNotFoundError for a name that is not a known preset. Parameters

register_seed

tai42_contract.app.facets.authoring.AppPresets.register_seed
Declare a default preset the platform seeds at import time. A plugin calls this through the tai42_app handle when its module loads. The declared seeds are applied by the startup/reload seed applier — created when absent, a preset already present left untouched. Declaring two seeds under the same name raises loudly — a silent overwrite could drop one plugin’s default under another’s. Parameters

store

tai42_contract.app.facets.authoring.AppPresets.store
The typed preset view over app.versioning.store (kind="preset").

AppSandboxes

tai42_contract.app.facets.execution.AppSandboxes
The sandbox-provider namespace (app.sandboxes).

Members

register_sandbox

tai42_contract.app.facets.execution.AppSandboxes.register_sandbox
Register the Sandbox provider (decorator form, returning the class unchanged). One provider backs the slot; a second registration is a conflict the runtime rejects loudly.

sandbox

tai42_contract.app.facets.execution.AppSandboxes.sandbox
The registered provider, or None — status/introspection ONLY. Never gate execution on this nullable read; acquire through require_sandbox, the every-door guarantee (a None property is how per-consumer checks drift).

require_sandbox

tai42_contract.app.facets.execution.AppSandboxes.require_sandbox
Return the registered provider from the ONE raising acquisition chokepoint. Raise SandboxUnavailableError (naming TAI_MCP_SANDBOX and sandbox_module) when none is registered. EVERY consumer acquires through here.

sandbox_policy

tai42_contract.app.facets.execution.AppSandboxes.sandbox_policy
Return the skeleton-resolved SandboxPolicy. This is the plugin-reachable READ of the SAME policy the skeleton binds to the kit at the session-create chokepoint. Available REGARDLESS of whether a provider is registered (it reads operator config, not a provider). Mirrors the ask / resolve_connection_auth facade accessors that let an in-process plugin read a skeleton-resolved value without importing the skeleton; a consumer building a policied spec reads the network default and scrub_transcript here. Implemented in the skeleton, which resolves the policy once and returns the SAME value it binds to the kit.

AppStates

tai42_contract.app.facets.states.AppStates
The subject-keyed state store namespace (app.states). The door-agnostic contract every door and tool reads and writes a subject’s document through. The store takes a full StateSubject and refuses anything less; subject resolution happens once per door, never here. Every write door supplies a WriteOrigin carrying only what a consumer knows — the platform completes it (door/actor/turn_id) at this chokepoint, so the audit ledger is never optional or forgeable. While the states component’s database is unbound every method raises StatesNotConfiguredError (501), never an empty read.

Members

list_declarations

tai42_contract.app.facets.states.AppStates.list_declarations
Every declared state.

get_declaration

tai42_contract.app.facets.states.AppStates.get_declaration
The declaration named name, or None when none is declared. Parameters

put_declaration

tai42_contract.app.facets.states.AppStates.put_declaration
Declare or re-declare a state and return the stored declaration. An additive re-declare (new optional fields, new subject kinds) is applied in place; a change that would remove or narrow a field while records exist raises NonAdditiveRedeclareError (erase the records first), and removing a subject kind still present in records raises DeclarationInUseError. Never a silent overwrite. Parameters

delete_declaration

tai42_contract.app.facets.states.AppStates.delete_declaration
Delete a state with its records and attachments. Raises DeclarationInUseError when a consumer still binds it. Parameters

stats

tai42_contract.app.facets.states.AppStates.stats
Counts for a state — records, subjects by kind, consumers — for the listing. Parameters

list_templates

tai42_contract.app.facets.states.AppStates.list_templates
Every stored platform template document.

get_template

tai42_contract.app.facets.states.AppStates.get_template
The template document named name, or None when none is stored. The read a consumer’s own sibling document validates against. Parameters

put_template

tai42_contract.app.facets.states.AppStates.put_template
Store a template document and return it (replace required to overwrite an existing name). Runs every registered attach validator over each live attachment before the write, so a consumer’s data-dependent check still fires here; a raise leaves the stored document untouched. Overwriting an existing name without replace raises TemplateExistsError. Parameters

delete_template

tai42_contract.app.facets.states.AppStates.delete_template
Delete a template document. Raises TemplateInUseError while it is still attached. Parameters

list_attachments

tai42_contract.app.facets.states.AppStates.list_attachments
Attachment rows filtered by state, by template, or every attachment when both are None. What the attachments listing and the Consumers tab read. Each row carries state, template, path, parameters and declarations. Parameters

attach

tai42_contract.app.facets.states.AppStates.attach
Attach template on state at body.path, recomposing the effective schema in one transaction. Stores the resolved parameters and declarations. Runs every registered attach validator before the write; a raise refuses the door with the validator’s message. Overlapping fragments raise AttachConflictError. Parameters

update_attachment_declarations

tai42_contract.app.facets.states.AppStates.update_attachment_declarations
Replace an attachment’s declaration values, recomposing the effective schema before the write. Re-runs every registered attach validator and reconciler before the write. options is a per-operation directive bag passed to the reconcilers for THIS operation only, never stored or served back (None is an empty bag). Parameters

detach

tai42_contract.app.facets.states.AppStates.detach
Remove an attachment and recompose the state’s effective schema. Parameters

read

tai42_contract.app.facets.states.AppStates.read
The record for subject (resolving a fold to its canonical subject), or None when none exists. An unknown person or a target mismatch is a refusal, never an empty document. Parameters

replace

tai42_contract.app.facets.states.AppStates.replace
Replace subject’s whole document with data and return the new record. Parameters

merge

tai42_contract.app.facets.states.AppStates.merge
Shallow top-level merge patch into subject’s document and return the new record. Parameters

apply

tai42_contract.app.facets.states.AppStates.apply
Apply an op batch to subject’s document under the effective schema. Refuses a whole-path write over a composing path (RegimeViolationError) before the ledger insert, stamps _trace under a traced attachment, and records one state_writes row with the touched paths and the completed origin. A replayed op_id returns applied=False without re-writing; guarded ops land in skipped. Parameters

eval_template_jq

tai42_contract.app.facets.states.AppStates.eval_template_jq
Evaluate an input-purpose template_jq program name for subject and return its value. The program’s jq runs over the subject’s record, params supplying its declared parameters. name resolves across the state’s attached templates (unqualified → the declaring template; <attachment>.<name> → that attachment’s template). An unknown name is a StateNotFoundError; an ambiguous unqualified name, an update-purpose name, an undeclared param or an evaluation failure is a ValueValidationError. A read; no write is recorded. Parameters

apply_template_jq

tai42_contract.app.facets.states.AppStates.apply_template_jq
Apply an update-purpose template_jq program name to subject. Its jq maps the record subtree (its .) with $input bound to a template-relative op batch, rebased under the attachment path and applied through the same chokepoint as apply — so regimes, the composing-shape guard, trace stamping and op_id idempotency all hold. name resolves as for eval_template_jq. An unknown name is a StateNotFoundError; an ambiguous unqualified name, an input-purpose name, an evaluation failure or a wrong-shaped return is a ValueValidationError. Parameters

erase

tai42_contract.app.facets.states.AppStates.erase
Erase subject’s record, recording the write. Parameters

fold

tai42_contract.app.facets.states.AppStates.fold
Fold subject into into and return the resulting canonical document. mode decides how the documents combine. A self-fold, a cycle, a conflicting re-fold, or a merge whose result fails the schema raises SubjectFoldError; a retried fold to the same target is a quiet no-op. Parameters

list_subjects

tai42_contract.app.facets.states.AppStates.list_subjects
A keyset page of subjects for state (optionally one kind). {"subjects": [...], "next_cursor": <cursor|None>}. Parameters

search

tai42_contract.app.facets.states.AppStates.search
A keyset page of records whose document contains filters. {"matches": [...], "next_cursor": <cursor|None>}. Parameters

writes

tai42_contract.app.facets.states.AppStates.writes
One keyset page of the audit trail for subject, newest first. The items (each a write with its completed origin and touched paths) plus the next_cursor that pages the trail like list_subjects/search page theirs (the last row’s id when the page is full, else None). Parameters

prune_expired

tai42_contract.app.facets.states.AppStates.prune_expired
Delete records past their state’s retention_days and return the per-state deletion counts.

context

tai42_contract.app.facets.states.AppStates.context
The ambient StateContext the current door deposited. None outside a door (an api write completes from the request principal instead).

register_consumer_lister

tai42_contract.app.facets.states.AppStates.register_consumer_lister
Register a lister for consumer kind (flow / hook / schedule / agent). A plugin calls this through the tai42_app handle when its module loads; consumers unions every registered lister. Registering two listers for one kind raises loudly. Parameters

consumers

tai42_contract.app.facets.states.AppStates.consumers
Everything that binds state — the union of every registered consumer lister — for the Consumers tab. Parameters

register_template_seed

tai42_contract.app.facets.states.AppStates.register_template_seed
Declare a platform template document the platform seeds at import time. A plugin calls this through the tai42_app handle when its module loads. The startup/reload seed applier creates it when absent and leaves a template already present untouched. Declaring two seeds under one name raises loudly. Parameters

register_attach_validator

tai42_contract.app.facets.states.AppStates.register_attach_validator
Register a data-dependent attach validator. A plugin calls this through the tai42_app handle when its module loads. The validator receives the template document, an attachment’s declaration values, and the state’s effective schema, and RAISES to refuse; it runs before every attach, update_attachment_declarations and put_template(replace=True) write, so a consumer’s checks fire at the platform’s declarations doors, the States page included. Parameters

register_attach_reconciler

tai42_contract.app.facets.states.AppStates.register_attach_reconciler
Register a pre-write attach reconciler. A plugin calls this through the tai42_app handle when its module loads. The reconciler receives a AttachReconcileContext — the template, the operation, the previous and new declarations, the attach options, and a record door bound to the state — inside every attach and update_attachment_declarations write, after the validators and before the write. It RAISES to refuse the attach (naming the records the new declarations orphan) or writes resolutions through the context’s record door and returns, letting the attach commit with those writes. Parameters

AppStorage

tai42_contract.app.facets.execution.AppStorage
The storage-provider namespace (app.storage).

Members

register_storage

tai42_contract.app.facets.execution.AppStorage.register_storage
Register the Storage provider; usable bare or as a decorator factory.

resource_manager

tai42_contract.app.facets.execution.AppStorage.resource_manager
The active resource manager (impl type; loads/renders content over storage).

AppSubApp

tai42_contract.app.facets.runtime.AppSubApp
Access to the sub-app MCP router.

Members

mcp_sub_app_router

tai42_contract.app.facets.runtime.AppSubApp.mcp_sub_app_router
The router for mounted sub-app MCP servers.

AppToolMeta

tai42_contract.app.facets.authoring.AppToolMeta
The tool-metadata namespace (app.tool_meta) — the organizational overlay over any live tool. The overlay is a folder tree plus a per-tool row (display name, folder placement, tags, badges, a hidden override). store is the ToolMetaStore view the routes and the preset lifecycle cascade read and write. patch is the in-process edit seam beside the HTTP PATCH door.

Members

store

tai42_contract.app.facets.authoring.AppToolMeta.store
The tool-metadata overlay store the routes and preset cascade read and write.

patch

tai42_contract.app.facets.authoring.AppToolMeta.patch
Patch a tool’s overlay row in-process and return its record. The in-process sibling of the HTTP PATCH door, running the same operation so validation is identical (an unknown folder_id is a loud error). Only the arguments given are written: folder_id places the tool, and a tags list REPLACES the whole tag set (array values are set replacements, not merges). tags=None leaves the tag set untouched; folder_id=None leaves the placement untouched. Parameters

AppVersioning

tai42_contract.app.facets.authoring.AppVersioning
The generic versioned-document store namespace (app.versioning). This is the platform persistence primitive — append-only versions + an active pointer + rollback over an opaque JSONB body, discriminated by kind. Direct consumers (e.g. AC policies under kind="ac_policy") reach it here; presets reach it through AppPresets, never as a new kind.

Members

store

tai42_contract.app.facets.authoring.AppVersioning.store
The append-only versioned-document store backing this namespace.

AppWebhookVerifiers

tai42_contract.app.facets.messaging.AppWebhookVerifiers
The webhook-verifier registry namespace (app.webhook_verifiers).

Members

register

tai42_contract.app.facets.messaging.AppWebhookVerifiers.register
Register a WebhookVerifier under name. A provider plugin calls this through the tai42_app handle when its import-only webhook_verifier_modules entry loads. Registering a name already taken raises loudly — a silent overwrite could swap a topic’s verifier out from under a live binding. Parameters

get

tai42_contract.app.facets.messaging.AppWebhookVerifiers.get
Fetch a registered verifier by name; raise loudly on an unknown name. Resolution happens when a verifier is bound to a public webhook door, so an unknown name surfaces at bind time as a loud failure, never a silently-unverified door. Parameters

DeclaredRouteMetadata

tai42_contract.app.facets.routing.DeclaredRouteMetadata
The behavioral OpenAPI properties a route DECLARES. A route registered through the operations adapter supplies this from its operation’s metadata + declared error classes; a native /api/* handler passes it explicitly at its custom_route registration. Its reload_gated / reads_body / error statuses / success status feed the emitted spec and the coverage/parity gates. additional_success_statuses names further 2xx codes one method may answer besides success_status; each is emitted as its own success response. Attributes

PendingMessage

tai42_contract.app.facets.messaging.PendingMessage
One participant message accepted on a thread but not yet carried into a turn. The projection AppConversations.pending_messages returns, so a body running inside a turn can learn a newer message is waiting and stop before an irreversible step. message_id is the accepted record’s id, text its verbatim inbound text, accepted_at the epoch seconds it was accepted at (the thread index’s own score). Frozen. Attributes

RouteAction

tai42_contract.app.facets.routing.RouteAction