For the complete documentation index, see llms.txt. This page is also available as Markdown.

Connector Runner

Bidirectional sync with external systems (EHR, FHIR store, CRM): entity resolution, confidence-gated writes, outbound handler registry, and call dispatch.

The connector runner is the bidirectional data pipeline between external systems and the workspace's world model. It polls external systems (EHR platforms, FHIR stores, CRMs), writes events with entity resolution (matching records from different systems to the same real-world entity), syncs agent-created data back to source systems after quality review, dispatches scheduled outbound calls, and runs the automated data quality pipeline.

Inbound data arrives via polling (dispatched by source type: ehr, fhir_store, smart_fhir, rest_api, webhook, file_drop, lakebase_schema) or real-time webhooks (for EHR systems that support FHIR Subscriptions or event notifications). Outbound write-back routes on the workspace's connector type (fhir_store, smart_fhir, athenahealth, charmhealth, eclinicalworks, meditab, hazelhealth, mbp, lakebase_schema) through a handler registry. The epic, cerner, and allscripts connector types exist in the enum but route through the fhir_store and smart_fhir handlers rather than dedicated handlers.

The connector runner has no public-facing API. It operates as a background service. Data sources and sync configuration are managed through the Data Sources endpoints on the Platform API, and its health is visible through the Pipeline Observability endpoints below. For the full architecture narrative - sync design, confidence gating, and review workflow - see the Connectors & EHR conceptual documentation.

Inbound Sync

Data sources feed the world model through two mechanisms:

  • Polling: sources are polled according to their sync strategy. Per-source locking prevents duplicate polling, content-hash deduplication prevents duplicate writes on repeated polls, and each resource-type batch is durable immediately, so partial failures never lose already-written data. Individual record failures are retried on the next poll cycle without blocking other records.

  • Real-time webhooks: EHR systems that support FHIR Subscriptions or event notifications push changes directly. Incoming webhooks are cryptographically verified, deduplicated, and the full resource is fetched and mapped to FHIR before writing to the world model. Subscription lifecycle (creation, renewal, cleanup) is managed per data source.

Both paths converge on the same world model event pipeline with identical entity resolution, enrichment, and confidence handling.

Polling behavior:

Feature
How It Works

Full vs light cycles

Full sync polls all resource types. Light sync polls only high-frequency types using cached reference data

Business hours gate

Polling can be restricted to defined operating hours to respect external API usage patterns

Reference data caching

Frequently-accessed reference data (locations, carrier lists) is reused between polls to reduce external API call volume

Configurable poll cadences

Per-resource poll intervals via poll_cadences in the data source connection config

Entity Resolution

Events arrive with references to external entities (for example, an appointment references a patient by external ID). Entity resolution maps those references to canonical IDs, creates or finds the matching world model entity, links the events, and projects graph relationships - all idempotently.

External Type
Entity Type
Canonical ID Format

Patient

person

{source}:Patient:{id}

Practitioner

person

{source}:Practitioner:{id}

Location

place

{source}:Location:{id}

Appointment

appointment

{source}:Appointment:{id}

Coverage / Encounter

Linked to patient

Via participant references

Slot

Skipped

Marked to prevent re-fetching

When a workspace has multiple data sources, entity resolution automatically detects when entities from different sources represent the same real-world thing. Matched entities are linked and their projected state is unified, so a single patient view reflects data from every connected system.

Entity Type
Match Criteria
Confidence

Patient

Phone number (E.164 normalized)

High

Patient

Email address

High

Patient

Name + date of birth

Moderate

Practitioner

NPI

High

Practitioner

Name + specialty

Moderate

After events are committed, background enrichment runs with zero added latency to the write path: vector embeddings are generated for every event and entity write, and AI-powered enrichment extracts and enhances fields on events that need it.

Outbound Sync

