Agent Skill · Frontline

frontline-workflows

Create, edit, connect, inspect, and delete Frontline automation workflows using the Frontline CLI. Use when the user asks to build workflows, add nodes or edges, manage workflow context, inspect status, or view analytics.

Provider: Frontline Path in repo: frontline-workflows/SKILL.md

Skill body

Prerequisites

Commands

List all workflows

frontline workflows list [--status <status>] [--table] [--debug]

Output is JSON by default (--json is accepted as a documented no-op — it never changes behavior). Use --table/--pretty to get human-readable output instead.

Flag Description
--status <status> Filter by status: active, inactive, or draft
--table Render as a human-readable table instead of JSON
--api-key <key> Override the stored API key for this request
--profile <name> Use a specific CLI profile
--debug Show HTTP request/response diagnostics

Example:

# List all workflows as JSON (default)
frontline workflows list

# List only active workflows as a table
frontline workflows list --status active --table

Output columns: id, name, status, triggerType, runsCount, lastRunDate

Create and select a workflow

frontline workflows create --name "Daily CRM Sync" [--description "..."]
frontline workflows use <workflowId>
frontline workflows describe [--include-nodes]
frontline workflows graph [--table]

create saves the created workflow ID as the active workflow for the current profile. use changes the active workflow. All graph commands accept --workflow-id <id> to override the active workflow, which is preferred for scripts and CI.

Update or delete a workflow

frontline workflows update --status ACTIVE          # name is optional; fetched automatically if omitted
frontline workflows update --name "Daily CRM Sync" --status ACTIVE
frontline workflows delete

Use a USER API key for mutations. GENERAL keys can still read account-level workflow data where the API allows it.

Manage variables

Workflow variable commands use the active workflow by default. Override with --workflow-id <id> in scripts and CI.

frontline workflows variables list --table
frontline workflows variables all
frontline workflows variables create --name order_id --description "Order ID"
frontline workflows variables describe 123
frontline workflows variables update 123 --name order_id --pattern "^[0-9]+$"
frontline workflows variables delete 123
frontline workflows variables check-name order_id

Use variables inside text fields as {VARIABLE_NAME}. Automation workflows also make each node output available by node ID — node IDs follow the node_<uuid> format, so a node with nodeId node_a1b2c3d4-e5f6-7890-abcd-ef1234567890 is referenced downstream as {node_a1b2c3d4-e5f6-7890-abcd-ef1234567890}.

Building Workflow Graphs

Always inspect the graph before changing it:

frontline workflows graph --table
frontline workflows nodes list --table

Node identity

Do not send nodeId or alias in nodes create. The server assigns both and returns them in the 201 JSON. Use frontline workflows graph --table or the create response before edges add or {node_<uuid>} references. Custom aliases: nodes update <nodeId> --data '{"alias":"..."}'.

Create nodes

The full trigger reference (all triggerType values — CONTACT_CREATED, CONTACT_UPDATED, CONVERSATION_ENDED, FEEDBACK_CAPTURED, CONVERSATION_IDLE, INCOMING_WEBHOOK, OBJECT_RECORD_CREATED, COMPOSIO_TRIGGER — plus SCHEDULED_TRIGGER, with required fields and payload variables) lives in the workflow-builder skill. Two common examples follow.

Trigger node (CONTACT_CREATED):

frontline workflows nodes create --data '{"type":"TRIGGER","position":{"positionX":0,"positionY":0},"data":{"type":"TRIGGER","triggerType":"CONTACT_CREATED"}}'

Conversation trigger (CONVERSATION_ENDED, CONVERSATION_IDLE, FEEDBACK_CAPTURED) — these fire per agent, so triggeredByAgentIds is required. Without it the node saves but the workflow never runs:

frontline agents list --table   # copy the agent uuid from the id column
frontline workflows nodes create --data '{"type":"TRIGGER","position":{"positionX":0,"positionY":0},"data":{"type":"TRIGGER","triggerType":"CONVERSATION_IDLE","triggeredByAgentIds":["550e8400-e29b-41d4-a716-446655440000"]}}'

