DenchClaw Event System: Real-Time Updates Across Your Workspace

How DenchClaw's event system broadcasts real-time updates across all open apps and views when CRM data changes.

Mark Rachapoom
Mark Rachapoom
·6 min read
DenchClaw Event System: Real-Time Updates Across Your Workspace

DenchClaw's event system is the real-time communication layer that connects your CRM, AI agent, and custom apps. When a deal status changes, an entry is created, or an AI task completes, an event is broadcast instantly to all listeners — other apps, widgets, view components, and external webhooks — keeping your entire workspace in sync without polling.

Architecture Overview#

The event system is built on a local publish-subscribe model:

CRM Update → Event Bus → [App Listeners, View Listeners, Webhook Listeners, ...]
AI Action  → Event Bus → [App Listeners, Notification System, ...]
App Action → Event Bus → [Other Apps, AI Agent, ...]

Every component in DenchClaw — views, apps, widgets, the AI agent, cron jobs — both emits and subscribes to events. The event bus is the nervous system of the workspace.

System Events Reference#

These events are emitted by DenchClaw automatically:

CRM Events#

// Entry lifecycle events
"entry:created"    // New entry added to any object
"entry:updated"    // Entry fields changed
"entry:deleted"    // Entry removed
"entry:restored"   // Deleted entry restored
 
// Payload for entry events:
{
  objectName: "deals",
  entryId: "abc-123",
  fields: { /* all field values */ },
  changedFields: { /* for updates: only changed fields */ }
}
// Object/schema events
"object:created"   // New CRM object created
"object:updated"   // Object schema modified
"object:deleted"   // Object deleted
 
// View events
"view:changed"     // User switched to a different view
"view:filtered"    // Active filter changed
"selection:changed"  // User selected entries in the current view

AI Agent Events#

"agent:message"        // New chat message (user or AI)
"agent:thinking"       // AI is processing
"agent:done"           // AI response completed
"agent:subagent:started"   // Subagent spawned
"agent:subagent:completed" // Subagent finished
"agent:tool_call"      // AI called a tool
"agent:tool_result"    // Tool returned a result

App Events#

"app:loaded"       // A Dench App opened
"app:closed"       // A Dench App closed
"app:error"        // App encountered an error

System Events#

"cron:started"     // Scheduled task began
"cron:completed"   // Scheduled task finished
"cron:failed"      // Scheduled task errored
"webhook:received" // Inbound webhook arrived
"workspace:synced" // Workspace data synced (cloud sync)

Subscribing to Events in Apps#

// Subscribe to a specific event
dench.events.on("entry:created", (event) => {
  if (event.objectName === "deals") {
    console.log("New deal:", event.fields["Deal Name"]);
  }
});
 
// Subscribe with filter function
dench.events.on("entry:updated", (event) => {
  if (event.objectName === "deals" &&
      event.changedFields?.["Status"] === "Closed Won") {
    celebrate();  // 🎉
  }
});
 
// Subscribe to all events (useful for debugging)
dench.events.on("*", (event) => {
  console.log(event.type, event);
});
 
// One-time subscription
dench.events.once("agent:done", (event) => {
  console.log("AI task finished:", event.result);
});
 
// Unsubscribe
const handler = (event) => { /* ... */ };
dench.events.on("entry:created", handler);
// Later:
dench.events.off("entry:created", handler);

Emitting Custom Events#

Apps emit custom events to communicate with each other:

// App-specific event (namespaced to avoid collisions)
await dench.events.emit("pipeline-dashboard:filter-changed", {
  filter: "Q1 Deals",
  dealCount: 42,
  totalValue: 1250000
});
 
// Another app listens for it
dench.events.on("pipeline-dashboard:filter-changed", (event) => {
  updateSummaryCard(event.dealCount, event.totalValue);
});

Talk to Sales

Tell us about your team and we'll show you how Dench fits your workflow.

