Files
zeekay bc4ddf332b chore: rebase the tree onto upstream master fa1a9a60
Mechanically re-derived: bin/debrand runs over a fresh import of
posthog/posthog@fa1a9a60d4 (2026-08-06).
The pipeline (.hanzo/workflows), the Dockerfiles and bin/docker*
entrypoints, compose files, LLM.md and the squashed initial migration
are restored from the shipped tree, same as the previous import.

The prune's import-closure guard kept 21 products the new core now
imports; dropping them is a refactor now, recorded rather than forced.
2026-08-06 01:25:36 -07:00

469 lines
23 KiB
YAML

# MCP tool definition — tool entries are scaffolded from the OpenAPI schema.
# The tool list and operation IDs are kept in sync automatically:
# pnpm --filter=@hanzo/mcp run scaffold-yaml -- --sync-all
#
# To enable a tool, set enabled: true and add required scopes + annotations.
# All other fields (title, description, enrich_url, etc.) are yours to configure.
category: Workflows
feature: workflows
url_prefix: /workflows
ui_apps:
workflow:
type: detail
view_prop: workflow
workflow-list:
type: list
detail_tool: workflows-get
tools:
script-flow-templates-create:
operation: hog_flow_templates_create
enabled: false
script-flow-templates-destroy:
operation: hog_flow_templates_destroy
enabled: false
script-flow-templates-list:
operation: hog_flow_templates_list
enabled: false
script-flow-templates-logs-retrieve:
operation: hog_flow_templates_logs_retrieve
enabled: false
script-flow-templates-partial-update:
operation: hog_flow_templates_partial_update
enabled: false
script-flow-templates-retrieve:
operation: hog_flow_templates_retrieve
enabled: false
script-flow-templates-update:
operation: hog_flow_templates_update
enabled: false
script-flows-asset-content-retrieve:
operation: hog_flows_asset_content_retrieve
enabled: false
script-flows-assets-retrieve:
operation: hog_flows_assets_retrieve
enabled: false
script-flows-batch-jobs-create:
operation: hog_flows_batch_jobs_create
enabled: false
script-flows-bulk-delete-create:
operation: hog_flows_bulk_delete_create
enabled: false
script-flows-create:
operation: hog_flows_create
enabled: false
script-flows-destroy:
operation: hog_flows_destroy
enabled: false
script-flows-discard-draft-create:
operation: hog_flows_discard_draft_create
enabled: false
script-flows-email-sending-suspension-retrieve:
operation: hog_flows_email_sending_suspension_retrieve
enabled: false
script-flows-invocations-create:
operation: hog_flows_invocations_create
enabled: false
script-flows-metrics-totals-retrieve:
operation: hog_flows_metrics_totals_retrieve
enabled: false
script-flows-partial-update:
operation: hog_flows_partial_update
enabled: false
script-flows-publish-create:
operation: hog_flows_publish_create
enabled: false
script-flows-reputation-retrieve:
operation: hog_flows_reputation_retrieve
enabled: false
script-flows-rerun-create:
operation: hog_flows_rerun_create
enabled: false
script-flows-revisions-list:
operation: hog_flows_revisions_list
enabled: false
script-flows-revisions-restore-create:
operation: hog_flows_revisions_restore_create
enabled: false
script-flows-revisions-retrieve:
operation: hog_flows_revisions_retrieve
enabled: false
script-flows-schedules-create:
operation: hog_flows_schedules_create
enabled: false
script-flows-schedules-destroy:
operation: hog_flows_schedules_destroy
enabled: false
script-flows-schedules-list:
operation: hog_flows_schedules_list
enabled: false
script-flows-update:
operation: hog_flows_update
enabled: false
script-flows-user-blast-radius-create:
operation: hog_flows_user_blast_radius_create
enabled: false
internal-script-flows-account-audience-create:
operation: internal_hog_flows_account_audience_create
enabled: false
internal-script-flows-batch-jobs-status-update:
operation: internal_hog_flows_batch_jobs_status_update
enabled: false
internal-script-flows-process-due-schedules-create:
operation: internal_hog_flows_process_due_schedules_create
enabled: false
internal-script-flows-user-blast-radius-create:
operation: internal_hog_flows_user_blast_radius_create
enabled: false
internal-script-flows-user-blast-radius-persons-create:
operation: internal_hog_flows_user_blast_radius_persons_create
enabled: false
workflows-create:
operation: hog_flows_create
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: false
idempotent: false
enrich_url: '{id}/workflow'
title: Create workflow
description: >
Create a workflow. It is created as a draft and does NOT run until enabled: test it with workflows-test-run
first, then enable (workflows-enable) only with the user's explicit approval — from then on it runs on real
people, and further content edits stage as a draft you must publish (workflows-publish) to take effect.
Provide an actions array with exactly one type='trigger' (config.type:
event|webhook|manual|batch|tracking_pixel) plus action nodes
(function/function_email/function_sms/function_push, delay, conditional_branch, wait_until_condition, ...)
connected by edges. A webhook or manual trigger also needs config.template_id set to the literal
'template-source-webhook', and a tracking_pixel trigger needs 'template-source-webhook-pixel'; without it
the create is rejected with 'Template not found' against the trigger node. Read the building-workflows skill
for node shapes before composing: a node that mismatches the per-type schema saves but breaks the visual
editor. Two traps that save but break: (1) a conditional_branch condition needs a 'filters' wrapper —
{filters:{properties:[...]}}, not {properties:[...]} on the condition; omitting it passes save but the
editor flags it and the branch won't evaluate your condition. (2) Never hand-author bytecode anywhere; send
properties/hash and the server compiles it. A 'batch' trigger broadcasts to an audience
(config.filters.properties: person-property conditions and/or cohort references), one run per matching
person, and does NOT fire on enable: dispatch with workflows-run-batch or attach a schedule with
workflows-schedule-create. Behavioral targeting ('did event X at least N times over the last M days') is
unsupported; reject it and explain why.
ui_app: workflow
workflows-discard-draft:
operation: hog_flows_discard_draft_create
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: true
idempotent: true
title: Discard workflow draft
description: >
Throw away a workflow's staged draft without touching the live config. Idempotent — discarding when nothing
is staged is a no-op. Returns the workflow.
ui_app: workflow
workflows-get:
operation: hog_flows_retrieve
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
enrich_url: '{id}/workflow'
title: Get workflow
description: >
Get a specific workflow by ID, where id is the workflow's UUID. When you have a workflow's name instead,
resolve it first with workflows-list (search=<name>) and use the id from that result. Returns the full
workflow definition including trigger, edges, actions, exit condition, variables, and any recurring
'schedules' (read-only here). For a batch workflow, check status=='active' plus an active entry in
'schedules' to confirm it will actually fire. On an active workflow, 'draft' holds staged content changes
awaiting workflows-publish (null when nothing is staged) — the live config in actions/edges is what's
running.
ui_app: workflow
workflows-get-invocation:
operation: hog_flows_invocation_result_retrieve
enabled: true
scopes:
- hog_flow:read
- person:read
annotations:
readOnly: true
destructive: false
idempotent: true
title: Get workflow invocation
description: >
Get a single workflow invocation by invocation_id, including invocation_globals — the raw triggering payload
(event/person/groups) that the run executed against. Use after workflows-list-invocations to inspect exactly
what input produced a failure.
workflows-get-revision:
operation: hog_flows_revisions_retrieve
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
title: Get workflow revision
description: >
Get one revision of a workflow by version number, including its full content snapshot (actions, edges,
trigger, variables). Use to inspect what was live at that version before restoring it with
workflows-restore-revision.
workflows-global-stats:
operation: hog_flows_metrics_global_retrieve
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
list: true
title: Workflow stats overview
description: >
At-a-glance health across ALL workflows in one call: per-workflow succeeded/failed counts over a window
(after/before, default last 7 days), sorted most-failing first. Start here when debugging — find which
workflows are failing, then drill into those with workflows-list-invocations (who it failed for) →
workflows-get-invocation (the triggering payload) → workflows-logs (the failing step). Avoids scanning every
workflow one at a time. For a single workflow's time-series, use workflows-stats.
workflows-list:
operation: hog_flows_list
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
list: true
title: List workflows
description: >
List all workflows in the project. Returns workflows with their name, description, status
(draft/active/archived), version, trigger configuration, and timestamps. Pass search=<name> to find a
workflow by name and read its id. Most workflows-* tools take that value as 'id'; workflows-blast-radius,
workflows-run-batch and workflows-schedule-create take it as 'workflow_id'.
ui_app: workflow-list
workflows-list-batch-jobs:
operation: hog_flows_batch_jobs_list
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
list: true
title: List workflow batch runs
description: >
List past batch runs for a workflow (both one-off broadcasts and schedule-triggered runs). Each entry shows
the audience filters and variable overrides the run used, plus when it was created. The status field is not
tracked — use workflows-logs / workflows-stats for the outcome of a run.
workflows-list-invocations:
operation: hog_flows_invocation_results_retrieve
enabled: true
scopes:
- hog_flow:read
- person:read
annotations:
readOnly: true
destructive: false
idempotent: true
list: true
title: List workflow invocations
description: >
List a workflow's individual invocations (one execution per person/event), each collapsed to its final
outcome — status, error_kind/error_message, distinct_id, person_id, timings. This is the per-recipient
failure view: filter status=failed to see who it failed for and why. Filter by distinct_id and time range.
Distinct from workflows-list-batch-jobs (the dispatch ledger, which has no per-person outcome) — drill from
a failed invocation into workflows-logs for the step-by-step trace.
workflows-list-revisions:
operation: hog_flows_revisions_list
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
list: true
title: List workflow revisions
description: >
List a workflow's revision history, newest first. Every live-content change (publish, direct edit) appends a
version; each entry shows version, when, and by whom. Fetch a version's content with workflows-get-revision;
roll back with workflows-restore-revision.
workflows-logs:
operation: hog_flows_logs_retrieve
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
title: Get workflow logs
description: >
Retrieve execution logs for a specific workflow by ID. Returns log entries with timestamp, level (DEBUG,
LOG, INFO, WARN, ERROR), and message. Use to debug why a workflow is failing or not producing expected
results. Supports filtering by log level, text search, time range (after/before), and pagination via limit.
workflows-patch-action-email:
operation: hog_flows_actions_email_partial_update
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: false
idempotent: false
input_schema: WorkflowActionEmailPatchSchema
title: Patch a workflow step's email
description: >
Surgically edit the email inside one function_email step - the fastest path for copy tweaks and design
changes on a workflow email. Use operations (the same design ops as workflows-patch-email-template,
addressing blocks by id from the step's config.inputs.email.value.design) to edit the design, and
email_patch to change subject, preheader, text, or recipients. After design ops the HTML is re-rendered
server-side, so the sent email always matches the design. Edits apply atomically: an invalid batch changes
nothing. On an active workflow, edits stage a draft (composing with any staged graph edits) and nothing
reaches real people until workflows-publish. The full updated workflow is returned. Prefer this over
workflows-patch-graph update_action for email content - it's smaller to send and keeps design and HTML in
sync. For library templates use workflows-patch-email-template instead.
workflows-patch-graph:
operation: hog_flows_graph_partial_update
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: false
idempotent: false
input_schema: WorkflowGraphPatchSchema
title: Patch workflow graph
description: >
Surgically edit a workflow's graph by sending a small, ordered list of operations instead of resending every
action and edge. Prefer this over workflows-update for any graph change — to tweak one node's config use
update_action with a deep-merge patch (e.g. change just an email subject), and use add_action /
remove_action / add_edge / remove_edge / replace_action_edges for structural changes. Reference nodes and
edges by id. Operations apply atomically: the graph is read, the ops applied in order, the result fully
validated (dangling edges, branch indexes, single trigger), and saved only if valid — otherwise nothing
changes. On an active workflow, patches stage a draft instead of changing what's running: the first patch
copies the live graph into the draft, later patches compose onto it, and nothing reaches real people until
workflows-publish. The full updated workflow is returned, so you don't need to re-fetch before the next
edit. When adding or editing a conditional_branch, each condition needs a 'filters' wrapper:
{filters:{properties:[...]}}, not {properties:[...]} on the condition. Re-test the changed path with
workflows-test-run after patching.
workflows-publish:
operation: hog_flows_publish_create
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: true
idempotent: false
title: Publish workflow draft
description: >
Apply a workflow's staged draft to its live config. Two-step: call without confirm first — it returns
in_flight_runs, a confirm_token, and an impact summary (per deleted step: about how many people are parked
there and whether they move to a surviving step or exit; variables that may render empty for runs that never
executed their new producer; schedules overriding removed variables), changing nothing. Echo the impact to
the user and get their go-ahead, then call again with confirm=true and that confirm_token. A 409 means the
draft changed since the preview and a 400 means the token expired — preview again and re-confirm either way.
Publish revalidates the draft fully and recompiles it, so an invalid draft is rejected with the reason and
the live config stays untouched. Test the draft first with workflows-test-run (use_draft=true). Shortened
delays apply to parked runs via a spread sweep: runs already waking soon keep their original time, and wakes
moved earlier by the sweep trickle in from a few minutes after publish rather than all at once - so runs
still parked shortly after publishing are normal, not a sign of a failed publish.
workflows-restore-revision:
operation: hog_flows_revisions_restore_create
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: true
idempotent: true
title: Restore workflow revision
description: >
Roll a workflow back (or forward) by copying a revision's content into its staged draft — the live config is
untouched until you publish. Then run the normal cycle: test with workflows-test-run (use_draft=true),
preview with workflows-publish, confirm. The preview shows exactly what the rollback does to people
in-flight. A 409 means a draft is already open — publish or discard it, or pass overwrite=true to replace
it. Note what a rollback can't undo: runs that already moved on while the newer version was live keep their
positions.
workflows-stats:
operation: hog_flows_metrics_retrieve
enabled: true
scopes:
- hog_flow:read
annotations:
readOnly: true
destructive: false
idempotent: true
title: Get workflow stats
description: >
Execution stats for a single workflow by ID: time-series success/failure counts over a configurable interval
(hour, day, or week). Use to inspect one workflow's health — failure spikes and reliability trends. For an
at-a-glance view across ALL workflows, call workflows-global-stats first, then drill in here. Supports
breakdown by metric kind (success/failure) or name, and time range filtering. For email engagement, read
email_opened and email_link_clicked against (email_sent - email_untracked): email_untracked counts sends
with open/click tracking off, which can never register an open or a click.
workflows-test-run:
operation: hog_flows_invocations_create
enabled: true
scopes:
- hog_flow:write
- group:read
annotations:
readOnly: false
destructive: true
idempotent: false
title: Test-run workflow
description: >
Test-invoke a workflow one node at a time; it does NOT traverse the full graph in one call. The result
includes nextActionId. To verify a path end to end, chain calls: start at the trigger (omit
current_action_id), then pass the returned nextActionId as current_action_id on the next call, and repeat.
To test a specific branch, set current_action_id to that node. Skip delay nodes by jumping to the action
after them, since delays are not simulated. Pass test data via globals (typically {event, person, groups}).
Async actions (HTTP/email/SMS/push) are mocked by default; set mock_async_functions=false to fire real side
effects. Returns the step's execution trace. Set use_draft=true to test a workflow's staged draft instead of
its live config — always do this before workflows-publish. use_draft requires a staged draft to exist
(workflows-get shows it in 'draft'); on a workflow with nothing staged, omit it.
exclude_params:
- configuration
workflows-update:
operation: hog_flows_partial_update
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: false
idempotent: true
enrich_url: '{id}/workflow'
title: Update workflow
description: >
Updates workflow fields a graph patch can't express: name, description, exit_condition, conversion,
trigger_masking, variables. Graph content (actions/edges) is rejected here - a partial list would silently
drop every step it omits - so all graph edits go through workflows-patch-graph. On an active workflow,
content fields stage a draft (published with workflows-publish) while name/description apply immediately.
Status changes go through workflows-enable / workflows-archive.
exclude_params:
- status
- actions
- edges
ui_app: workflow
workflows-update-schedule:
operation: hog_flows_schedules_partial_update
enabled: true
scopes:
- hog_flow:write
annotations:
readOnly: false
destructive: false
idempotent: true
title: Update workflow schedule
description: >
Update a recurring schedule's RRULE, start time, timezone, or variable overrides. Changing the cadence
reschedules the next run. Each firing re-broadcasts to the workflow's current trigger audience.