Data captured by the voice agent during calls is gated before syncing to external systems:

  • Source allowlist: only voice_agent, encounter_finalized, and platform_api_mcp (clinical writes made through the MCP server, which must reach the EHR like the voice path) events are eligible for outbound sync. Events from api, outbound_sync_agent, ehr_sync, and connector_runner sources are excluded. This is an allowlist, not a blocklist - new sources must be explicitly added to become eligible.

  • Confidence gate: only events at or above the verified confidence threshold sync on the automatic path. Below-threshold writes never reach external systems automatically. The threshold is enforced independently at every outbound path as defense in depth.

  • Review-gated sinks: a sink can be configured to require human review. When it does, outbound write intents are staged as external write proposals instead of auto-pushing. An operator approves or rejects each proposal through the Review Queue, and approved proposals are then delivered to the sink. Because a human decision is the authority, review-gated sinks capture writes at any confidence; the confidence gate governs only the un-reviewed automatic path. Staging is idempotent, so a redelivered write intent never creates a duplicate proposal or re-proposes an already-decided write.

Write-Back

A workspace can write back to multiple external systems simultaneously (multi-sink). For example, a workspace might sync patient and appointment data to the EHR while syncing patient and contact data to the CRM. Each sink is configured independently with its own outbound_entity_types, and sync progress is tracked per sink. A failure writing to one system does not block writes to others.

Outbound events are routed through a handler registry that maps each sink's connector_type to the correct write-back handler. The registry is the single routing authority for all outbound paths.

Connector Type
Write-Back
Auth

fhir_store

FHIR R4 (ETag optimistic locking)

Managed credentials

smart_fhir

SMART-compliant FHIR R4

SMART Backend Services (RS384/ES384 JWT assertion)

athenahealth

athenahealth EHR adapter (Patient create/update, Appointment book/cancel)

OAuth2 client credentials

charmhealth

Charm EHR adapter

OAuth2 + API key

eclinicalworks

eClinicalWorks EHR adapter

Managed credentials

meditab

Meditab EHR adapter

Managed credentials

hazelhealth

Hazel Health EHR adapter

Managed credentials

mbp

MBP EHR adapter

Managed credentials

lakebase_schema

Workspace database schema adapter

Managed credentials

For approved events, the connector runner translates world model data into the target system's format:

Event Type
What Happens

patient.created

Create patient record in EHR (with AI translation for complex field mapping plus deterministic fallback)

patient.updated

Merge demographics with current EHR record

appointment.booked

Create appointment (patient resolved from entity external IDs)

appointment.confirmed / cancelled

Update appointment status

coverage.created

Create insurance record (carrier fuzzy-matched from EHR carrier list)

Write-back safeguards:

  • Optimistic locking: for FHIR stores, ETag-based locking prevents lost updates. On conflict (412), the write is re-read and retried up to 3 times.

  • Confidence-aware dependencies: when a write depends on another entity (for example, appointment creation requires the patient to exist in the EHR), the dependency check evaluates confidence. A below-threshold dependency fails fast rather than waiting indefinitely on unverified voice data.

  • Duplicate prevention: when the voice agent creates a patient not yet in the target EHR, an autonomous check verifies no duplicates exist before creating the record.

  • Loop prevention: events that originated from EHR sync are always skipped in outbound paths.

Outbound Call Dispatch

The connector runner dispatches outbound calls when scheduled outbound_task entities become due. This implements the execution side of the voice agent's outbound system. For each due task, the runner loads the patient entity from the world model, builds a rich system prompt from the patient projection, resolves the outbound phone number, and dispatches the call - writing an outbound.dispatched or outbound.failed event with the result.

Feature
How It Works

Business hours gate

Per-task timezone-aware window (e.g., 9am-5pm ET). Outside hours, the task waits for the next window

Priority ordering

Tasks dispatched highest-priority first (1-10 scale)

Dispatch locking

Per-entity locking prevents double-dispatch

Retry with backoff

Configurable max attempts and backoff interval. Failed tasks automatically schedule the next attempt

Rich context

