Orchestrators
Orchestrators
The SDK includes four orchestrators that handle the bidirectional flow between bridge and platform. They are created and managed by the Runtime — you typically don't instantiate them directly.
Reconciler
Synchronizes bridge sessions with platform containers. Creates new containers for new sessions, renames existing ones when titles change.
Behavior
- No orphan deletion — if a bridge session disappears, the container is left in place (data preservation)
- Title repair — on startup, fixes containers that still have placeholder titles (e.g.,
claude_abc123...) - Guards against empty titles — rejects rename to empty string
- Configurable title length — truncates to
titleMaxLength(default 128)
sync(sessions)
Called automatically when sessions:list arrives from the bridge.
// For each session:
// 1. Does a container exist in the store?
// No → createContainer() → store.containers.upsert()
// Yes → has title changed? → renameContainer()
// 2. Update status in store
repairTitles()
Called once during startup. Scans all containers and renames any whose title is still the raw conversationId prefix.
BridgeToPlatform
Routes incoming bridge stream events to the platform. This is the most complex orchestrator, handling streaming, tool cards, deduplication, and message mapping.
Event Flow
stream:message_start → create TurnStreamer for conversation
stream:text_delta → streamer.appendDelta(text)
stream:tool_use → finalize streamer → post tool_card (partial)
stream:tool_result → edit tool_card with result
stream:message_complete → finalize streamer with markdown render
stream:result → post result_card (usage, cost)
stream:stopped → post stopped indicator
stream:user_message → dedup check → post user_message_card
session:error → post error_card
session:status → post status indicator
Tool Call Chronological Ordering
When toolCallChronologicalOrdering: true (default), the SDK preserves the visual order of events:
- Text before tool → finalize streamer (commits placeholder)
- Tool card posted after the committed text
- New streamer created for post-tool text
- Text after tool → streamer edits new placeholder
- Message complete → finalize with accumulated text (not full
e.content)
This prevents duplication when a turn contains text → tool → text sequences.
Deduplication
Messages are deduplicated using two mechanisms:
- Message map —
store.messages.hasBridgeMessage(id)checks if a bridge message was already posted - Pending outbound — tracks messages in-flight (POSTed but not yet confirmed) to catch echoes
PlatformToBridge
Implements PlatformHandlers to receive incoming platform events and route them to the bridge.
onMessage
- Resolve
containerId→conversationIdvia store - Download attached files → upload to bridge API
- POST message to bridge with sender info
- Register pending outbound token for dedup
- Store message mapping
onContainerClosed
Configurable behavior:
'delete-session'(default) — callsbridgeApi.deleteSession()'leave-room'— leaves the WebSocket room'noop'— ignores the event
onContainerRenamed
- Checks echo guard (was this rename triggered by the SDK itself?)
- If not echo → calls
bridgeApi.updateSessionTitle() - If
propagateRenames: false→ ignores all renames
Replayer
Replays historical messages from the bridge into platform containers on startup.
Behavior
- For each session with a container:
- Fetch messages from bridge API (
getMessages) - Skip messages already in message map
- Render each message → post to container
- Record in message map
- Fetch messages from bridge API (
Configuration
interface ReplayerConfig {
limitPerSession: number // default: 50
skipIfNoContainer: boolean // default: true
}
skipReplay: true in AdapterConfig during development to speed up startup.