Skip to content

How The Local Read Database Works

The Daeda AI Automation Suite keeps a local read database for each connected HubSpot portal (via the @daeda/mcp-pro client).

That database is DuckDB.

It lives on your machine.

The local mirror is not one single data source.

It is made from two different systems:

  1. Artifact-backed data
  2. Lightweight plugin-backed data

This distinction is very important.

Data typeFreshness rule
Artifact-backed dataUsually handled automatically for normal reads
Lightweight plugin-backed dataNot automatically current; refresh it yourself when current values matter

Each connected portal gets its own local folder.

FilePurpose
hubspot.duckdbMain writable DuckDB database
hubspot.replica.duckdbPublished read replica for safe reads
portal_data.jsonLocal artifact and plugin sync state

Artifact-backed data is the main CRM mirror.

It comes from full exports, stored snapshots, and automated follow-up sync flows.

KindExamples
CRM object tablescontacts, companies, deals, tickets, custom object tables, and other enabled object tables
Shared association tableassociations
Artifact-backed metadataassociation_schema, workflows
StepWhat happens
1The server decides which artifacts exist for the portal
2The client requests the latest artifact inventory
3The client downloads missing or changed artifacts
4It loads those artifacts into the local DuckDB database
5It runs catch-up diff logic and selected-portal watch behaviour

What Counts As Lightweight Plugin-Backed Data

Section titled “What Counts As Lightweight Plugin-Backed Data”

Plugins are small metadata sync jobs.

They populate metadata tables that do not ride on the main artifact flow.

These tables are useful, but they are not treated as live real-time data.

Plugin nameLocal table or tables
property-definitionsproperty_definitions, property_groups, property_definition_object_state
pipelinespipelines, pipeline_stages
ownersowners
portal-infoportal_info
action-type-catalogaction_type_catalog
workflow-enrollment-triggersworkflow_enrollment_triggers, workflow_event_types
listslists
sequencessequences, sequence_steps
communication-subscriptionscommunication_subscription_definitions
conversation-inboxesconversation_inboxes, conversation_channels, conversation_channel_accounts
formsforms, form_fields
user-teams-permissionsprovisioning_users, provisioning_teams, provisioning_roles

These plugin names exist in the codebase, but they are currently disabled and not part of the normal active sync surface.

Disabled pluginTable
snippetssnippets
email-templatesemail_templates
account-settingsaccount_settings
record-viewsrecord_views

The Automation Suite client does not keep lightweight plugin tables continuously current.

It can auto-skip plugin sync when data looks fresh enough.

The built-in freshness window is 24 hours.

That means plugin tables can be correct enough for many tasks, but still not current enough for operational work.

Which System Should You Trust For Freshness

Section titled “Which System Should You Trust For Freshness”
NeedWhat to trust
CRM records and associationsArtifact-backed local mirror
Workflow snapshot plus selected-portal workflow deltasArtifact-backed workflows table
Lists, owners, pipelines, forms, inboxes, sequences, and similar metadataPlugin freshness in status(section="schema")

The selected portal gets the strongest freshness behaviour.

Data typeBehaviour
CRM object recordsCatch-up diff plus live watch behaviour
AssociationsUpdated through the same diff/watch path
WorkflowsSnapshot artifact plus selected-portal workflow delta messages
Plugin-backed metadataStill manual refresh when current values matter

Non-selected portals do not get the same live behaviour as the selected portal.

Reads can still use the local mirror.

For enabled portals, the client can wait for artifact queue work to drain before reading.

That helps artifact freshness.

It does not make plugin metadata current.

If portal sync is disabled, the Automation Suite only uses stale local data for that portal.

If no local database exists yet, reads fail.

Use this model:

QuestionAnswer
Is this table a CRM object table, associations, association_schema, or workflows?Treat it as artifact-backed
Is this table owned by a named lightweight plugin such as lists or owners?Treat it as plugin-backed and manually refresh when needed

Always use:

status(section="schema")

This is the authoritative freshness view.

What To Look For In status(section="schema")

Section titled “What To Look For In status(section="schema")”
FieldMeaning
lightweightPlugins.<plugin>.statusPlugin state such as NOT_STARTED, SYNCED, or FAILED
lightweightPlugins.<plugin>.lastRefreshedAtReplica-backed last refresh time
lightweightPlugins.<plugin>.ageSecondsAge of that plugin data
refreshJobsActive and recent plugin refresh jobs

Run refresh_plugins before any task that depends on current plugin-backed metadata.

If you need current…Refresh these plugins first
ownersowners
deal or ticket pipelinespipelines
listslists
workflow trigger catalogworkflow-enrollment-triggers
supported workflow action metadataaction-type-catalog
formsforms
inboxes and channelsconversation-inboxes
sequencessequences
communication subscription definitionscommunication-subscriptions
provisioning users, teams, and rolesuser-teams-permissions

If a task needs several of these, refresh them together in one call.

StepAction
1Call status(section="schema")
2Decide which plugin-backed metadata you need
3Call refresh_plugins(pluginNames=[...])
4Poll status(section="schema") again
5Wait until the matching refresh job is COMPLETED
6Also confirm the plugin lastRefreshedAt values have advanced
7Only then run query, chart, or plan-building work that depends on those tables

COMPLETED does not just mean the remote work finished.

It means the writable client has also published and verified the updated read replica.

That is why status(section="schema") is the real gate.

StateMeaning
QUEUEDJob created but not started
RUNNINGRefresh logic is executing
REPLICATINGThe local read replica is being published and verified
COMPLETEDRefresh finished and the replica is verified
FAILEDRefresh failed; use the error message
QuestionWhy
Which deals are in closedwon?CRM object data
Which contacts belong to which companies?CRM object data plus associations
How many workflows are enabled?Artifact-backed workflows table
QuestionWhy
Which owners exist today?owners is plugin-backed
What are the current deal stage IDs?pipelines is plugin-backed
What is the latest list ID for a static list?lists is plugin-backed
What forms exist right now?forms is plugin-backed
NuanceWhat it means
workflows is not a plugin tableIt is artifact-backed
property-definitions is a pluginRefresh it manually when schema freshness matters
Read-only MCP clients can still serve readsThey use the published local replica
Plugin refresh can be relayedA read-only client can request refresh through the writable master client

Use this rule before every serious query:

If your task depends on…Do this
CRM records onlystatus(section="schema"), then query
CRM records plus plugin metadatastatus(section="schema"), then refresh_plugins, then wait for replica-verified completion, then query

Troubleshooting