Files
inkreach-teable-cli/.agents/skills/inkreach-teable/guides/automation-guide.md
T
yeuimu 73998173a8 docs(skill): update formSubmitted trigger docs for multi-form support
Reflect the formId(formId) -> formIds[] change across skill + CLI + docs:
- skill api-reference/trigger-types.md: formIds array config + legacy note
- skill guides (automation-guide.md, cli-reference.md): --form-ids <csv>
- inkreach-cli: add --form-ids option (csv parse), keep --form-id legacy
- docs/automation/triggers.md: P1 formSubmitted marked done
- docs/automation/README.md: formSubmitted config fields updated
2026-08-12 03:59:12 +00:00

8.3 KiB

Automation Guide

Automations (workflows) are event-driven: a trigger fires, then actions run in topological order. inkreach-teable's automation engine is self-built — use the inkreach-teable CLI (not official teable).

Required reading before configuring triggers: trigger-types.md Required reading before writing script actions: action-types.md

Mental Model

[Trigger] → [Action 1] → [Action 2] → ... → [triggerEnd]
  • A workflow has exactly one trigger node (type trigger) and N action nodes (type action).
  • Nodes connect via edges (linear chain; each node has at most one upstream — no parallel branches).
  • Activating freezes a snapshot; execution runs against the snapshot, not the draft.
  • hasDraft: true = unactivated changes exist; re-activate to apply.

Available Commands

Command Purpose
workflow list List all workflows in the base
workflow get <id> Detail (nodes + edges + config)
workflow create --name <n> Create (auto-adds a recordCreated trigger)
workflow update <id> [--name] [--description] Rename
workflow delete <id> Soft-delete
workflow activate <id> Snapshot + register trigger + create auto-token
workflow deactivate <id> Unregister trigger
workflow test <id> Mock-input test run (no trigger, no queue)
trigger set <id> --type <T> ... Set trigger type + config
action add <id> --type <T> ... Add an action node
action update <id> <nodeId> ... Update an action node
action delete <id> <nodeId> Remove an action node
secret set/list/delete Manage script secrets
runs list/get/rerun Execution history
fire button-click/webhook Manually trigger for testing

Trigger Selection

User scenario --type Key options
React to new records recordCreated --table-id
React to record changes recordUpdated --table-id, --field-ids (empty = all)
React when a condition matches recordCondition --table-id, --conditions (required)
React to create OR update recordCreatedOrUpdated --table-id, --conditions (optional)
Form submission formSubmitted --table-id, --form-ids <csv>
Schedule (only type+interval work) scheduledTime --schedule '{"timing":{"type":"minutes","interval":5}}'
Button field click buttonClick --table-id, --field-ids
External HTTP POST webhook (none; auth backend-ignored)

Batch processing (record triggers only): add --batch '{"enabled":true,"batchWindow":2000,"batchSize":100}' to merge events within a window into a single run. The script receives an array of records.

Full config details: trigger-types.md.

Action Selection

Goal --type Key options
Run JS code (transform, call APIs, compute) script --code '<js>' or --code-file <path>, --timeout <ms>
Send email sendEmail --to, --subject, --body <html>
Call external HTTP httpRequest --url, --method, --headers <json>, --req-body <json>
Create records createRecord --target-table <id>, --records <json>
Update records updateRecord --target-table <id>, --records <json>
Query records getRecords --target-table <id>, --query <json>

Full config details: action-types.md.

Creation Workflow

# 1. Gather IDs
inkreach-teable table get tblXXX        # confirm table
inkreach-teable field list tblXXX       # find field ids for triggers

# 2. Create workflow
inkreach-teable workflow create --name "My automation"
# → returns wflXXX

# 3. Set trigger
inkreach-teable trigger set wflXXX --type recordUpdated \
  --table-id tblXXX --field-ids '["fldStatus"]'

# 4. Add action(s)
inkreach-teable action add wflXXX --type script \
  --code 'return { status: triggerInput.record.fields.Status }'

# 5. (Optional) add secrets the script needs
inkreach-teable secret set wflXXX --name API_KEY --value sk_xxx

