Skip to content

surfaces

The closed catalog and its renderers.

coalitionkit_surfaces

Surfaces: AG-UI 1.0 feed and agent sessions and validated A2UI v0.9 trees.

AgentSession

Interrupts and agent text for one viewer. Answers become owner-signed decisions.

say
say(text: str) -> None

Queue a message from an agent to this person (the caller addresses it to them).

changed
changed() -> list[Frame]

Call after a bus wake: a new run only when the set of open requests changed.

answer
answer(
    interrupt_id: str,
    consent: bool,
    choice: str | None = None,
) -> Document

Turn this person's answer into an owner-signed coalition.decide and send it.

ConsentError

Bases: Exception

A consent answer was refused. code is stable; detail is safe to show.

Composed dataclass

A surface's three messages (createSurface first) and whether they are the fallback.

FeedSession

Frames for one connected viewer. Pure state machine: the caller supplies time and wakes.

start
start() -> list[Frame]

A new run with a fresh snapshot. Connecting, reconnecting and rotating all call this.

changed
changed() -> list[Frame]

Call after a bus wake. A delta only when this viewer's own projection changed.

tick
tick() -> list[Frame]

Call on a timer: queued events, run rotation, or a keep-alive comment.

room_delta
room_delta(room: Document) -> list[Frame]

Patch only the room key of the last state sent, without reading the host.

is_stale
is_stale() -> bool

Something outside the log changed this viewer's extra state (the room engine's step).

fail
fail(message: str, code: str | None = None) -> list[Frame]

End the run with RUN_ERROR. The renderer keeps its last good surface and reconnects.

publish_surface
publish_surface(
    surface_id: str,
    components: list[Document],
    data_model: Any = None,
    known_events: Collection[str] | None = None,
) -> bool

Queue a composed surface. Returns False when it failed validation and the fallback layout was queued instead. Callers pass content already limited to this viewer.

KeepAlive dataclass

An SSE comment line. It carries no data and exists only to hold the connection open.

SurfaceHub

refused
refused(viewer: str, kind: str, error: Document) -> None

Keep only safe refusal metadata, never the refused payload or error detail.

view_as
view_as(viewer: str, target: str) -> list[Document]

Compose only values present in both projections; never merge their scopes.

say
say(viewer: str, text: str) -> None

Deliver only to this viewer, independently on the feed and legacy agent channel.

stream async
stream(
    session: Session, viewer: str | None = None
) -> AsyncGenerator[str]

SSE text for one connection. Subscribes before the first snapshot so nothing is lost.

OwnerSigner

Bases: Protocol

Turns a person's yes or no into a signed coalition.decide envelope.

subject is {kind, id, revision}. choice is the value the decision names (the subject id for every kind except tension_option). The returned envelope must be signed by the agent key and carry a consent_sig made with the OWNER key. The surface verifies that before it sends anything.

ViewerAuth

Bases: Protocol

Maps a bearer token to the participant it speaks for, or None.

bound_number

bound_number(
    value: int | float, event_ref: str
) -> Document

A number tied to the event it came from: the only form of a number the catalog accepts.

fallback_components

fallback_components() -> list[Document]

The fixed layout shown when a composed tree fails validation.

open_requests

open_requests(
    host: CoalitionHost, viewer: str
) -> list[ConsentRequest]

Pending consent rows of this decider on the host ledger, for the current revision only.

load_catalog

load_catalog(path: str | Path) -> Catalog

Read the typed catalog: {catalogId, components: {Name: {props: {p: {type, ...}}}}}.

Every prop has a type from PROP_TYPES, an optional required flag and, for enum, its values. Props of type child and children hold component ids.

validate_components

validate_components(
    catalog: Catalog,
    components: Any,
    known_events: Collection[str] | None = None,
) -> list[str]

Every reason the tree must not be sent. An empty list means it passes.

apply_patch

apply_patch(
    document: Document, ops: list[Document]
) -> Document

Apply a patch to a copy of document; used by renderers' tests and the property test.

encode

encode(frame: Frame) -> str

The SSE text of one frame.

json_patch

json_patch(
    previous: Document, current: Document
) -> list[Document]

An RFC 6902 patch that turns previous into current (empty when equal).