Skip to content

feat(canvas): workflows attached to canvases#3535

Open
mayteio wants to merge 5 commits into
mainfrom
posthog-code/canvas-workflows
Open

feat(canvas): workflows attached to canvases#3535
mayteio wants to merge 5 commits into
mainfrom
posthog-code/canvas-workflows

Conversation

@mayteio

@mayteio mayteio commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What

A workflow canvas = a canvas artifact (desktop-FS dashboard row) + a PostHog workflow (HogFlow, built and managed only via the workflows-* MCP tools) + the link between them (meta.workflow). A user types "Send an email after signup" into the canvas composer; the build agent drafts the workflow, authors the email template (neutral branding), tests every branch, and publishes an observability canvas from a baked-in starter board - then stops for the human to approve going live.

image

There is no "New workflow" button: the standard canvas generation prompt gained a workflow intent branch, so free-typed requests just work and suggestion chips are plain prefilled prompts.

How

  • Unified generation prompt (freeformPrompt.ts): first builds carry a MODE gate (plain canvas / build a workflow / track an existing workflow) plus a <workflow_instructions> block - discover destinations → draft via workflows-create/workflows-patch-graph → email templates in parallel subagents (neutral branding, never ask mid-run) → workflows-test-run every branch → workflows-blast-radius for batch → publish the canvas → summarise → STOP. Edit prompts are unchanged.
  • Starter boards (workflowStarters.ts): WORKFLOW_HEALTH_STARTER (deliverability/health) and WORKFLOW_ENGAGEMENT_STARTER (email engagement) are embedded in the prompt so the agent edits a proven scaffold instead of authoring React from scratch - this is what cuts the multi-minute UI generation down.
  • The workflow link primitive (agent emits → host writes): PostToolUse hooks pair a workflows-create/workflows-get result with the subsequent canvas publish and emit _posthog/workflow_built; the app catches it off the session event stream, PATCHes meta.workflow onto the row, and stamps templateId: "workflow". That one write drives the lightning-bolt icon in Artifacts, the status badge in the canvas header, edit-time prompt resolution, and the canvas rename. The MCP renders tool results as YAML, so the parser handles both YAML documents and JSON envelopes (regression-tested against a captured live payload).
  • Go-live gating: workflows-enable / workflows-run-batch / workflows-schedule-create / workflows-update-schedule always raise an "Approve & publish" card - even in auto mode, before persisted always-allows, with no always-allow option, never persisted. The cloud agent-server relays these when a client is reachable and otherwise parks them (never falls through to auto-approve).
  • Fixes found while dogfooding:
    • "Always allow" on a permission card no longer demotes an auto/bypass session to acceptEdits (previously one click caused a prompt storm for the rest of the run).
    • Hero-initiated canvas builds now resolve the backend feed channel, so the run shows in the channel feed.
    • A terminal cloud run now clears "Generating" even while the chat session lingers connected.
    • Repo-less tasks no longer render a diff-stats chip.
    • Generating screen shows the agent's live to-do list and flips optimistically on submit.

Verification

  • pnpm --filter typechecks clean for core / ui / agent / host-router; biome lint clean (no new warnings); check-host-boundaries clean.
  • Full suites green: agent 1426, ui 1737, core 2418 tests.
  • Live-verified in the dev app against a real PostHog project: intent detection (build-new and track-existing), draft workflow + email template creation, per-branch workflows-test-run, saved-insight-backed canvas published from the engagement starter, _posthog/workflow_built emitted with the full payload, auto-naming, and the auto-mode demotion fix.

Known gaps / follow-ups

  • Cloud park rule (agent-server.ts) ships with the sandbox image; verify the go-live card relays after the image rolls out (unit-tested meanwhile).
  • Stall-resume edge: if a run stalls long enough for the completion watcher to untrack the task and is then resumed, the link write can be missed (the watcher scans only tracked generations). Rare in the normal single-turn flow, where the publish lands while tracked.
  • workflowStatus on the badge is link-time only (not kept live).
  • Local dev only: a per-installation needs_approval state on mcp__posthog__exec makes every exec call prompt regardless of mode - pre-existing MCP-approval behavior, not introduced here.

Created with PostHog Code

mayteio added 3 commits July 17, 2026 10:56
A workflow canvas = a canvas artifact + a PostHog workflow (HogFlow) + the
link between them. The unified canvas generation prompt gains a workflow
intent branch: describing an ongoing action ("Send an email after signup")
makes the build agent draft a workflow over the PostHog MCP workflows-*
tools, author email templates with neutral branding, test every branch,
and publish an observability canvas from a baked-in starter board (health
or engagement) instead of authoring React from scratch.

