Blueprint Run
A blueprint_run records a single execution of the Blueprint Analyzer — Well's multi-phase web-navigation agent (Claude Opus) that autonomously browses a target URL to accomplish a natural-language goal. Each run belongs to exactly one workspace and progresses through a lifecycle (queued → running → persisting → completed | failed | abandoned). The run is the audit spine for the analysis session: it captures the high-level intent (goal, target_url), the agent's final synthesized output (result_blueprint), and — on failure — structured error diagnostics (error_type, error_message, failed_at_step, error_context). Individual navigation actions are stored as child BlueprintStep records linked by a one-to-many relationship.
| Naming | Value |
|---|---|
| Object | Blueprint Run |
Resource type (JSON:API type) | blueprint_run |
| Collection / records root | blueprint_runs |
| REST base | /v1/blueprint-runs |
| Entity class | BlueprintRun |
API operations
| Operation | Method & path | Status |
|---|---|---|
| List | GET /v1/blueprint-runs | ✅ Implemented |
| Retrieve | GET /v1/blueprint-runs/{id} | ✅ Implemented |
| Create | POST /v1/blueprint-runs | 🟡 Planned |
| Update | PATCH /v1/blueprint-runs/{id} | 🟡 Planned |
| Delete | DELETE /v1/blueprint-runs/{id} | 🟡 Planned |
Data model
Attributes
| Field | Type | Required | Constraints | Allowed values | Description |
|---|---|---|---|---|---|
| blueprint_run_id | string, UUID, 🔒 system | ✅ Yes | unique; generated via gen_random_uuid() on insert | — | Public immutable identifier for the run. Used in all API surfaces; the internal pk is never exposed. |
| goal | string | ✅ Yes | text; no max length | — | Natural-language objective passed to the Blueprint Analyzer agent at run creation. Describes what the agent should accomplish on the target website. |
| target_url | string | ✅ Yes | text; no max length; must be a valid URL reachable by the agent | — | The URL the agent navigates as the starting point of the run. |
| firebase_uid | string | ⚪ No | text; nullable | — | Firebase UID of the authenticated user who initiated the run. Written at run creation from the Firebase auth context. Used to associate the run back to a specific user session within the workspace. |
| status | enum (BlueprintRunStatusEnum) | ✅ Yes | default 'running'; not null; native Postgres enum blueprint_run_status_enum | queued, running, persisting, completed, failed, abandoned | Lifecycle state of the run. Transitions: queued (created but not yet started) → running (agent executing steps) → persisting (BlueprintStorageService writing results) → completed (success) | failed (agent error) | abandoned (timed out or manually cancelled). The queued and persisting states were added in Migration20260429110000. |
| step_count | integer | ✅ Yes | default 0; not null; incremented atomically by BlueprintStorageService.persistStep | — | Running count of steps persisted for this run. Incremented atomically (not derived from the steps collection count) so it reflects the true number of completed steps even if child rows are soft-deleted. |
| result_blueprint | jsonb | ⚪ No | nullable; free-form JSON | — | The structured output produced by the agent upon successful completion. Written by BlueprintStorageService from the AI's final aiResponse.blueprint payload. Shape is agent-defined and varies by goal type (e.g. pricing tables, API schemas, form fields). Null until the run reaches completed status. |
| error_type | string | ⚪ No | text; nullable | — | Machine-readable error category written when the run transitions to failed. Examples: navigation_error, timeout, parse_error. Used to group failures in monitoring dashboards. |
| error_message | string | ⚪ No | text; nullable | — | Human-readable error description accompanying error_type on failure. Written by BlueprintStorageService when the agent reports a terminal error. |
| failed_at_step | integer | ⚪ No | nullable; references the 1-based step_number of the failing BlueprintStep | — | The step_number at which the run failed. Written alongside error_type and error_message by BlueprintStorageService. Null when the run completed successfully or was abandoned before any step executed. |
| error_context | jsonb | ⚪ No | nullable; free-form JSON | — | Full diagnostic payload for the failure event. Written by BlueprintStorageService as { aiResponse: <raw agent response> } at the point of failure. Provides the raw AI output that caused or accompanied the error, for debugging and replay. |
| created_at | timestamptz, 🔒 system | ✅ Yes | set by MikroORM onCreate lifecycle hook; not null | — | Timestamp when the run record was created. Indexed DESC for recency queries (partial index on deleted_at IS NULL). |
| updated_at | timestamptz, 🔒 system | ⚪ No | set by MikroORM onCreate + onUpdate lifecycle hooks; nullable | — | Timestamp of the most recent update to any field on the run. Refreshed automatically on every flush that modifies the record. |
| completed_at | timestamptz | ⚪ No | nullable; written by BlueprintStorageService when status transitions to completed or failed | — | Timestamp when the run reached its terminal state (completed or failed). Combined with created_at, this gives the wall-clock duration of the agent execution. Null while the run is in-flight (queued/running/persisting) or abandoned. |
| deleted_at | timestamptz | ⚪ No | nullable; soft-delete sentinel | — | Soft-delete timestamp. When non-null the run is considered deleted and excluded from all standard queries and both partial indexes (which filter WHERE deleted_at IS NULL). Cascade delete from the workspace also hard-deletes via the FK constraint. |
Relationships
| Name | Type | Required | Description |
|---|---|---|---|
| workspace | to-one (workspace) | ✅ Yes | The workspace that owns this blueprint run. FK: workspace_pk → workspaces.pk. Cascade: ON DELETE CASCADE — deleting a workspace hard-deletes all its runs. Used to scope the run to a tenant and enforce multi-tenant isolation in Hasura RLS. |
| steps | to-many (blueprint_step) | — | Ordered collection of BlueprintStep records representing the individual navigation actions the agent took during this run. Related via BlueprintStep.blueprint_run_pk → BlueprintRun.pk. Cascade: ON DELETE CASCADE — deleting a run hard-deletes all its steps. The composite composite_steps_list in composites.yml surfaces step_number, action_type, and action_success in the records table view. |
System-computed
blueprint_run_idis generated by Postgresgen_random_uuid()on insert; unique constraint enforced at the DB level.created_atis set by the MikroORMonCreatelifecycle hook on first flush; never updated.updated_atis set by bothonCreateandonUpdatelifecycle hooks; refreshed on every write to the record.statusdefaults torunningat the DB level; the controller may set it toqueuedwhen enqueuing before agent dispatch.BlueprintStorageServicedrives transitions: running → persisting at start of persist, then persisting → completed on success or persisting → failed on error.step_countis incremented atomically byBlueprintStorageService.persistStep(not derived from the child collection) so it is consistent even when child rows are soft-deleted.completed_atis written byBlueprintStorageServicewhen the run reachescompletedorfailedstatus. It is never set forabandonedruns.result_blueprintis written fromaiResponse.blueprintbyBlueprintStorageServiceonly on the final successful step (terminalcompletedtransition).failed_at_stepanderror_contextare written together byBlueprintStorageServicewhen the agent reports a terminal error;error_contextcaptures the rawaiResponsepayload for replay.- Both partial indexes (
idx_blueprint_runs_workspace_statuson(workspace_pk, status)andidx_blueprint_runs_created_at_descon(created_at DESC)) filterWHERE deleted_at IS NULL, so they apply only to active rows. - Cascade deletes flow from workspace → blueprint_runs → blueprint_steps via FK ON DELETE CASCADE chains.
Example
{
"data": {
"type": "blueprint_run",
"id": "c3f7a2b1-8e4d-4f91-b035-2a6c1d9e0f84",
"attributes": {
"goal": "Extract the current pricing plans and feature comparison table from the Stripe pricing page",
"target_url": "https://stripe.com/pricing",
"firebase_uid": "XkJ7Qm2pL9nRvBwdTzAs8oY3eH5fCi",
"status": "completed",
"step_count": 7,
"result_blueprint": {
"pricing_plans": [
{ "name": "Starter", "price_usd": 0, "features": ["Payments", "Dashboard"] },
{ "name": "Growth", "price_usd": 49, "features": ["Payments", "Dashboard", "Radar", "Billing"] }
],
"summary": "Three tiers identified: Starter (free), Growth ($49/mo), Enterprise (custom)."
},
"error_type": null,
"error_message": null,
"failed_at_step": null,
"error_context": null,
"created_at": "2026-05-14T09:12:03.000Z",
"updated_at": "2026-05-14T09:14:47.000Z",
"completed_at": "2026-05-14T09:14:47.000Z",
"deleted_at": null
},
"relationships": {
"workspace": {
"data": { "type": "workspace", "id": "b91e4d02-7c3a-41f6-9d28-5f0a3bc87e14" }
},
"steps": {
"data": [
{ "type": "blueprint_step", "id": "a1b2c3d4-0001-4e5f-8abc-def012345678" },
{ "type": "blueprint_step", "id": "a1b2c3d4-0002-4e5f-8abc-def012345679" }
]
}
}
}
}apps/api/src/database/entities/BlueprintRun.ts · domain: automation · tier: Activity