Patient projection enriches the system prompt, so the voice agent starts with full patient knowledge

Idempotency

Dispatch keyed by outbound:{entity_id}:{attempt}, safe to retry

Pipeline Observability

The Platform API exposes 10 read-only pipeline observability endpoints under /v1/{workspace_id}/pipeline/ that combine live connector runner state with stored pipeline data. These power the pipeline dashboard in the Developer Console.

Endpoints

Endpoint
Description

GET /v1/{workspace_id}/pipeline/status

Composite pipeline status: overall health, active polls, total events/entities, per-source status, all loop states

GET /v1/{workspace_id}/pipeline/sources

Data sources with live health from recent poll results

GET /v1/{workspace_id}/pipeline/sources/{source_id}/overview

Aggregated overview of a source's pipeline health: event counts by status, last sync time, error summary

GET /v1/{workspace_id}/pipeline/sources/{source_id}/history

Sync history bucketed by time window (1h or 1d) for a specific source

GET /v1/{workspace_id}/pipeline/sources/{source_id}/events

Paginated events for a specific source (sortable by ingested_at, event_type, confidence)

GET /v1/{workspace_id}/pipeline/outbound

Per-sink outbound sync summary: synced/failed/pending counts

GET /v1/{workspace_id}/pipeline/outbound/{data_source_id}/log

Paginated outbound sync log for a specific sink (sortable by created_at, synced_at, attempt_count)

GET /v1/{workspace_id}/pipeline/entity-resolution

Entity resolution metrics: total same-as edges, recent merges (24h), loop status

GET /v1/{workspace_id}/pipeline/review

Review pipeline metrics: queue depth, pending by priority, approved/rejected (7d), average review time

GET /v1/{workspace_id}/pipeline/throughput

Event throughput time series across all sources (configurable date range and interval)

All endpoints require viewer+ permissions and are workspace-scoped.

Health Snapshot

The /v1/{workspace_id}/pipeline/status endpoint returns a composite view:

Field
Description

status

healthy, degraded, starting, or unavailable

connector_runner_status

Live connector runner status (same values)

uptime_seconds

Connector runner uptime

active_polls

Number of sources currently polling

total_events / total_entities

Workspace-level counts

sources

Per-source status with poll metrics, error counts, and connection health

entity_resolution, outbound_dispatch, outbound_subscriber, gap_scanner

Per-component operational state (a component field is null when that component is not running)

Source Health

Each source in the listing includes live health enrichment:

Field
Type
Description

health_status

string

healthy, degraded, or unknown

last_poll.at

ISO timestamp

When the last poll completed

last_poll.duration_ms

integer

Poll duration in milliseconds

last_poll.event_count

integer

Number of events written

last_poll.error

string or null

Error message if the poll failed

Connection health is tracked per source using consecutive error counts. A source is marked degraded after 3+ consecutive poll failures and recovers automatically on the next successful poll.

Live health metrics reflect recent poll activity and reset when the connector runner restarts; stored pipeline data (event counts, sync history, review stats) is unaffected.

Graceful Degradation

If the connector runner is temporarily unavailable, the pipeline endpoints still return stored data (event counts, sync history, review stats, entity resolution metrics). Only live component states and active poll counts are omitted. The dashboard stays functional during connector runner restarts or deployments.

Connector Settings

Connector definitions are managed through workspace settings with typed configuration models. Each connector definition includes:

Field
Description

connector_type

The external system type (maps to the handler registry)

sync_strategy

Sync cadence: continuous, scheduled, manual, or webhook

connection_config

System-specific connection parameters (endpoints, credentials, resource scoping)

poll_cadences

Per-resource type polling intervals

The connector settings endpoint validates sync strategy values with strict type checking, preventing misconfiguration bugs. The data source response includes an is_stale field computed from the connector's last successful sync and its configured cadence. Configuration changes are picked up automatically on the next sync cycle - no restart is needed.

API Reference

Last updated

Was this helpful?