- Workflow link primitive: the agent-side hooks pair a workflows-create/get
  result with the canvas publish and emit _posthog/workflow_built; the app
  writes the link into the dashboard row meta (setWorkflow) and stamps
  templateId "workflow" (lightning icon in Artifacts, workflow badge in the
  canvas header, edit-time prompt resolution).
- Go-live gating: workflows-enable / run-batch / schedule-create /
  update-schedule always raise an "Approve & publish" card - even in auto
  mode, with no always-allow, never persisted - and the cloud agent-server
  parks (never auto-approves) such requests when no client is reachable.
- Generating state now mirrors the agent's live to-do list (StepList) and
  flips optimistically on submit; a terminal cloud run now clears
  "Generating" even while the chat session lingers connected.
- Hero suggestions gain workflow ideas; repo-less tasks hide the diff chip.

Generated-By: PostHog Code
Task-Id: 3b50883f-cab5-443a-8b92-3d0c948688da
- Parse the PostHog MCP's YAML tool results in the workflow-built pairing:
  workflows-create/get return a YAML document, not JSON, so the link
  notification never fired. Add a top-level-line YAML fallback with a
  regression test against a captured real payload.
- Resolve the backend feed channel in useGenerateFreeformCanvas when the
  caller doesn't pass one (the canvas hero didn't), so hero-initiated
  builds land in the channel feed like composer submits.
- Never demote an auto/bypass session to acceptEdits when the user answers
  a permission card with "always allow" - the upgrade helper previously
  preferred acceptEdits unconditionally, which turned one "always allow"
  click into a prompt storm for the rest of an auto canvas build.

Generated-By: PostHog Code
Task-Id: 3b50883f-cab5-443a-8b92-3d0c948688da
Export findWorkflowBuilt and test it directly: live-stream and replay
method variants, request/response and foreign notifications ignored,
malformed payloads skipped.

Generated-By: PostHog Code
Task-Id: 3b50883f-cab5-443a-8b92-3d0c948688da
@trunk-io

trunk-io Bot commented Jul 17, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

React Doctor found 2 issues in 2 files · 2 warnings.

2 warnings

src/features/canvas/freeform/CanvasGenerateHero.tsx

src/features/canvas/freeform/FreeformCanvasView.tsx

Reviewed by React Doctor for commit 9cbdd7a.

@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Security Review

Workflow publication is gated before auto-mode and persisted approvals, but the disconnected and background parking path loses its safety instructions and becomes a generic failure.

Comments Outside Diff (1)

  1. packages/agent/src/adapters/claude/permissions/permission-handlers.ts, line 649-651 (link)

    P1 security Parked Approval Becomes Failure

    When no client is reachable or the run is in background mode, the cloud server cancels this request with instructions to leave the workflow disabled and end the turn. This branch discards that message and throws Tool use aborted, so a safely parked publication can fail the run or be retried later instead of stopping with the intended guidance.

Reviews (1): Last reviewed commit: "test(canvas): cover the workflow-built s..." | Re-trigger Greptile

Comment thread packages/agent/src/adapters/claude/hooks.ts
Comment thread packages/agent/src/server/agent-server.ts Outdated
Comment thread packages/agent/src/adapters/claude/permissions/posthog-exec-gate.ts
@veria-ai

veria-ai Bot commented Jul 17, 2026

Copy link
Copy Markdown

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 2 · PR risk: 0/10

mayteio added 2 commits July 17, 2026 12:40
Workflow builds were only discoverable via + > New canvas. Add a canvas-kind
starter card to the channel task suggestions, shown on both new-task surfaces:

- Channel home: selecting it prefills the composer AND arms canvas mode, so
  the submit runs canvas generation (whose unified prompt handles workflow
  intent) instead of creating a plain task.
- New-task screen: TaskInput hands canvas suggestions to the surface, which
  creates a canvas in the channel and opens it with the starter prompt
  dropped into the hero composer (one-shot prefill handoff), ready to edit.

Generated-By: PostHog Code
Task-Id: 3b50883f-cab5-443a-8b92-3d0c948688da
- Classify go-live calls adapter-neutrally at the cloud relay: Codex
  forwards PostHog exec approvals without Claude's alwaysGated marker, so
  the park rule now also inspects the tool call itself
  (isPostHogGoLiveToolCall: posthog server exec + always-gated sub-tool).
- Recognize plugin-installed PostHog servers (mcp__plugin_posthog_*__exec)
  in the exec-tool matcher, mirroring the renderer's server-name pattern,
  so both the destructive and go-live gates cover them.
- Consume the pendingWorkflow slot after a link is emitted, so a later
  canvas publish in the same session can't re-emit a stale workflow link.

Generated-By: PostHog Code
Task-Id: 3b50883f-cab5-443a-8b92-3d0c948688da
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant