How The Read Database Works
The Daeda AI Automation Suite keeps a synced read database for each connected HubSpot portal, hosted by Daeda’s managed database service and reached through the @daeda/mcp-pro client.
The database engine is DuckDB, so your SQL can use DuckDB functions like json_extract_string.
The synced mirror is not one single data source.
It is made from two different systems:
- Artifact-backed data
- Lightweight plugin-backed data
This distinction is very important.
The Simple Rule
Section titled “The Simple Rule”| Data type | Freshness rule |
|---|---|
| Artifact-backed data | Usually handled automatically for normal reads |
| Lightweight plugin-backed data | Not automatically current; refresh it yourself when current values matter |
Where Your Data Lives
Section titled “Where Your Data Lives”Each connected portal has an isolated database inside Daeda’s managed database service. Your MCP client authenticates with your license key and routes queries at the portal you have selected.
What Counts As Artifact-Backed Data
Section titled “What Counts As Artifact-Backed Data”Artifact-backed data is the main CRM mirror.
It comes from full exports, stored snapshots, and automated follow-up sync flows.
Artifact-Backed Tables
Section titled “Artifact-Backed Tables”| Kind | Examples |
|---|---|
| CRM object tables | contacts, companies, deals, tickets, custom object tables, and other enabled object tables |
| Shared association table | associations |
| Artifact-backed metadata | association_schema, workflows |
How Artifact-Backed Data Arrives
Section titled “How Artifact-Backed Data Arrives”| Step | What happens |
|---|---|
| 1 | The server decides which artifacts exist for the portal |
| 2 | The client requests the latest artifact inventory |
| 3 | The client downloads missing or changed artifacts |
| 4 | It loads those artifacts into the portal’s database |
| 5 | It 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.
Active Lightweight Plugin Tables
Section titled “Active Lightweight Plugin Tables”| Plugin name | Synced table or tables |
|---|---|
property-definitions | property_definitions, property_groups, property_definition_object_state |
pipelines | pipelines, pipeline_stages |
owners | owners |
portal-info | portal_info |
action-type-catalog | action_type_catalog |
workflow-enrollment-triggers | workflow_enrollment_triggers, workflow_event_types |
lists | lists |
sequences | sequences, sequence_steps |
communication-subscriptions | communication_subscription_definitions |
conversation-inboxes | conversation_inboxes, conversation_channels, conversation_channel_accounts |
forms | forms, form_fields |
user-teams-permissions | provisioning_users, provisioning_teams, provisioning_roles |
Disabled Bridge-Backed Plugins
Section titled “Disabled Bridge-Backed Plugins”These plugin names exist in the codebase, but they are currently disabled and not part of the normal active sync surface.
| Disabled plugin | Table |
|---|---|
snippets | snippets |
email-templates | email_templates |
account-settings | account_settings |
record-views | record_views |
Why Plugins Need Manual Refresh
Section titled “Why Plugins Need Manual Refresh”The Automation Suite 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”| Need | What to trust |
|---|---|
| CRM records and associations | Artifact-backed synced tables |
| Workflow snapshot plus selected-portal workflow deltas | Artifact-backed workflows table |
| Lists, owners, pipelines, forms, inboxes, sequences, and similar metadata | Plugin freshness in status(section="schema") |
Real-Time And Near-Real-Time Behaviour
Section titled “Real-Time And Near-Real-Time Behaviour”Selected Portal
Section titled “Selected Portal”The selected portal gets the strongest freshness behaviour.
| Data type | Behaviour |
|---|---|
| CRM object records | Catch-up diff plus live watch behaviour |
| Associations | Updated through the same diff/watch path |
| Workflows | Snapshot artifact plus selected-portal workflow delta messages |
| Plugin-backed metadata | Still manual refresh when current values matter |
Non-Selected Enabled Portals
Section titled “Non-Selected Enabled Portals”Non-selected portals do not get the same live behaviour as the selected portal.
Reads can still use whatever is already synced.
For enabled portals, the service can wait for artifact queue work to drain before serving reads.
That helps artifact freshness.
It does not make plugin metadata current.
Disabled Portals
Section titled “Disabled Portals”If portal sync is disabled, the Automation Suite only serves whatever data is already synced for that portal.
If no data has been synced yet, reads fail.
The Main Mental Model
Section titled “The Main Mental Model”Use this model:
| Question | Answer |
|---|---|
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 |
How To Check Freshness
Section titled “How To Check Freshness”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")”| Field | Meaning |
|---|---|
lightweightPlugins.<plugin>.status | Plugin state such as NOT_STARTED, SYNCED, or FAILED |
lightweightPlugins.<plugin>.lastRefreshedAt | Last refresh time for that plugin |
lightweightPlugins.<plugin>.ageSeconds | Age of that plugin data |
refreshJobs | Active and recent plugin refresh jobs |
When You Must Run refresh_plugins
Section titled “When You Must Run refresh_plugins”Run refresh_plugins before any task that depends on current plugin-backed metadata.
Common Cases
Section titled “Common Cases”| If you need current… | Refresh these plugins first |
|---|---|
| owners | owners |
| deal or ticket pipelines | pipelines |
| lists | lists |
| workflow trigger catalog | workflow-enrollment-triggers |
| supported workflow action metadata | action-type-catalog |
| forms | forms |
| inboxes and channels | conversation-inboxes |
| sequences | sequences |
| communication subscription definitions | communication-subscriptions |
| provisioning users, teams, and roles | user-teams-permissions |
If a task needs several of these, refresh them together in one call.
The Correct Refresh Workflow
Section titled “The Correct Refresh Workflow”| Step | Action |
|---|---|
| 1 | Call status(section="schema") |
| 2 | Decide which plugin-backed metadata you need |
| 3 | Call refresh_plugins(pluginNames=[...]) |
| 4 | Poll status(section="schema") again |
| 5 | Wait until the matching refresh job is COMPLETED |
| 6 | Also confirm the plugin lastRefreshedAt values have advanced |
| 7 | Only then run query, chart, or plan-building work that depends on those tables |
Why COMPLETED Matters
Section titled “Why COMPLETED Matters”COMPLETED means the refresh finished and the new values are queryable. That is why status(section="schema") is the real gate before you run a query that depends on freshly refreshed plugin data.
Refresh Job States
Section titled “Refresh Job States”| State | Meaning |
|---|---|
QUEUED | Job created but not started |
RUNNING | Refresh logic is executing |
COMPLETED | Refresh finished and the new values are queryable |
FAILED | Refresh failed; use the error message |
Safe Examples
Section titled “Safe Examples”Safe To Query Without Plugin Refresh
Section titled “Safe To Query Without Plugin Refresh”| Question | Why |
|---|---|
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 |
Refresh First
Section titled “Refresh First”| Question | Why |
|---|---|
| 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 |
A Few Important Nuances
Section titled “A Few Important Nuances”| Nuance | What it means |
|---|---|
workflows is not a plugin table | It is artifact-backed |
property-definitions is a plugin | Refresh it manually when schema freshness matters |
Recommended Habit
Section titled “Recommended Habit”Use this rule before every serious query:
| If your task depends on… | Do this |
|---|---|
| CRM records only | status(section="schema"), then query |
| CRM records plus plugin metadata | status(section="schema"), then refresh_plugins, then wait for COMPLETED, then query |