# 6. Activate
inkreach-teable workflow activate wflXXX
# → returns snapshotId

# 7. Test
inkreach-teable fire button-click tblXXX recXXX fldXXX   # for buttonClick
# or just perform the triggering action (create/update a record, POST webhook...)
inkreach-teable runs list wflXXX

Editing an Existing Workflow

# Change trigger config
inkreach-teable trigger set wflXXX --type buttonClick --table-id tblXXX --field-ids '["fldNew"]'
# Add another action
inkreach-teable action add wflXXX --type sendEmail --to a@b.com --subject Done --body '<p>ok</p>'
# Remove an action
inkreach-teable action delete wflXXX node-12345
# RE-ACTIVATE to snapshot the changes
inkreach-teable workflow activate wflXXX

trigger set / action add/update/delete internally do GET→modify→PUT the whole graph, so they're safe. But you must re-activate for changes to take effect at runtime.

Secrets

Scripts often need API keys. Never hardcode — use secrets.

inkreach-teable secret set wflXXX --name OPENAI_KEY --value sk-xxx --description "for AI calls"
inkreach-teable secret list wflXXX           # names only — value never returned
inkreach-teable secret update wflXXX secXXX --value sk-new
inkreach-teable secret delete wflXXX secXXX

In a script action, read via process.env.OPENAI_KEY. Secrets are AES-encrypted at rest.

Testing / Triggering

Most triggers fire from real events (record create/update, form submit, schedule). Two triggers are manually fireable for testing:

# Button field click
inkreach-teable fire button-click <tableId> <recordId> <fieldId>

# Webhook (no auth needed)
inkreach-teable fire webhook <baseId> <workflowId> --body '{"event":"test"}'

For other triggers, test by performing the real action (create/update a record, submit the form). Then inspect:

inkreach-teable runs list wflXXX --status failed
inkreach-teable runs get wflXXX <executionId>
# rerun a failed execution
inkreach-teable runs rerun wflXXX <executionId>

workflow test vs real fire

workflow test <id> runs actions synchronously with mock input (a fake {record:{id:'rec_test',fields:{}}, user:{...}}). It does NOT fire the trigger or use the queue. Two caveats:

  • Upstream outputs are absent in test mode — if a script reads triggerInput.record.fields.<X>, it gets {} because the mock record has no fields. Test only validates that the script runs without throwing, not that it produces correct data.
  • For data-dependent validation, do a real fire (button-click / webhook) or perform the real triggering action, then check runs list.

Variable References (cross-node data)

An action can reference upstream nodes' output in string fields via {{nodeIndex.path}}:

  • {{1.record.id}} — trigger record's id (trigger = node 1)
  • {{1.record.fields.Status}} — trigger record's Status field
  • {{2.records}} — output of the first action (node 2)

Node index follows topological execution order (trigger is always 1). Script actions can also read the merged upstream output directly via triggerInput.

Common Patterns

Notify on status change

inkreach-teable workflow create --name "Status→email"
inkreach-teable trigger set wflXXX --type recordUpdated --table-id tblXXX --field-ids '["fldStatus"]'
inkreach-teable action add wflXXX --type sendEmail \
  --to ops@x.com --subject 'Status changed' \
  --body '{{1.record.fields.Status}}'
inkreach-teable workflow activate wflXXX

Daily digest

inkreach-teable trigger set wflXXX --type scheduledTime \
  --schedule '{"timing":{"type":"hours","interval":24}}'

Button → script → update another table

inkreach-teable trigger set wflXXX --type buttonClick --table-id tblA --field-ids '["fldGo"]'
inkreach-teable action add wflXXX --type script --code '
  const r = triggerInput.record;
  // call back into the instance API using the auto-injected token
  const res = await fetch(triggerInput._apiBaseUrl + "/api/table/tblB/record", {
    method: "POST",
    headers: { Authorization: "Bearer " + triggerInput._accessToken, "Content-Type": "application/json" },
    body: JSON.stringify({ fields: { Source: r.id } })
  });
  return { created: await res.json() };
'