Skip to main content

Philosophy

A stream is a view of an agent’s durable conversation, not ownership of the agent’s execution. Formation keeps execution in Temporal and canonical data in Postgres. A browser, mobile application, or backend adapter can disconnect and rejoin without starting another model call or cancelling the run. This follows Formation’s identity-first and perspective principles: every feed belongs to one agent, connector installation, conversation, and authorized reader. Authentication of an installation is not permission to disclose a conversation to a different actor. Current audience checks apply to snapshots, live reads, and replay. Capture precedes behavior. Public events commit before they reach a socket; projection updates and their sequence numbers commit together. Provider bytes are private inference until the runtime authorizes publication. Tool arguments, reasoning, control syntax, and ambiguous working commentary are not public progress. Existing evidence-backed progress remains the progress authority. The adapter principle keeps provider decoding separate from runtime policy and HTTP transport. Model adapters report incremental content and final accounting; the runtime decides what may be published. An application backend authenticates its user and proxies the signed protocol. It does not run another agent loop.

ELI5

Think of Formation as a person writing in a shared notebook. The notebook is saved before each new piece is shown. Your phone watches the notebook through a window. Closing the window does not stop the person working. When you reopen it, you tell Formation the last numbered update you saw and it shows what you missed. Only the pages you are allowed to read are visible. The person’s private scratch paper and tool instructions never appear in that window.

Contracts

  • Commands and subscriptions have separate lifetimes. Disconnecting a subscriber never signals cancellation. A completed run is an explicit durable state; socket EOF only means reconnect.
  • A snapshot includes a conversation-local sequence watermark. Replay begins at the next sequence. SSE IDs are decimal sequence numbers compatible with the application SDK. Sequence assignment is serialized by the conversation row, not a global SQL sequence whose allocation order can differ from commit order.
  • Every public delta and its materialized message update commit atomically. Consumers need no provider connection and no sticky API replica. PostgreSQL remains authoritative; transport wakeups are hints, never durable delivery.
  • Model attempts have distinct identities. A retry replaces its incomplete draft explicitly; it never appends a different generation to a partial answer. Existing execution ownership fencing rejects obsolete workers.
  • Rechecks precede publication. If early disclosure cannot be established, the runtime buffers the answer until the existing final validation succeeds.
  • Slow subscribers have bounded writes and replay pages. Expired or invalid cursors require a fresh snapshot instead of silently skipping updates.
  • Provider usage and errors remain in the existing attempt/accounting path. Partial tool JSON is never executed and private reasoning is never emitted.

Verification requirements

Exercise genuine first-content delivery before provider completion, reconnect without duplicate commands, concurrent append ordering, snapshot/event races, wrong-agent/install/actor denial, audience revocation, stale-owner rejection, partial provider failure and retry, terminal reconciliation, slow consumers, and final usage accounting. Persistence tests use a real PostgreSQL database.

Implementation

The implementation exposes signed snapshot and SSE endpoints on the generic connector. See the protocol for exact wire shapes, bounds, and client behavior. Provider adapters support incremental Chat Completions and Responses decoding through the existing audit/retry path. An explicit begin_answer handoff separates private tool work from a public, tool-free answer inference. This costs an extra inference boundary for a normal working turn, but prevents accidental publication of commentary that precedes a tool call. Its receipt uses the ordinary durable tool ledger; no parallel agent loop or new execution scheduler is introduced. Control-envelope replies remain buffered when incremental publication cannot preserve their validation contract. Postgres hooks capture graph messages, run status, and authorized progress in the same transaction as those records. Incremental text uses the existing acquired execution-generation fence. Public drafts have explicit attempt identities; canonical delivery settles them by message ID. Existing generic conversations are backfilled during migration. The initial transport polls committed pages instead of adding a broker or requiring session-pinned database connections. This fits the existing transaction-pool deployment contract. Notification fan-out remains an optional optimization: it may wake readers, but must never replace replay from Postgres. Streaming capability does not imply new application command capabilities. Cancellation and approval remain independent runtime concerns; this protocol keeps disconnect separate from them and does not advertise new command APIs.

Opt-in native presentation

Streaming is a per-installation capability, disabled by default. It changes neither existing webhook contracts nor buffered callers’ inference flow until an operator enables it. The public-answer handoff has the same authorization and private/public boundary for an application feed, Slack, and Telegram. Slack and Telegram are presentation adapters over that boundary. Authorized text is journaled before native publication. A separate durable reservation tracks the external draft identity; it is never a canonical reply receipt. The ordinary reply boundary still validates and renders the answer, persists per-part delivery state, and records the canonical conversation. Progress notices cannot finalize a draft. Only the first final part reconciles it. In notebook terms: Slack shows an erasable copy of the page and later replaces it with the checked version. Telegram briefly shows a pencil sketch, then sends the finished page. Each connection must ask for that preview; everyone else continues receiving the finished page as before. Native transport cannot promise exactly-once visibility: Slack has no creation idempotency key. Reservations avoid blind retries, known IDs permit reconciliation, and interrupted attempts receive best-effort cleanup. An unacknowledged creation can leave a provisional message. This limitation belongs to the adapter, not to execution ownership or the application journal’s resumable subscription contract.