Do not set triggeredBy to USER on these — conversation events always come from the agent. CONVERSATION_IDLE additionally requires enableIdle and idleSettings on the agent’s channel (frontline agents settings get/update <channel>). See the workflow-builder skill for the full walkthrough.

Incoming webhook trigger — first create the webhook resource:

frontline incoming-webhooks create --name "My Webhook"
# Save the returned id
frontline workflows nodes create --data '{"type":"TRIGGER","position":{"positionX":0,"positionY":0},"data":{"type":"TRIGGER","triggerType":"INCOMING_WEBHOOK","triggerByWebhookIds":["<incoming-webhook-id>"]}}'

When this fires, the POST body is available as {webhook_payload} in all downstream nodes.

Integration trigger (COMPOSIO_TRIGGER) — fires on a third-party event such as a new Google Drive file or Gmail message. Requires connectedAccountId + triggerToolkit (both from frontline integrations list --table) and a triggerSlug:

frontline workflows nodes create --data '{"type":"TRIGGER","position":{"positionX":0,"positionY":0},"data":{"type":"TRIGGER","triggerType":"COMPOSIO_TRIGGER","connectedAccountId":42,"triggerToolkit":"GOOGLEDRIVE","triggerSlug":"GOOGLEDRIVE_FILE_CREATED_TRIGGER"}}'

Saving the node subscribes with the provider and fills in connectedAccountTriggerId — never send that field yourself. The event body arrives as {trigger_payload}.

Discover slugs and config fields instead of guessing (an unlisted slug fails with Unsupported trigger: <slug>, and a misnamed config key fails with Unknown trigger config field):

frontline integrations trigger-types --toolkit GOOGLEDRIVE --table
frontline integrations trigger-resources --type googledrive_folders --connected-account-id 42 --table

trigger-types lists each event’s required and optional triggerConfig fields and which of them have a picker; trigger-resources returns the actual ids to put in those fields. See the workflow-builder skill for the full walkthrough.

Scheduled trigger (cron) is a different node type, not a triggerType. startTime and endTime are nullable but must be present:

frontline workflows nodes create --data '{"type":"SCHEDULED_TRIGGER","position":{"positionX":0,"positionY":0},"data":{"type":"SCHEDULED_TRIGGER","cronExpression":"0 9 * * 1-5","timezone":"America/New_York","startTime":null,"endTime":null,"frequency":"DAILY"}}'

The cron job only runs while the workflow is ACTIVE; setting it back to DRAFT disables the schedule.

API action node (two fixed outgoing handles: success/fail — the canvas never renders a default handle for this node type; connecting default is rejected):

frontline workflows nodes create --data '{"type":"API","position":{"positionX":320,"positionY":0},"data":{"type":"API","url":"https://example.com","method":"GET","headers":[]}}'
frontline workflows edges add --source <api-node-id> --source-handle success --target <next-node-id> --target-handle default
frontline workflows edges add --source <api-node-id> --source-handle fail --target <error-node-id> --target-handle default

Supported automation node types:

TRIGGER, SCHEDULED_TRIGGER, WEBHOOK, TOOLS_AI, API, CONDITIONAL_ROUTING, AI_CAPTURE, DATA_TRANSFORMER, DYNAMIC_TABLES, CREATE_RECORD_ACTIVITY, ITERATION, BREAK, AUTOMATION_STATUS, SEND_MESSAGE, SEND_WHATSAPP_MESSAGE, TRANSCRIPTION, FILE_ANALYSIS.

Integrations (read-only — for Send WhatsApp Message nodes)

frontline channels list --table
frontline channels whatsapp-templates --table

Use channels list to pick a phoneNumberId where canSendMessages is true. Use channels whatsapp-templates to pick an approved template name.

For OAuth connected accounts (Google Sheets, Gmail, etc.), use frontline integrations list --table and pass the returned id as connectedAccountId.

Loop (ITERATION) node

Wire type is ITERATION. Iterates an array variable with three handles: body, completed, empty.

