Skip to content

Validate Automation Graph

Check a step graph without saving anything.

Updated View as MarkdownAsk ClaudeOpen in ChatGPTllms.txt

Use the Speak AI MCP server tool validate_automation_graph to check a step graph without saving anything.

What does it do?

Check a step graph without saving anything. Reports the same problems create_automation and update_automation would refuse (branch wiring, rules a condition cannot actually read, shapes the Speak web editor could not reopen) plus non-blocking warnings. Use it to iterate on a branched automation instead of discovering the problems one failed save at a time.

Parameters

validate_automation_graph takes 3 parameters, 1 of them required.

Name Type Required Description
steps array of object Yes Ordered array of graph steps (1-20). Each step is an object: { stepId: string (unique within the array), stepType: one of “speak-upload” | “magic-prompt” | “translation” | “filter” | “condition” | “notify” | “outbound-webhook” | “composio-action”, dependsOn?: string[] (stepIds this step runs after), branch?: “true”|“false” (which outcome of an upstream condition step this step belongs to) } plus ONE config key matching stepType: • speak-upload -> speakUpload: { sourceMode: “url”|“file”, sourceUrl (required when sourceMode=“url”; tokens allowed. If the token resolves to an object, the first http(s) URL inside it is used), folderId (required, unless folderRouting.mode=“dynamic” where it becomes the optional fallback), name? (tokens allowed, mixable with static text), language? (language code or token), fieldsMap?: { <customFieldId>: “<value>” } (writes payload values into Speak custom fields on the uploaded media; values are usually {{trigger.payload.<path>}} tokens. Get field ids from list_fields), folderRouting?: { mode: “static”|“dynamic”, sourceKey (payload key holding the destination folder name, required when dynamic), onNoMatch: “create”|“default” (create a folder named after the value, or fall back to folderId) } } • magic-prompt -> magicPrompt: { prompt (required unless fieldIds given, max 20000), title?, assistantType? (“general”|“researcher”|“marketer”|“sales”|“recruiter”|“custom”, default “general”), assistantTemplateId? (required if assistantType=“custom”), fieldIds?: string[] (max 10. Extract answers into these custom fields), analysisInput? (“transcript” (default) | “audio” | “video”): what the model receives. “audio” lets it hear tone and delivery, “video” also lets it see what is on screen; on a video file “audio” extracts the audio track first. Premium: requires the account’s audio/video analysis opt-in, and costs credits per hour of media } • translation -> translation: { targetLanguage: region-qualified locale code, e.g. “es-ES”, “fr-FR” (bare codes like “es” are rejected) } • filter -> filter: { logic: “AND”|“OR” (default “AND”), rules: [{ field, op, value? }] (1-20) }. The run continues only when the rules match, otherwise it stops silently • condition -> condition: same { logic, rules } shape as filter, but instead of stopping it routes: downstream steps marked branch:“true”/“false” run according to the outcome. Branch wiring rules, all enforced before the request is sent: • A leg is a CHAIN: the first step of a leg depends on the condition, the rest depend on the step before them in the same leg, and every step on the leg carries the same branch marker. • A step that runs after the branch (a merge) depends on the LAST step of every leg that carries on. When a leg is empty its last step IS the condition, and the merge then carries that leg’s marker. • A leg ends the run simply by having nothing depend on its last step. • Once anything carries a branch marker, EVERY other step needs a dependsOn: a step with no parents is an entry point and runs on both branches, and a second entry point is rejected. • A condition with no steps on either side is rejected: both paths would do the same thing. • Branches nest at most three deep, and a nested condition must be the last step of the leg it sits on, or the automation cannot be reopened in the Speak web editor. • A scheduled automation cannot branch: a schedule runs over a batch and a condition resolves once for the whole batch, so the leg would run against media that did not match. Use a filter, which narrows the batch. • notify -> notify: { channel: “in_app”|“email”|“slack”, target?, message (required, tokens allowed) } • outbound-webhook -> outboundWebhook: { url (required, tokens allowed), method? (“GET”|“POST”|“PUT”|“PATCH”|“DELETE”, default “POST”), headers?: { <name>: <value> }, bodyTemplate?: string | object (tokens allowed) } • composio-action -> composio: { app, action, connectedAccountId?, argsTemplate? } (Composio is currently behind a server flag and may be unavailable) Filter/condition rule fields depend on what flows into the step: MEDIA -> name|duration|sourceLanguage|tags|transcript|speakers or a custom field id; INSIGHT (straight after a magic-prompt step) -> answer only, so put a branch on a media field BEFORE the AI step. Neither a filter nor a condition can read the inbound webhook payload (they see the media and earlier step answers only) so a payload path such as “contact.status” is refused: upload first with speakUpload.fieldsMap to write that value into a custom field, then test the field id instead. Ops by field type. Text: eq|neq|contains|ncontains|startsWith|exists; number: eq|neq|gt|lt|exists; array: contains|ncontains|exists (“exists” takes no value; gt/lt values are numbers). Token syntax (usable in fields marked ‘tokens allowed’): {{trigger.payload.<path>}} reads the inbound webhook payload (dot paths and [n] array indices; paths are relative to trigger.childKey when set. Discover valid paths with get_inbound_webhook after sending a test payload); {{step.<stepId>.<path>}} reads a previous step’s output (speak-upload -> mediaId, magic-prompt -> answer, outbound-webhook -> status/response). A positional {{step.<index>.<path>}} form also exists but is REFUSED on a branched automation: the index counts stored order ([condition, true leg, false leg, merge]), not run order, and a step on the branch that was not taken produces nothing. The token would resolve to an empty string inside whatever the step sends.
trigger object No Trigger object (the automation’s root). Always include triggerSlug. Supported shapes: • Media analyzed in folder(s): { type: “folders”, triggerSlug: “media_analyzed”, folderIds: string[] (min 1) } • Inbound webhook (receive external payloads): { type: “folders”, triggerSlug: “inbound_webhook”, webhookId? (from provision_inbound_webhook; omit to auto-provision a new one on create), childKey? (dot-path narrowing which part of the payload feeds the automation, e.g. “data”) }. The create/update response includes inboundWebhook.inboundUrl: the public URL to POST payloads to. • Custom field updated: { type: “folders”, triggerSlug: “field_updated”, values: string[] (watched custom field ids, min 1), fieldValueMatches?: [{ fieldId, values: string[] }] (fire only when the field changes TO one of these values; empty values = any change), fieldMatchLogic?: “AND”|“OR” (how multiple fieldValueMatches combine, default “OR”) } • Composio app event: { type: “composio”, provider: “composio”, app, triggerSlug, connectedAccountId } (requires a connected account; may be behind a server flag) Notes: “tags”/“keywords” trigger types are rejected for graph automations. The server stores inbound-webhook triggers with type “webhook” internally: send type “folders” plus the slug as shown above.
runType enum: instant, schedule No Run type the graph would be saved with. A schedule refuses any branch.

Behaviour

The Speak AI MCP server publishes these behaviour hints for validate_automation_graph.

  • Only reads data. Does not modify your workspace.
  • Does not delete or overwrite existing data.
  • Repeating an identical call is safe.
  • Stays inside Speak AI. Does not reach other systems.
  • Automations lists the rest of the Automations category.
  • Tool reference lists every Speak AI MCP server tool.
  • MCP server covers setup, supported clients, and what agents can do once connected.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close