Integrations (experimental)
This opt-in feature runs on workflows.
An integration keeps one source system in step with one graph. You connect a source with its credential or a developer-owned app. LBB fits the source to your ontology and runs every sync. A sync reads the source page by page and writes records under stable keys. Depending on the connector, later syncs read incremental changes or repeat bounded source passes.
What you get
Section titled “What you get”- Your classes. Each stream of the source maps to a class of your
ontology when one fits. A match is by name, by a common synonym, or by the
connector’s class hint. HubSpot contacts and Linear users both land in
Person. One SPARQL query overPersonfinds both. - A starter ontology. Each connector maps onto the starter of its
domain: HubSpot onto CRM, Linear and GitHub onto Work management, SharePoint,
Google Drive and Notion onto Documents. What your ontology lacks is proposed under the starter’s names,
such as
Deal,annual_revenueandWORKS_AT, with the starter’s parent classes and relation rules. Two CRMs land in the same terms. - Noise set aside. A field the source hides, computes or keeps for
itself (HubSpot’s
hs_properties), a field that repeats the record’s name or a link, and a field no record fills get no property. A suggestion counts them: “It sets 23 fields aside: 12 internal, 8 calculated and 3 hidden.” - Fields and references. Each field maps to a property of the same value type. Each reference maps to a relation.
- One suggestion per class. What does not fit becomes a suggestion: “Add class Deal”, or “Add 3 properties to Organization”. The starter’s properties come first, then the source’s own fields, the best filled first. Each suggestion shows sample records and the fill rate of the new fields. It shows the record count when the source reports one. LBB counts the fill rates itself; no record value leaves it for that.
- Data that waits. Streams that fit sync at once. A stream without a class waits, and so does a field without a property. After you accept a suggestion, the next sync reads the waiting records in full. Each record is written once.
- New fields on synced records. Accept a suggestion that adds fields to a stream that already synced. The next sync reads only those fields from the source. It adds them to the records it wrote and keeps their other values. Any other change to what a stream writes reads the stream again in full.
- Stable keys. A record is keyed by connection, stream and source id. A re-read updates the same entity. Source relationship and property clearing is not fully reconciled for the new provider-app readers.
- Deletes. Supported explicit deletion signals retract source entities. Coverage and retention bounds depend on the connector; missing records in incomplete listings do not establish deletion. See the provider-app limits.
- Only changes are written. LBB keeps a short hash of what each record wrote. A record that writes the same again is left out. A sync with no change at the source writes nothing to the graph. The changed records of one sync step go in one write.
- Crash safety. Each step reads one page of every stream still to read, as one checkpointed workflow step. A crash repeats at most the unfinished step.
On an empty graph, the first integration’s suggestions are the first draft of
your ontology. Accept HubSpot’s, and the graph has Organization, Person,
User, Deal, Team, Pipeline and Stage. Linear then maps its teams
into Team and its workflow states into Stage. It suggests only what is
new, such as Issue, Project and Comment.
Connectors
Section titled “Connectors”Notion, GitHub and Slack use your company’s registered provider apps in hosted LBB. This flow is separately opt-in and sends customers through provider consent and explicit resource selection. Open Integrations → Provider apps to set up an app, then create customer links from your backend. See Offer Notion, GitHub and Slack in your product for setup, scopes, readers and current limits. Provider approval and live app acceptance are not established by LBB’s fixture tests.
The following connectors use credential entry:
| Connector | Streams | Starter classes | Credential |
|---|---|---|---|
| Linear | teams, users, projects, issues, comments, workflows and their states, labels, cycles, project milestones | Work management: Team, User, Project, Issue, Comment, Pipeline, Stage, Tag, Iteration, Milestone | A personal API key (lin_api_…), from Linear under Settings, Security & access |
| HubSpot | companies, contacts, deals, owners and their teams, deal pipelines and stages; tickets when you turn them on | CRM: Organization, Person, Deal, User, Team, Pipeline, Stage, Ticket | A private app token with read scopes for companies, contacts, deals and owners, plus tickets for tickets, from HubSpot under Settings, Integrations, Private apps |
| SharePoint | sites, document libraries, documents with text from Office and text files | Documents: Site, Library, Document, User | The tenant id, client id and a client secret of a Microsoft Entra app registration with Sites.Selected and read access to each site |
| Google Drive | My Drive and shared drives, folders, files with text from Google Docs, Sheets, Slides, Office and text files, and who each file is shared with | Documents: Library, Folder, Document, User | An OAuth client id, client secret and refresh token with the drive.readonly scope, or the JSON key of a service account that the folders are shared with |
A deal links to its stage, a stage to its pipeline, an issue to its state, labels, cycle and milestone, and a document to its library. A HubSpot token that may not read the deal pipelines syncs the deals without their stages. SharePoint also reads each library’s columns and content types as a description of the documents. They show in the fit, and their values are not synced.
LBB stores a credential sealed, bound to its environment, graph and connection. No answer from LBB shows it again, the console’s included.
Google Drive links each file to its folder and drive. It writes acl from
the file’s sharing. Each entry is user:<email>, group:<email>,
domain:<domain> or anyone. A file the account may not share has no
acl. The Folders
setting limits a sync to some folders or shared drives. A file moved out of
them is removed from the graph at the next sync.
Google Docs and Slides sync as plain text. Sheets sync as CSV of the first sheet. Google exports at most 10 MB of a file. PDF and image files keep their metadata without text.
SharePoint and Google Drive read the text of files up to a size limit. The limit is 20 MB by
default and 50 MB at most; a higher setting counts as 50 MB. Files larger
than the limit are kept without their text, with text_status set to
too_large. An Office file whose contents unpack to more than four times the
limit (64 MiB at most) is kept the same way. A document keeps the first
100,000 characters of its text.
Upload a file
Section titled “Upload a file”File upload is the first card on Sources → Integrations. It works on every plan, also where the connectors are off. Choose Upload, then paste or choose a Turtle, N-Triples or NDJSON file. It goes into the selected graph, and a graph that does not exist yet is created. For files in code, see Load data.
Connect a source
Section titled “Connect a source”Open Sources → Integrations in the console and choose Connect on a credential-based connector. Notion, GitHub and Slack cards instead open provider app setup; their customers use the hosted consent flow. The credential dialog has three steps.
-
Credentials. Paste the credential. The help under each field says where to create it. Choose the connector settings (for example the HubSpot objects or the SharePoint sites) and a schedule.
-
Ontology. The step shows at once which starter the connector maps onto. For example: “SharePoint maps onto the Documents starter: sites, libraries, documents and people.” For each starter class, choose:
- Use your class, for example
Customerfor HubSpot companies. - Add class, under the starter’s name or one you type.
- Skip, to leave the stream out.
The starter properties and relations show under each class. In the background, LBB checks the fit against your ontology with its models. When that check answers, the step updates in place. A match then shows its score, or “model · 88%” when the fit model picked it. You do not need to wait for it. If the check waits behind another connection, the step says which one. For example: “The fit check starts after HubSpot’s fit (about 8 min).” If the check fails, for example on a rejected credential, the step shows the error with Retry and Update credentials. A check with no progress for 3 minutes shows Retry.
- Use your class, for example
-
Start. You can select Start as soon as the credentials step is done. LBB queues the first sync and runs every scheduled one. Anything new that the fit finds arrives as suggestions. If you close the dialog instead, the connection stays. Start its first sync from its card.
You can connect several sources one after another. Nothing in the dialog waits for another connection.
By default, new classes and properties wait for your review in Review. The streams that fit sync at once. Choose Apply the ontology now in the Ontology step to add them before the first sync.
The card of a connection shows its state, and a line on what runs now. For example: “Claude is drafting new terms (4 of 12) · about 8 min left”.
| State | Meaning |
|---|---|
| Queued | The next turn starts after another connection’s turn. The card names it, for example “Starts after HubSpot’s fit (about 8 min)”. |
| Starting… | LBB is picking up the next sync or check. |
| Syncing | A sync runs, with its progress. |
| Up to date | The last sync finished. |
| Waiting for review | A stream waits for an ontology change you have not accepted. |
| Needs attention | A turn failed, for example on a rejected credential. Retry or Skip it. |
| Storage full | The graph refused an import because the Free plan’s 30 GiB is used. Delete data or upgrade to Cloud, then Retry the turn. |
| Delayed | LBB has not picked the turn up for five minutes. It retries by itself. |
| Paused | Nothing syncs until you resume. |
The card also counts what the connection wrote:
- Written: the records written over all syncs, the running sync included. A record counts again each time it changes.
- Last sync: when the last sync finished, and its records. While a sync runs, it shows Running and the records written so far.
- Streams: the same counts for each stream. They add up to Written.
During the first sync, the three numbers are the same. A sync that starts while another one runs joins it. It continues from where that sync is. A full resync starts again from the first record.
Manage a connection
Section titled “Manage a connection”The menu on a connection’s card has:
- Sync now and Full resync. A full resync reads every record again and writes it, changed or not.
- Edit schedule…: manual, hourly, daily, or every N minutes.
- Ontology mode: review changes first, or apply them automatically.
- Update credentials…: paste a new credential. LBB checks it against the source.
- Edit settings…: the connector settings you chose on connect.
- Pause and Resume.
- Remove…: type the connection id to confirm. LBB stops syncing and deletes the connection with its stored credential. The records it wrote stay in the graph.
A change to the schedule, the mode, the settings or the credential applies within a minute. Open a connection to see its Fit tab: each stream against the class it maps to, each field against a property, and what waits for review. Change a class, a property or a relation there, and LBB checks the fit again.
Query the result with SPARQL:
PREFIX p: <https://littlebigbrain.com/p/>PREFIX r: <https://littlebigbrain.com/r/>PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>SELECT ?issue ?team WHERE { ?i p:priority_label "Urgent" ; r:in_team ?t ; rdfs:label ?issue . ?t rdfs:label ?team .}Review ontology changes
Section titled “Review ontology changes”By default, an integration files its suggestions and syncs what already fits. Open Review in the console. There you read a change, discuss it, and edit it. Then you accept or dismiss it.
Your edits carry over. Rename a class or a property, and the integration uses your name. Remove a property, and the integration leaves that field out.
An accept queues a sync. Until it runs, the stream shows accepted · syncs next. A failed sync holds everything after it. Retry or skip it first.
A dismissed suggestion keeps its stream waiting. The graph refuses a change that would narrow or remove what it holds. A source can only add to your ontology.
Link the same thing across sources
Section titled “Link the same thing across sources”HubSpot contacts and Linear users both land in Person, so Ada can exist
twice: once from each source. After a sync, the integration compares its
records with those of the other connections in the same class. It matches
on an email property, or on website, domain or url. Emails compare
lowercase and trimmed. Web addresses also drop the scheme, www. and a
trailing /.
The matches arrive as one suggestion per class and pair of connections, for
example “12 people appear in both HubSpot and Linear”. In Knowledge graph →
Suggestions you see each group of records with its sources and the value
they share. Edit, then accept lets you leave out a group, or a record of
a larger group. Accept, and the graph links each group with SAME_AS
edges. Follow them in SPARQL to read a person’s records together.
The comparison runs as SPARQL inside your graph. No record value leaves it.
Map a source yourself
Section titled “Map a source yourself”A connection’s mapping binds streams, fields and references to terms you choose. It holds only what differs from the match:
{ "type": "configure", "mapping": { "companies": { "class": "Organization", "fields": { "domain": "website", "hs_lead_status": null } }, "owners": { "class": null } }}"class": null ignores a stream. A field or reference set to null is left
out. A class that does not exist yet is suggested under the name you give.
Send the mapping as a configure message to the connection’s workflow. The
Ontology step and the Fit tab send the same message.
Let a model match the rest
Section titled “Let a model match the rest”Names do not match everything. HubSpot’s domain field means the same as
a website property, and no rule of names says so. TypeSafe’s Jev model
answers what the names leave open: the class of a stream, and the property
of a field. It never answers for a stream or field you mapped yourself.
LBB runs the fit model and pays for it. You choose no model and bring no key. Where the environment has no TypeSafe key, fit uses names and synonyms only. The console’s Models page lists Jev as a decision model. It shows how many decisions Jev made this month.
Only schema text leaves LBB. That is the source label, the stream and field names, labels and value types, and your ontology’s class and property names. Record values never leave it.
An answer at the confidence threshold or above maps at once. The threshold is 0.7. The Fit tab shows it as “model · 87%”. A lower answer shows as “Model suggests website · 62%”, with a Use button. Each question is asked once; the answer is kept with the integration.
Let a model propose what your ontology lacks
Section titled “Let a model propose what your ontology lacks”Your own fields often have no place in the starter. A renewal date or a customer tier is one. In the hosted console, Claude Sonnet 5.5 proposes the smallest set of terms that holds them. Jev maps the fields it can to your terms. It sets internal fields aside and checks each proposed change.
The fit model reads the source before the first sync. It reads it again when the source’s fields change. A run takes a few minutes. Meanwhile the Fit tab shows the step it is on, for example “Claude is drafting new terms (4 of 12)”. A fit check you start then runs after the fit model.
Its changes arrive in Review, one per class. An example is “Extend Organization: 9 properties, 1 relation”. A new class gets its own suggestion.
In automatic mode, a change applies by itself only when Jev supports it well and a dry run passes. Every other change waits for your review. Accepted changes start syncing the fields they hold.
The Fit tab shows each class’s changes and where they stand. It also lists the fields the model left out, with the reason for each. A field the model left out is not synced.
The models see the schema and statistics LBB computes: fill rate, distinct values and the longest value. They never see a record value.
Run the worker yourself
Section titled “Run the worker yourself”The self-run worker is for self-hosted servers, where LBB does not hold source credentials. You run it from a checkout of the repository, with the credentials in its environment. The console lists the connections it serves.
Start a data plane with workflows enabled (see the workflows guide). Then build the worker in the checkout:
npm cinpm run build -w @littlebigbrain/client -w @littlebigbrain/integrationsSet the variables and run it:
export LBB_URL=http://127.0.0.1:7400 LBB_API_KEY=lbb_sk_test_local LBB_GRAPH=mainexport LINEAR_API_KEY=lin_api_...
node sdk/integrations/dist/cli.js preview linear # how the source fits your ontology; writes nothingnode sdk/integrations/dist/cli.js add linear-main linear --every 1hnode sdk/integrations/dist/cli.js worker # runs syncs until you stop itnode sdk/integrations/dist/cli.js fit linear-main # each stream against its classThe worker reads these variables:
| Connector | Variables |
|---|---|
| Linear | LINEAR_API_KEY |
| HubSpot | HUBSPOT_TOKEN |
| SharePoint | SHAREPOINT_TENANT_ID, SHAREPOINT_CLIENT_ID, SHAREPOINT_CLIENT_SECRET |
| Google Drive | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REFRESH_TOKEN, or GOOGLE_SERVICE_ACCOUNT_KEY with an optional GOOGLE_DELEGATED_USER |
A connection-scoped variable (<CONNECTION_ID>_<VARIABLE>) wins over the
plain one. One worker can then serve two accounts of the same system. Set
JEV_API_KEY for the fit model, LBB_FIT_MODEL=off to turn it off, and
LBB_FIT_MODEL_THRESHOLD to change the 0.7.
The worker runs the work of up to four connections at once. A new connection’s fit does not wait for another connection’s sync. The steps of one connection always run in order.
A connection’s workflow type is sdk.integration (lbb.integration before
2026-10-13). The worker claims both names until no connection of the old
name is left. Build it from a checkout of 2026-10-13 or later before your
server moves its connections (database/scripts/workflow-retype.py): an
older worker claims only the old name and stops finding work. A self-hosted
server moves them, then sets LBB_RESERVED_WORKFLOW_TYPES=all, as in the
workflows guide.
fit prints one row per stream. A row shows the stream’s records and its
class with the match score, or “new class Issue”. It counts the fields that
map, are new, or are ignored. The last column says if the stream syncs or
waits.
Review suggestions from the command line:
node sdk/integrations/dist/cli.js suggestions hubspot-main # this integration's suggestionsnode sdk/integrations/dist/cli.js suggestions accept <id> --sync # accept one, then syncnode sdk/integrations/dist/cli.js suggestions dismiss <id> --reason "We track deals elsewhere"node sdk/integrations/dist/cli.js apply hubspot-main # accept them all, then syncnode sdk/integrations/dist/cli.js resolve hubspot-main # compare records across sources nowTo apply every change without review, add --auto:
node sdk/integrations/dist/cli.js add hubspot-main hubspot --autoExperimental PostgreSQL CDC controls
Section titled “Experimental PostgreSQL CDC controls”PostgreSQL CDC uses a separate workflow and a dedicated source reader. It is
still under development and is disabled by default. Authenticated discovery,
mapping approval and the gated console setup flow are implemented.
Its console entry points share the integrations feature flag with the other
connectors; backend CDC capability gates still apply independently.
Open PostgreSQL CDC in the sidebar, next to Integrations. Saved PostgreSQL
connections also appear at the top of Integrations; choose View sync to
open a source and its customer graphs. These links remain available even when
the selected graph’s workflow status cannot load, including before a first
destination graph exists.
For an active sync, PostgreSQL streams committed changes from its write-ahead
log. Each captured batch wakes the graph workflow; a 30-second recovery check
repairs missed notifications. Query visibility follows publication, so click
Run again to refresh existing query results.
Operators must approve the truth-format
rollout before activating a source; enabling API routes alone is insufficient.
Managed Models now propose customer ownership and ontology fit from schema metadata. Source discovery and the guided console work without a destination graph. A reviewed source can feed multiple isolated customer graphs; adopting existing populated destinations is not supported. A model proposal or review does not activate replication. After a SaaS host restart, unfinished proposals resume automatically if their source, ontology, Models policy and decisions are unchanged. Failed attempts need an explicit retry. Recovery does not review a draft or start replication.
For a disposable local end-to-end test, a source checkout includes
database/scripts/cdc-acceptance.py. With the local server, SDKs, SaaS API and
reader image built, run:
python3 database/scripts/cdc-acceptance.py --supervised \ --image lbb-cdc-reader:local \ --interactive-ready-file /tmp/lbb-cdc-playground.jsonThe harness verifies real insert/update/delete publication, then stays running.
The JSON file contains PostgreSQL connection settings, a ready-to-use psql
command, and the LBB endpoint and query. Point a development console at that
endpoint, edit public.items, and rerun Query to see changes. This maps
id, title and body into one graph; customer routing and model-assisted setup
are separate. No provider keys are needed. Ctrl-C cleans up this fixture and its
temporary data. The one-second recovery check is for this local test.
For a bounded bulk test against that running fixture:
python3 database/scripts/cdc-playground-bulk.py \ --playground /tmp/lbb-cdc-playground.json --rows 500 --batch 50 \ --report /tmp/lbb-cdc-bulk-result.jsonThis inserts 500 new rows, updates 250 and deletes 100, leaving 400 for inspection. It also checks rollback isolation. Each phase verifies the exact published values; your pre-existing rows remain untouched. Click Run in Query to refresh results.
In an enabled hosted environment, choose Add connection → PostgreSQL or
Connect on its Integrations catalog card. Setup walks through
Connect → Tables → Review → Preview. Enter credentials and an explicit list of
schema.table names, then Check source. Port and private CA settings are
under Advanced connection settings; publication and slot names are under
Replication settings. The publication must match the table list.
Choose an existing ontology template or start from the tables, then Suggest setup. Review the proposed customer boundary and expandable table mappings, answer any questions, and Save reviewed draft. Choose a graph prefix and customer limit, then Preview customer graphs. Preview reads the source to check ownership without creating destination graphs. Start syncing approves creation of the customer graphs with the reviewed ontology; subsequent customers get a graph up to that limit. The connection list is scoped to the environment, independent of the selected graph. A saved plan remembers its ontology template. Table mappings and Model details expand when needed; field exclusions remain visible for review.
If a field’s type cannot be fitted, open Field exclusions and explicitly
select any fields to leave out, then Revise proposal. Exact PostgreSQL
numeric values are currently one such type. Exclusions stay visible when you
reopen the draft. Removing an exclusion requires another proposal; unsent edits
must be resolved before you can save a review. No values are silently converted.
Graph syncs retains the earlier single-target foundation controls for the selected graph. Its approval/start path remains separate and release-gated. The status card follows PostgreSQL → Graph → Queries, showing where changes are waiting. Pause updates keeps capturing source changes while graph updates are paused; Resume updates wakes that backlog. Capture controls and retirement are in More actions, and counters are under Sync details. Source risks and active alerts stay visible.
For an already approved binding on a deployment that enables the CDC integration API, use a stack API key with the TypeScript or Python SDK:
const status = await client.integrations.cdcStatus("postgres", { graph: "orders" });const requested = await client.integrations.cdcControl("postgres", { graph: "orders", operationId: "maintenance-1", action: "pause_capture",});Python uses cdc_status and cdc_control, with operation_id. Status separates
captured, applied and published progress. Only published data is ready for
queries. A source-health sample expires after 60 seconds; an unknown source is
not reported as streaming simply because its last captured work was applied.
Controls are pause_capture, resume_capture, pause_apply, resume_apply and
retire. Reuse the same operation id after a lost response. A pending result
is durable intent; status reports when it becomes applied or failed.
applied confirms the mode change; reader health separately reports shutdown.
Retirement requires confirm equal to the connection id, preserves captured and
graph data, and never drops a PostgreSQL replication slot. An interrupted initial
snapshot cannot resume through this control; it requires an explicit rebuild.
On a deployment with the CDC API enabled and an explicit source sealing key,
client.integrations.cdcDiscover creates a sealed discovery job for an existing
graph. Supply jobId, expectedRevision: 0, the source host/port/database/
publication/slot, an explicit list of tables, and credentials. Keep the same job
id, settings and credentials after a lost response. cdcDiscovery reads progress
and the verified catalog; cdcCancelDiscovery requires the job id, graph epoch
and revision from that response. Python exposes cdc_discover, cdc_discovery
and cdc_cancel_discovery on both sync and async clients.
The dedicated host connects to PostgreSQL over verified TLS. Source credentials and sealed values never appear in status. Discovery does not activate capture; it prepares the schema for mapping review. CDC connection and job ids accept letters, digits, underscores and hyphens. Developer creation limits apply, while an exact retry of an existing job spends no additional creation.
The connection view separates captured, applied and published progress from source health. Fresh source checks show slot activity and retained/unconfirmed WAL bytes; these are byte distances, not elapsed lag or available disk space. Unknown values remain unknown. Per-table initial-snapshot counts describe rows durably captured and may be unavailable after reader restore. Paused and retired readers stop probing PostgreSQL, so continue monitoring the source slot directly.
The optional reader resource view shows sampled process CPU time, container current/peak memory and JVM heap use. Unknown measurements remain unknown; lifetime counters reset when the reader restarts. These operating samples are not billing quantities. The connector uses existing storage and completed-work metering and does not add row pricing.
The connection view also shows active capacity, source/WAL and application-stall conditions plus the latest 32 alert/recovery notices. Notices appear once per transition and survive host restart. Muting suppresses new notices while keeping active conditions visible; unmuting does not replay missed notices. A stale evaluation is explicitly marked, and missing source evidence is not recovery. External notification channels are not part of this experimental release.
await client.integrations.cdcMuteAlerts("postgres", { graph: "orders", expectedRevision: status.alerts!.settings_revision, muted: true,});After a lost response, retry the same body. Python uses cdc_mute_alerts with
expected_revision on both sync and async clients. A settings conflict requires
reading the current revision before choosing a new preference.
Limits
Section titled “Limits”- Polling connectors use the property-graph write model. A graph first written with RDF refuses the import route. The sync then fails with that reason.
- A many-valued reference (HubSpot associations, project teams) only adds edges. An association removed at the source stays in the graph.
- Properties are graph-wide. A field name can exist with another value type.
The field is then suggested with the class as a prefix, as in
deal_amount. - A suggestion holds at most 64 changes. A class that needs more gets the rest in its next suggestion, the least filled fields last.