SKILL.md
Automate WhatsApp
When to use
Use this skill to build and run WhatsApp automations: workflow CRUD, graph edits, triggers, executions, function management, app integrations, and D1 database operations.
Setup
Preferred path:
- Kapso CLI installed and authenticated (
kapso login)
- For workflow and function edits, use source-controlled projects with
kapso link,kapso pull,kapso build, andkapso push
- For workflow code, use
@kapso/workflowsand export aWorkflowinstance fromworkflow.jsorworkflow.ts
Fallback path:
Env vars:
KAPSO_API_BASE_URL(host only, no/platform/v1)
KAPSO_API_KEY
How to
Edit workflows locally
Use this path first when the user is working in, or can create, a local repo.
npm install -g @kapso/cli
npm install --save-dev @kapso/workflows
kapso login
kapso link --project <project-id>
kapso pull
Edit workflows/<workflow-slug>/workflow.js or workflow.ts with @kapso/workflows:
import { START, Workflow } from "@kapso/workflows";
const workflow = new Workflow("inbound-support", {
name: "Inbound Support",
status: "draft",
});
workflow.addTrigger({
type: "inbound_message",
phoneNumberId: "<phone-number-id>",
});
workflow.addNode(START, {
position: { x: 100, y: 100 },
});
workflow.addNode("reply", {
type: "send_text",
message: "Thanks for reaching out.",
});
workflow.addEdge(START, "reply");
export default workflow;
Build and push:
kapso build
kapso push --dry-run
kapso push workflow <workflow-slug>
Use kapso push to push every local function and workflow. See references/local-workflow-source.md for repo layout, source-file behavior, and JSON-only editing.
Discover phone numbers first
Preferred path:
- Check project state:
kapso status
- List connected numbers:
kapso whatsapp numbers list --output json
- Resolve a display number when needed:
kapso whatsapp numbers resolve --phone-number "<display-number>" --output json
Fallback path:
- List number configs for triggers:
node scripts/list-whatsapp-phone-numbers.js
Edit a workflow graph through API scripts
Prefer local source sync for workflow edits. Use these scripts as a fallback for debugging, direct graph inspection, or API-only environments.
- Fetch graph:
node scripts/get-graph.js <workflow_id>(note thelock_version)
- Edit the JSON (see graph rules below)
- Validate:
node scripts/validate-graph.js --definition-file <path>
- Update:
node scripts/update-graph.js <workflow_id> --expected-lock-version <n> --definition-file <path>
- Re-fetch to confirm
For small edits, use edit-graph.js with --old-file and --new-file instead.
If you get a lock_version conflict: re-fetch, re-apply changes, retry with new lock_version.
Manage triggers
- List:
node scripts/list-triggers.js <workflow_id>
- Create:
node scripts/create-trigger.js <workflow_id> --trigger-type <type> --phone-number-id <id>
- Toggle:
node scripts/update-trigger.js --trigger-id <id> --active true|false
- Delete:
node scripts/delete-trigger.js --trigger-id <id>
For inbound_message triggers, prefer kapso whatsapp numbers resolve --phone-number "<display-number>" --output json to get the exact phone_number_id. Fall back to node scripts/list-whatsapp-phone-numbers.js when the CLI is unavailable.
Debug executions
- List:
node scripts/list-executions.js <workflow_id>
- Inspect:
node scripts/get-execution.js <execution-id>
- Get value:
node scripts/get-context-value.js <execution-id> --variable-path vars.foo
- Events:
node scripts/list-execution-events.js <execution-id>
Create and deploy a function
- Write code with handler signature (see function rules below)
- Create:
node scripts/create-function.js --name <name> --code-file <path> [--public-endpoint true]
- Deploy:
node scripts/deploy-function.js --function-id <id>
- Verify:
node scripts/get-function.js --function-id <id>
Use --public-endpoint true when the function should be callable without X-API-Key via the Kapso-hosted invoke URL. This is only supported for Cloudflare functions.
New functions default to invoke_response_mode=passthrough, which returns the function body directly on successful invoke. Legacy wrapped functions can be migrated later with update-function.js.
Set up agent node with app integrations
- Find model:
node scripts/list-provider-models.js
- Find account:
node scripts/list-accounts.js --app-slug <slug>(usepipedream_account_id)
- Find action:
node scripts/search-actions.js --query <word> --app-slug <slug>(action_id = key)
- Create integration:
node scripts/create-integration.js --action-id <id> --app-slug <slug> --account-id <id> --configured-props <json>
- Add tools to agent node via
flow_agent_app_integration_tools
Set up agent node with remote sandbox repositories
Use this when the agent needs a remote ephemeral workspace to inspect or modify repository files during a workflow run.
- Read
references/agent-remote-sandbox.mdfor the execution model and field rules
- Find model:
node scripts/list-provider-models.js
- Copy
assets/agent-remote-sandbox-github-repo-example.jsonas a starting point, or edit the agent node underdata.config
- Set
sandbox_enabled: true
- Set
sandbox_network_modetoallow_allorallow_list
- If using
allow_list, add extra outbound hosts insandbox_allowed_outbound_hosts
- Add GitHub repositories to
flow_agent_resourceswith:
resource_type: "github_repository"
repo_url
branch
pat
- Write the system prompt so it explicitly reads from
/workspace/repos/<repo-slug>before making changes
- Validate and update the graph
Notes:
- Remote sandbox is beta and free during the beta
sandbox_enabledcontrols whether the remote workspace and sandbox tools are available
- Repository resources stay configured even if sandbox access is turned off later
- v1 supports GitHub repositories only
- Use a repository root URL, not a GitHub file URL or
tree/...URL
- Repositories are mounted into
/workspace/repos/<repo-slug>inside the remote sandbox
- Use
references/agent-remote-sandbox.mdandreferences/node-types.mdfor the exact shape
Database CRUD
- List tables:
node scripts/list-tables.js
- Query:
node scripts/query-rows.js --table <name> --filters <json>
- Create/update/delete with row scripts
Graph rules
- Exactly one start node with
id=start
- Never change existing node IDs
- Use
{node_type}_{timestamp_ms}for new node IDs
- Non-decide nodes have 0 or 1 outgoing
nextedge
- Decide edge labels must match
conditions[].label
- Edge keys are
source/target/label(notfrom/to)
For full schema details, see references/graph-contract.md.
Function rules
async function handler(request, env) {
// Parse input
const body = await request.json();
// Use env.KV and env.DB as needed
return new Response(JSON.stringify({ result: "ok" }));
}
- Do NOT use
export,export default, or arrow functions
- Return a
Responseobject
Execution context
Always use this structure:
vars- user-defined variables
system- system variables
context- channel data
metadata- request metadata
Scripts
Workflows
Script
Purpose
list-workflows.js
List workflows (metadata only)
get-workflow.js
Get workflow metadata
create-workflow.js
Create a workflow
update-workflow-settings.js
Update workflow settings
Graph
Script
Purpose
get-graph.js
Get workflow graph + lock_version
edit-graph.js
Patch graph via string replacement
update-graph.js
Replace entire graph
validate-graph.js
Validate graph structure locally
Triggers
Script
Purpose
list-triggers.js
List triggers for a workflow
create-trigger.js
Create a trigger
update-trigger.js
Enable/disable a trigger
delete-trigger.js
Delete a trigger
list-whatsapp-phone-numbers.js
List phone numbers for trigger setup
Executions
Script
Purpose
list-executions.js
List executions
get-execution.js
Get execution details
get-context-value.js
Read value from execution context
update-execution-status.js
Force execution state
resume-execution.js
Resume waiting execution
list-execution-events.js
List execution events
Functions
Script
Purpose
list-functions.js
List project functions
get-function.js
Get function details + code
create-function.js
Create a function, optionally with a public invoke endpoint
update-function.js
Update function code, public endpoint setting, or migrate a legacy wrapped function to passthrough
deploy-function.js
Deploy function to runtime
invoke-function.js
Invoke function with payload
list-function-invocations.js
List function invocations
App integrations
Script
Purpose
list-apps.js
Search integration apps
search-actions.js
Search actions (action_id = key)
get-action-schema.js
Get action JSON schema
list-accounts.js
List connected accounts
create-connect-token.js
Create OAuth connect link
configure-prop.js
Resolve remote_options for a prop
reload-props.js
Reload dynamic props
list-integrations.js
List saved integrations
create-integration.js
Create an integration
update-integration.js
Update an integration
delete-integration.js
Delete an integration
Databases
Script
Purpose
list-tables.js
List D1 tables
get-table.js
Get table schema + sample rows
query-rows.js
Query rows with filters
create-row.js
Create a row
update-row.js
Update rows
upsert-row.js
Upsert a row
delete-row.js
Delete rows
OpenAPI
Script
Purpose
openapi-explore.mjs
Explore OpenAPI (search/op/schema/where)
Install deps (once):
npm i
Examples:
node scripts/openapi-explore.mjs --spec workflows search "variables"
node scripts/openapi-explore.mjs --spec workflows op getWorkflowVariables
node scripts/openapi-explore.mjs --spec platform op queryDatabaseRows
Notes
- Prefer file paths over inline JSON (
--definition-file,--code-file)
action_idis the same askeyfromsearch-actions
--account-idusespipedream_account_idfromlist-accounts
- Variable CRUD (
variables-set.js,variables-delete.js) is blocked - Platform API doesn't support it
- Raw SQL execution is not supported via Platform API
References
Read before editing:
- references/local-workflow-source.md - CLI source sync, repo layout, and
@kapso/workflows
- references/graph-contract.md - Graph schema, computed vs editable fields, lock_version
- references/node-types.md - Node types and config shapes
- references/workflow-overview.md - Execution flow and states
Other references:
- references/execution-context.md - Context structure and variable substitution
- references/triggers.md - Trigger types and setup
- references/app-integrations.md - App integration and variable_definitions
- references/agent-remote-sandbox.md - Remote sandbox behavior, repo resources, mounted paths
- references/functions-reference.md - Function management
- references/functions-payloads.md - Payload shapes for functions
- references/databases-reference.md - Database operations
Assets
File
Description
workflow-linear.json
Minimal linear workflow
workflow-decision.json
Minimal branching workflow
workflow-agent-simple.json
Minimal agent workflow
workflow-customer-support-intake-agent.json
Customer support intake
workflow-interactive-buttons-decide-function.json
Interactive buttons + decide (function)
workflow-interactive-buttons-decide-ai.json
Interactive buttons + decide (AI)
workflow-api-template-wait-agent.json
API trigger + template + agent
function-decide-route-interactive-buttons.json
Function for button routing
agent-app-integration-example.json
Agent node with app integrations
agent-remote-sandbox-github-repo-example.json
Agent node with remote sandbox + GitHub repo resource
Related skills
integrate-whatsapp- Onboarding, webhooks, messaging, templates, flows
observe-whatsapp- Debugging, logs, health checks
[automate-whatsapp file map]|root: .
|.:{package.json,SKILL.md}
|assets:{agent-app-integration-example.json,agent-remote-sandbox-github-repo-example.json,databases-example.json,function-decide-route-interactive-buttons.json,functions-example.json,workflow-agent-simple.json,workflow-api-template-wait-agent.json,workflow-customer-support-intake-agent.json,workflow-decision.json,workflow-interactive-buttons-decide-ai.json,workflow-interactive-buttons-decide-function.json,workflow-linear.json}
|references:{agent-remote-sandbox.md,app-integrations.md,databases-reference.md,execution-context.md,function-contracts.md,functions-payloads.md,functions-reference.md,graph-contract.md,local-workflow-source.md,node-types.md,triggers.md,workflow-overview.md,workflow-reference.md}
|scripts:{configure-prop.js,create-connect-token.js,create-function.js,create-integration.js,create-row.js,create-trigger.js,create-workflow.js,delete-integration.js,delete-row.js,delete-trigger.js,deploy-function.js,edit-graph.js,get-action-schema.js,get-context-value.js,get-execution-event.js,get-execution.js,get-function.js,get-graph.js,get-table.js,get-workflow.js,invoke-function.js,list-accounts.js,list-apps.js,list-execution-events.js,list-executions.js,list-function-invocations.js,list-functions.js,list-integrations.js,list-provider-models.js,list-tables.js,list-triggers.js,list-whatsapp-phone-numbers.js,list-workflows.js,openapi-explore.mjs,query-rows.js,reload-props.js,resume-execution.js,search-actions.js,update-execution-status.js,update-function.js,update-graph.js,update-integration.js,update-row.js,update-trigger.js,update-workflow-settings.js,upsert-row.js,validate-graph.js,variables-delete.js,variables-list.js,variables-set.js}
|scripts/lib/databases:{args.js,filters.js,kapso-api.js}
|scripts/lib/functions:{args.js,kapso-api.js}
|scripts/lib/workflows:{args.js,kapso-api.js,result.js}