Skip to main content

Implementing the Four Extension Points

The four extension points are the heart of the plugin contract: they're the functions the core calls, at defined moments, to hand domain-specific work back to you. Your manifest declares all four; the core invokes them. This is the overview — the most complex one, the result handler, gets its own deep dive.

The four, at a glance​

Extension pointThe core calls it when…It returns…
resultHandlera workflow execution completes successfullyvoid — you persist domain artifacts
workspaceSnapshotProviderit's assembling the webhook payload at workflow launchthe domain JSON for workspace_snapshot
dashboardStatsProviderit's rendering the dashboard{ total, completed, label? }
workspaceDisplayResolverit's rendering dashboard tables that show entity identity[{ workspaceId, entityDisplayName, manageRoute }]

resultHandler​

Called at completion, inside the core's transaction (you receive a client — use it for all writes; never BEGIN/COMMIT/ROLLBACK). You validate and persist the workflow's result payload, and — when the workflow creates a new workspace — create that workspace via coreWorkspaceService.create and link it. You do not update workspace status; the core does that after you return. If you throw, the core rolls everything back and marks the execution failed_permanent. This one is important enough to have its own article.

workspaceSnapshotProvider​

Called at launch. You inspect the workspace's current state and return the domain context for the run — the plugin's slice of the webhook payload (for the default plugin: the thing's title, description, current text, input, and status). This is how the operator's specific request reaches the workflow. If it throws, the launch fails cleanly (no execution created).

dashboardStatsProvider​

Called when the dashboard renders. You return your completion KPI — { total, completed, label } — because only your plugin knows what "completed" means for your entity. The core can't compute it; it just renders the card you return.

workspaceDisplayResolver​

Called when the core renders shared tables (in-progress executions, recent errors) that need to show which entity a workspace belongs to. Given a list of workspace IDs your plugin owns, you return a display name and manage-route for each (a null route for a deleted/unresolvable one). The core only ever passes you workspace IDs your plugin owns, so you don't filter others.

The shape of the deal​

Notice the pattern: the core handles everything domain-agnostic (dispatch, logging, cost, status transitions, table rendering) and calls you for the four things only your domain can answer — persist a result, build domain context, define completion, name an entity. Implement these four faithfully and your plugin is fully wired into the platform.