frontline workflows nodes create --data '{"type":"ITERATION","position":{"positionX":320,"positionY":0},"data":{"type":"ITERATION","variableName":"items","variablePath":"data.items","continueOnError":false}}'
# Use the nodeId returned above (<loop-node-id>) for all three edges:
frontline workflows edges add --source <loop-node-id> --source-handle body --target <body-node> --target-handle default
frontline workflows edges add --source <loop-node-id> --source-handle completed --target <after-loop> --target-handle default
frontline workflows edges add --source <loop-node-id> --source-handle empty --target <empty-handler> --target-handle default

Inside the loop, use the loop node’s nodeId (from frontline workflows graph --table):

No sub-properties: {<loopNodeId>.item.id} / {<loopNodeId>.item.phone} do not work. To use one field per iteration, loop over scalars and use {<loopNodeId>.item} directly, or extract a field inside the loop with AI_CAPTURE / DATA_TRANSFORMER.

Limits: At most 50 items per loop invocation. More than 50 items fails the automation run before the loop body starts (no partial processing). Max 500 automation execution steps total.

For DYNAMIC*TABLES SEARCH output, the result is a top-level array of rows — set variablePath empty when looping over {node*<search-node-id>}.

Send WhatsApp Message node

frontline workflows nodes create --data '{"type":"SEND_WHATSAPP_MESSAGE","position":{"positionX":640,"positionY":0},"data":{"type":"SEND_WHATSAPP_MESSAGE","recipientMode":"PHONE_NUMBER","personName":"{first_name} {last_name}","phoneNumber":"{phone_number}","phoneNumberId":"<meta-phone-number-id>","template":"hello_world","templateVariables":{"body":{"1":"{first_name}"}}}}'

DYNAMIC_TABLES node

Used to create, update, delete, search, or change the record type of records in an object. Always get the object schema first:

frontline object get <object-name>
# id → tableId, record_types[0].id → recordTypeId, fields[].name → rowData keys

rowData maps field names (e.g. "First Name", "Email") — not UUIDs — to static values or {VARIABLE_NAME} references. inputModeByField sets "INPUT" (static) or "VARIABLE" (interpolated) per field name. All variables used must exist and be populated by a prior node.

Variables are plain text substitutions{my_var} is replaced with the exact string stored in that variable. There is no dot-access: {webhook_payload.firstName} is not valid.

frontline workflows nodes create --data '{"type":"DYNAMIC_TABLES","position":{"positionX":640,"positionY":0},"data":{"type":"DYNAMIC_TABLES","tableId":2,"recordTypeId":2,"actionType":"CREATE","rowData":{"First Name":"{first_name}","Email":"{email}"},"inputModeByField":{"First Name":"VARIABLE","Email":"VARIABLE"}}}'

actionType values: CREATE, UPDATE, DELETE, SEARCH, SEARCH_BY_ID, CHANGE_RECORD_TYPE.

Required fields per action (the Public API returns 400 at create/update if missing): CREATErowData; UPDATErowId + rowData; DELETE / SEARCH_BY_IDrowId; CHANGE_RECORD_TYPErowId + targetRecordTypeId (the destination record type id).

FILE_ANALYSIS node

Runs OCR + AI analysis on a file from a URL (PDF, image, scanned doc). Produces two outputs: the extracted OCR text and an XML analysis guided by prompt.

frontline workflows nodes create --data '{"type":"FILE_ANALYSIS","position":{"positionX":640,"positionY":0},"data":{"type":"FILE_ANALYSIS","fileUrl":"{document_url}","prompt":"Extract the invoice total and vendor name.","model":"<external_id_from_ai_models_list>","aiVendor":"<vendor_from_same_row>","captureVariables":[{"id":<analysis_var_id>,"name":"<analysis_var_name>","description":"XML analysis output"}],"captureOcrVariable":{"id":<ocr_var_id>,"name":"<ocr_var_name>","description":"Extracted OCR text"}}}'

Connect nodes

frontline workflows edges add \
  --source node_11111111-1111-1111-1111-111111111111 \
  --source-handle default \
  --target node_22222222-2222-2222-2222-222222222222 \
  --target-handle default

The API enforces one outgoing edge per node (except CONDITIONAL_ROUTING, TOOLS_AI, and API, which support multiple outgoing handles), no self-edges, source/target existence, and no cycles.

