AI & Agents

Durable Session Channels

Multi-turn identity, scoped membership, ordered controls, strict stream cursors, verified snapshots, and safe runtime upgrades.

One identity. One ordered journal. Any number of reconnecting views.
Authority
Live owner/member ACL on every operation
Continuity
Strict inclusive cursor over committed sequences
Recovery
Verified snapshots accelerate replay; never replace it

A durable agent session owns ordered input, output, controls, membership, retention, and runtime requirements across individual turns. A conversation view is a projection of that journal, not a second source of truth.

Identity and access

Session identity is scoped by tenant, pinned agent definition, and external id; the API returns an opaque server id. Repeated creation and racing tabs converge on one session. A bounded idempotency key makes each input or control append exactly once.

Knowing a same-tenant session id grants nothing. Every create, list, get, append, subscribe, action, lifecycle command, token operation, and watch operation checks the live owner/member ACL.

Session roleCapabilities
owner / managerRead, append, controls, membership, lifecycle, scoped tokens, watches
contributorRead, subscribe, append, answer input, invoke declared actions
viewerRead and subscribe only

Browser session tokens last at most 15 minutes and bind tenant, actor, environment, session, token id, operations, and expiry. They cannot delegate token minting, membership, lifecycle, legal-hold, or watch-management authority.

One cursor contract

Responses identify the last committed inclusive sequence. A subscriber requests records strictly after that sequence with Last-Event-ID or ?after=. Reconnect backfills the durable journal before joining live delivery and removes boundary duplicates. A future cursor conflicts; pruned retained history returns typed HTTP 410 resync_required metadata.

Closing a network stream never cancels accepted work. Use the explicit turn cancel operation when cancellation is intended.

Reconnect pathThe journal closes every delivery gap
  1. Commit

    Persist the event and assign its inclusive sequence.

  2. Resume

    Request records strictly after the last seen sequence.

  3. Backfill

    Read durable history before joining live delivery.

  4. Follow

    Remove boundary duplicates and continue from the live stream.

Interrupted inference and tools recover differently:

  • model work preserves committed partial deltas and follows the pinned discard, continue, or repair policy;
  • an ambiguous in-flight tool call parks for reconciliation and is never blindly repeated;
  • text_reset stream controls tell clients whether interrupted partial output was cleared, retained, or replaced.

Ordered controls

POST /api/v1/chat/sessions/{session_id}/controls appends one typed control:

  • queued_message becomes the next normal turn;
  • steering_message is considered only between completed model/tool steps;
  • a declared action creates a new immutable history revision;
  • context_candidate is internal-only and requires a declared processor or specialist source.

Controls never interrupt an in-flight side effect. Undo or regenerate changes only the model-visible branch; it cannot claim to reverse an external action. Compensation must be a separately authorized tool call with its own target and receipt.

Verified fold snapshots

Postgres remains authoritative. A background worker may store a bounded snapshot with the session incarnation, event sequence, journal-prefix hash, fold/codec versions, definition/policy/tool lineage, and state hash. Reads verify every binding, then resume from sequence + 1.

Missing, stale, corrupt, oversized, wrong-lineage, or unsupported snapshots are quarantined with content-free evidence and fall back to full journal replay. Redis is not required for correctness.

Runtime compatibility and upgrades

Every request sends Ductor-Agent-Protocol-Version: 1. Missing or unsupported versions return HTTP 426 with supported versions. Active turns pin build, deployment, compatibility set, journal-fold version, and client-protocol version; an incompatible worker cannot claim them.

An owner or manager may upgrade a safe, unleased session:

POST /api/v1/chat/sessions/{session_id}/upgrade
Ductor-Agent-Protocol-Version: 1
Content-Type: application/json

{"expected_sequence":42,"reason":"rolling deploy"}

The server selects the target runtime. Partial model output, running tools, pending input, and reconciliation states must resolve first. The successful upgrade appends an immutable session.runtime_upgraded fact; it never rewrites history.

Retention and residency

Default content retention is 30 days and the content-free tombstone default is 90 days, bounded by tenant policy. Only closed terminal sessions without a live lease or legal hold are swept. The deletion transaction writes a receipt and authorized tombstone before removing content.

Admission separately pins home storage, allowed replicas, provider destinations, artifact/log destinations, and failover policy. Moving compute never silently moves journal data or provider egress.