By submitting this form you agree to be contacted by our team. See our Privacy Policy and Terms of Service.

Event-Driven Live Views#

The most powerful application: live-updating data views that react instantly to CRM changes.

// Live pipeline chart that updates when deals change
let chartData = null;
 
async function loadChart() {
  const data = await dench.db.query(`
    SELECT "Stage", COUNT(*) as count, SUM(CAST("Deal Value" AS FLOAT)) as total
    FROM v_deals WHERE "Status" = 'Active'
    GROUP BY "Stage"
  `);
 
  chartData = data;
  renderChart(data);
}
 
// Initial load
await loadChart();
 
// React to CRM changes — no polling needed
dench.events.on("entry:created", async (e) => {
  if (e.objectName === "deals") await loadChart();
});
dench.events.on("entry:updated", async (e) => {
  if (e.objectName === "deals") await loadChart();
});
dench.events.on("entry:deleted", async (e) => {
  if (e.objectName === "deals") await loadChart();
});

Your chart now updates the instant a deal changes — without any polling loop or refresh button.

AI Agent Event Integration#

The AI agent integrates deeply with the event system:

The agent listens to app events: When your custom app emits an event, the agent can react:

// App emits a request for AI assistance
await dench.events.emit("app:help-requested", {
  context: "User is viewing deal pipeline",
  question: "Which deals are at risk this quarter?"
});
 
// Agent receives this and generates a response
// The response arrives via agent:message event
dench.events.on("agent:message", (event) => {
  if (event.replyTo === "app:help-requested") {
    displayAIInsight(event.content);
  }
});

The agent emits events from tool calls: When the AI creates or updates a CRM entry, an entry:created or entry:updated event fires — keeping your open views and apps in sync.

Event Delivery Guarantees#

Events in DenchClaw are:

  • In-order: Events are delivered in the order they occurred
  • Synchronous delivery: All listeners are called before the emit resolves
  • No persistence: Events are not stored (use the history API for recent events)
  • Local scope: Events are scoped to the running workspace instance

For cross-session or cross-machine event delivery, use webhooks instead.

Performance Considerations#

The event system adds negligible overhead for typical usage. However:

  • Avoid heavy computations in event handlers — they block the event loop
  • For expensive operations (database queries, AI calls), debounce rapid events:
let debounceTimer;
dench.events.on("entry:updated", (e) => {
  if (e.objectName !== "deals") return;
  clearTimeout(debounceTimer);
  debounceTimer = setTimeout(async () => {
    await refreshDashboard();
  }, 500);  // Wait 500ms after last update before refreshing
});

This prevents redundant refreshes when bulk operations update many records rapidly.

See also: DenchClaw Inter-App Messaging for app-to-app communication patterns, and DenchClaw Webhooks for external event delivery.

Frequently Asked Questions#

Can I subscribe to events from the AI chat?#

Yes. Subscribe to agent:message to receive all AI responses in your app. This enables custom UIs that overlay AI output on your data — for example, an AI assistant panel that responds to context from your currently active CRM view.

Do events fire during bulk imports?#

Yes. Each entry created during a bulk import fires an entry:created event. For large imports (1000+ entries), this can cause many rapid events. Use debouncing in your event handlers for bulk-import scenarios.

Can events trigger external webhooks?#

Yes — configure outbound webhooks to trigger on system events. See the DenchClaw Webhooks guide for event-to-webhook configuration.

Is there a way to replay historical events?#

Use dench.events.getHistory({ limit: 100, type: "entry:created" }) to retrieve recent events. History is limited to the last 100 events per type in the current session.

Can events be emitted from cron jobs?#

Yes. Tasks running in cron contexts have full event system access. A cron job can emit a completion event that triggers an update in any currently open app: dench.events.emit("cron:enrichment-complete", { newContactsAdded: 12 }).

Ready to try DenchClaw? Install in one command: npx denchclaw. Full setup guide →

Related articles

Keep reading

View all