Edit and delete nodes

frontline workflows nodes update node_22222222-2222-2222-2222-222222222222 --data '{"alias":"Fetch external data"}'
frontline workflows nodes delete node_22222222-2222-2222-2222-222222222222

Deleting a node also removes incoming and outgoing edges.

Remove an edge

frontline workflows edges remove \
  --source node_11111111-1111-1111-1111-111111111111 \
  --source-handle default \
  --target node_22222222-2222-2222-2222-222222222222 \
  --target-handle default

Validation Checklist

Variable Interpolation

Interpolable workflow fields include API url, headers[].value, parameters[].value, body; Send Message / Say AI message and prompt; Response AI instructions; Tools AI instructions and prompt; AI Capture prompt and instructions; Data Transformer prompt; Conditional Routing AI conditions[].expression; Dynamic Tables rowId, search, rowData values; Transcription audioUrl; and WhatsApp template variables in templateVariables.header, templateVariables.body, and templateVariables.buttons.

Each node’s output is also available as {nodeId} in downstream nodes.

Get analytics for a specific workflow

frontline workflows analytics [workflowId] [--workflow-id <id>] [--start-date <YYYY-MM-DD>] [--end-date <YYYY-MM-DD>] [--table] [--debug]

Output is JSON by default (--json is accepted as a no-op). Use --table/--pretty for the summary + table view.

Flag Description
<workflowId> Optional workflow ID
--workflow-id <id> Override the active workflow
--start-date <date> Start date in YYYY-MM-DD format
--end-date <date> End date in YYYY-MM-DD format
--table Human-readable summary + table
--api-key <key> Override API key
--profile <name> Use a specific CLI profile
--debug Show HTTP request/response diagnostics

Example:

# Get workflow analytics for a date range as JSON (default)
frontline workflows analytics 42 --start-date 2025-01-01 --end-date 2025-01-31

# Get workflow analytics as a human-readable table
frontline workflows analytics 42 --table

Output: Summary section, Runs by Date table (date, totalRuns, successfulRuns, failedRuns, totalCredits).

Read run logs

Every workflow run records an execution log. List them to audit results or debug failures; get one log to see the per-node results.

frontline workflows logs [workflowId] [--workflow-id <id>] [--status <s>] [--start-date <YYYY-MM-DD>] [--end-date <YYYY-MM-DD>] [--page <n>] [--page-size <n>] [--table]
frontline workflows logs get <logId> [--workflow-id <id>] [--pretty]
frontline workflows logs trace <logId> <nodeResultId> [--workflow-id <id>] [--pretty]

Output is JSON by default (--json is accepted as a no-op).

Flag Description
--workflow-id <id> Override the active workflow
--status <s> Filter by run status (e.g. SUCCESS, FAILED)
--start-date <date> Start date in YYYY-MM-DD format
--end-date <date> End date in YYYY-MM-DD format
--table / --pretty Human-readable output

Examples:

# List recent runs as a table
frontline workflows logs --workflow-id 2 --table

# Only failed runs since a date
frontline workflows logs --workflow-id 2 --status FAILED --start-date 2025-01-01

# Inspect one run with its per-node results
frontline workflows logs get 9001 --workflow-id 2 --pretty

# Drill into one node's full execution trace within that run
frontline workflows logs trace 9001 7001 --workflow-id 2 --pretty

Output: list = runs (id, successful, started_at, completed_at, duration, ai_credits, error); detail adds a node_results table (id, node_id, alias, type, success, ai_credits, error, audit_log_id).

Tracing: a run is many node results; the UI shows the audit log per node. Each node_results row has its own id and an audit_log_id when it has a trace. logs trace <logId> <nodeResultId> returns that one node’s full execution trace — fetched per node, never the whole run at once.

Troubleshooting


See also

Skill frontmatter

allowed-tools: Bash(frontline:*)

Work with this as data

Every skill here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for agent skills

4 MCP tools reach this
  • find_skillsBrowse and filter every skill in the catalog.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This skill
curl "https://apis.io/api/v1/skills/frontline-workflows"
All agent skills
curl "https://apis.io/api/v1/skills?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.