Docs

Node Types

Reference for trigger, task, code, and human nodes, including configs and runtime context.

Gondo workflows use four node types: trigger, task, code, and human.

Shared node fields

Most nodes share this shape:

id: example_node
type: task
title: Example node
goal: One short sentence for people reading the graph.
integrations:
  - finance_gmail
config: {}
ui:
  x: 0
  y: 0

integrations lists the integration reference IDs the node is allowed to use.

Trigger nodes

Triggers start workflows.

Command trigger

Use a command trigger when the workflow starts from chat, a manual run, or a command-style invocation.

type: trigger
title: Run
config:
  kind: command
  name: review-invoices
  dataSchema:
    type: object
    properties:
      folderId:
        type: string
    required: [folderId]

The config.name field above names the command trigger, not the workflow itself.

The trigger output is available downstream as ctx.data.<triggerNodeId>.

Auto trigger

Use an auto trigger when the workflow should run on a schedule.

type: trigger
title: Weekday check
config:
  kind: auto
  cron: '0 9 * * 1-5'
  timezone: Europe/London

An auto trigger can also run code before starting workflow runs.

type: trigger
title: New Gmail messages
integrations:
  - finance_gmail
config:
  kind: auto
  cron: '*/15 * * * *'
  code: |
    const gmail = getIntegration('finance_gmail')
    const messages = await (await gmail.get('/messages?q=invoice')).json()

    for (const message of messages.messages ?? []) {
      await triggerWorkflow({ messageId: message.id })
    }
  dataSchema:
    type: object
    required: [messageId]
    properties:
      messageId:
        type: string

Auto trigger code can use store.get, store.set, store.delete, and triggerWorkflow(data).

Task nodes

A task node is an AI reasoning step.

Use it when the workflow needs judgement, classification, drafting, document reading, messy data handling, or adaptable browser work.

type: task
title: Classify invoice
goal: Decide whether the invoice needs review.
integrations:
  - finance_gmail
config:
  instruction: |-
    Read the invoice email identified by ctx.data.new_email.messageId.
    Return whether it needs human review.
    If the amount is missing, set needsReview to true and explain why.
  dataSchema:
    type: object
    required: [needsReview, reason]
    properties:
      needsReview:
        type: boolean
      reason:
        type: string

The task node returns structured data matching dataSchema.

Code nodes

A code node runs deterministic JavaScript.

Use it for API calls, structured writes, file movement in the workflow workspace, or transformations where the input shape is already clear.

type: code
title: Add row to sheet
goal: Write approved invoice data to the finance sheet.
integrations:
  - finance_sheets
config:
  code: |
    const sheets = getIntegration('finance_sheets')
    const invoice = ctx.data.classify_invoice
    const response = await sheets.post('/values/A1:append', {
      values: [[invoice.supplierName, invoice.amount]]
    })
    const result = await response.json()
    return { updatedRange: result.updates?.updatedRange ?? null }
  dataSchema:
    type: object
    required: [updatedRange]
    properties:
      updatedRange:
        type: [string, 'null']

Code nodes can use:

  • ctx.data
  • ctx.run
  • ctx.vars
  • getIntegration('<referenceId>')
  • log(...)

External provider calls must go through getIntegration().

Human nodes

A human node pauses the workflow.

Use it when a person should review, approve, edit, or provide information.

Human node UI is stored as a Vue single-file component in config.component. When completed, its final state becomes ctx.data.<nodeId>.

type: human
title: Approve invoice
goal: Ask finance to approve or reject the invoice.
config:
  dataSchema:
    type: object
    required: [decision, notes]
    properties:
      decision:
        type: string
        enum: [approved, rejected]
      notes:
        type: string
  component: |
    <template>
      <section>
        <p>Approve this invoice?</p>
        <button type="button" @click="approve">Approve</button>
      </section>
    </template>

    <script setup>
    const { submitAction } = defineProps({
      submitAction: { type: Function, required: true }
    })

    function approve() {
      submitAction('approve', { notes: '' })
    }
    </script>

    <script backend>
    export async function approve(state, inputs) {
      return { ...state, decision: 'approved', notes: inputs.notes, done: true }
    }
    </script>

Human nodes should render both an active input state and a completed recap state.