Skip to content

04. Integration Catalog

The complete list of things a CALL node can do. Put one of the ids below in integration:, then fill input: with the values that integration asks for.

- id: node-id
  name: Node name
  type: CALL
  integration: llm_chat      # ← here
  input:                     # ← every integration asks for different fields
    ...

The full list

id Name Category Connection needed What it does
http_request HTTP request HTTP None Call any HTTP API directly
llm_chat LLM Chat AI None (API key) Have AI summarize, classify or write
transform_jmespath Transform (JMESPath) DATA None Shape and filter JSON data
dataset Dataset DATA None Read and write workspace datasets
slack_post_message Send Slack message MESSAGING Slack connection Post a message to a Slack channel
httpbin_get HTTPBin GET HTTP None A test call for checking things work

Start with the ones that need no connection. With just http_request · llm_chat · transform_jmespath you can build most automations end to end. Set up OAuth connections only when you really need that service.

Checking the current list: this catalog grows. To see what is available in your workspace right now, look at the node palette in the visual editor, or — if you have connected an AI assistant — just ask it "what integrations can I use?".


http_request

Calls any HTTP API directly. The most flexible integration, and the one you will use most.

Input

Field Required Description
uri The address to call. Expressions allowed
method GET · POST · PUT · DELETE · PATCH
mediaType Content-Type. Defaults to application/json
queryParams Query string (?a=1&b=2)
body Request body
authenticate A bundle of auth headers (see below)

Example — reading

- id: fetch-orders
  name: Fetch orders
  type: CALL
  integration: http_request
  timeout: 10s
  input:
    uri: "https://api.example.com/v1/orders"
    method: GET
    queryParams:
      status: "PAID"
      from: "${nodes.trigger.response.body.windowStart}"
    authenticate:
      authMethod: HEADERS
      data:
        Authorization: "Bearer ${secrets.EXAMPLE_API_TOKEN}"

Example — sending

- id: post-hook
  name: Notify an external system
  type: CALL
  integration: http_request
  input:
    uri: "https://hooks.example.com/notify"
    method: POST
    body:
      orderId: "${nodes.trigger.response.body.orderId}"
      status: "confirmed"

Output

The response body is the output, as-is.

${nodes.fetch-orders.response.body.data}          # the data field of the response body
${nodes.fetch-orders.response.body.items.0.name}  # the name of the first array element

API keys always go through ${secrets.*}. If you write a token straight into YAML, it leaks along with the workflow whenever you copy or share it. → 08. Variables and Secrets


llm_chat

Calls AI. Use it for summarizing, classifying, changing tone, drafting and so on.

It is not tied to a specific vendor — you pick an API shape (contract) instead. Any provider that matches the shape works.

Input

Field Required Description
apiContract OPENAI_CHAT or ANTHROPIC_MESSAGES
model The model id. For example: gpt-4o-mini, claude-sonnet-4-6
apiKey The API key. Pass it via ${secrets.*}
userPrompt What you are asking the AI to do
systemPrompt Sets the role and the rules
endpoint If omitted, the default address for the contract
maxTokens Maximum response length. ANTHROPIC_MESSAGES sends 4096 when omitted
temperature 0–2. Only sent when you set it

If you omit endpoint, this is where the call goes.

apiContract Default address
OPENAI_CHAT https://api.openai.com/v1/chat/completions
ANTHROPIC_MESSAGES https://api.anthropic.com/v1/messages

Anywhere else works too as long as the contract is compatible (Fireworks, Together, your own vLLM instance, and so on). Just put the address in endpoint.

Example

- id: summarize
  name: Sales summary
  type: CALL
  integration: llm_chat
  timeout: 30s
  input:
    apiContract: OPENAI_CHAT
    model: gpt-4o-mini
    apiKey: "${secrets.OPENAI_API_KEY}"
    systemPrompt: "You are an e-commerce operations lead. Do not exaggerate numbers; report facts concisely."
    userPrompt: |
      Summarize the order data below in three lines.
      Always include total revenue and order count, and add one line if anything stands out.

      Data: ${nodes.aggregate.response.body.summary}

Output

Field Description
${nodes.summarize.response.body.content} The text the AI wrote
${nodes.summarize.response.body.tokenUsage.totalTokens} Tokens used
${nodes.summarize.response.body.tokenUsage.promptTokens} Input tokens
${nodes.summarize.response.body.tokenUsage.completionTokens} Output tokens

Careful with temperature: some models, including recent Claude models, reject this value with a 400 error. If you do not need it, leave it out entirely.

You pay for usage. eeumsae only makes the call on your behalf with your API key; the bill comes from OpenAI, Anthropic and the rest directly. If tokens worry you, cap them with maxTokens.

Want to branch on the AI's answer? → the contains operator in 06. Flow Control


transform_jmespath

Reshapes JSON data. Pull out only the fields you need, keep only what matches a condition, count things, and so on.

It uses JMESPath syntax.

Input

Field Required Description
expression A JMESPath expression
data What to transform. If omitted, everything in input except expression

⚠️ The result must be an object

A CALL node's output has to be a JSON object. Emitting a bare array or number fails. Wrap it in braces.

expression: "items[*].id"              # ❌ array → fails
expression: "{ids: items[*].id}"       # ✅ object → works

expression: "length(items)"            # ❌ number → fails
expression: "{count: length(items)}"   # ✅ works

Common patterns

# pull specific fields into an array
expression: "{ids: data[*].orderId}"

# filter by a condition (mind the backticks)
expression: "{active: items[?status == `active`]}"

# count and sum
expression: "{count: length(orders), total: sum(orders[*].amount)}"

# rename fields
expression: "{name: customer.name, amount: payment.total}"

# several at once
expression: "{count: length(orders), revenue: sum(orders[*].amount), firstOrder: orders[0]}"

Example

- id: aggregate
  name: Aggregate orders
  type: CALL
  integration: transform_jmespath
  input:
    expression: "{count: length(@), totalRevenue: sum([*].amount)}"
    data: "${nodes.fetch-orders.response.body.data | raw}"

Do not forget | raw. Without that marker, an array or object passed to another node gets converted into a string. → 05. Connecting Data with Expressions

Output

The result of evaluating expression, as-is.

${nodes.aggregate.response.body.count}
${nodes.aggregate.response.body.totalRevenue}

dataset

Reads and writes rows in a workspace dataset. Use it when you need to remember a value between executions (for example: order numbers you already processed, or a running total).

The dataset has to exist first. → 09. Datasets

Input

Field Required Description
datasetTitle The title of the target dataset (unique within the workspace)
operation QUERY · INSERT · UPDATE · DELETE
data INSERT/UPDATE The values to store. Keys that are not dataset columns are dropped
rowId UPDATE/DELETE The id of the target row
limit Maximum rows for QUERY. Default 100, maximum 1000
offset Where QUERY starts

Example

# read
- id: load-log
  type: CALL
  integration: dataset
  input:
    datasetTitle: "processing-log"
    operation: QUERY
    limit: 50

# write
- id: save-log
  type: CALL
  integration: dataset
  input:
    datasetTitle: "processing-log"
    operation: INSERT
    data:
      orderId: "${nodes.trigger.response.body.orderId}"
      processedAt: "${nodes.trigger.response.body.windowEnd}"

Output

operation Output shape Reference example
QUERY { rows: [ {id, ...columns}, ... ] } ${nodes.load-log.response.body.rows \| raw}
INSERT / UPDATE { id, ...columns } ${nodes.save-log.response.body.id}
DELETE { deleted: true, id } ${nodes.del.response.body.deleted}

slack_post_message

Posts a message to a channel in a connected Slack workspace.

Before you start

  1. Connect Slack on the Connections screen. → 07. Managing Connections
  2. Invite the eeumsae bot into the channel you want to post to. In that channel, run /invite @eeumsae. Skip this step and you get a not_in_channel error.

Input

Field Required Description
channel Channel ID (for example C0123ABCDEF) or channel name
text The message body

In the visual editor you can pick channel from the channel list of the connected Slack.

Example

- id: notify
  name: Send to Slack
  type: CALL
  integration: slack_post_message
  input:
    channel: "C0123ABCDEF"
    text: |
      📊 Today's sales summary

      ${nodes.summarize.response.body.content}

Output

Field Description
${nodes.notify.response.body.ok} Whether it succeeded
${nodes.notify.response.body.channel} The channel it was sent to
${nodes.notify.response.body.ts} The message timestamp

⚠️ This integration really does send

slack_post_message is marked as an integration with a side effect. When you run it from an AI assistant over MCP, a workflow like this does not run straight away — it asks for approval once. That safeguard exists so an AI cannot accidentally blast messages at your customers.


httpbin_get

A test integration for checking things work. It calls httpbin.org, which echoes back what you send. Since it needs no authentication, it is handy for quickly confirming "does this workflow run at all?".

Field Required Description
query The value to get echoed back. URL-safe characters only (letters, digits, _ . ~ -)
- id: ping
  name: Health check
  type: CALL
  integration: httpbin_get
  input:
    query: "hello"

Output: ${nodes.ping.response.body.args} · ${nodes.ping.response.body.url} · ${nodes.ping.response.body.origin}

Non-ASCII characters or spaces cause the save to be rejected. It is for testing only, so keep it out of real automations.


Options every CALL node can use

These can be attached to any CALL node, whatever its integration.

- id: fetch
  type: CALL
  integration: http_request
  timeout: 10s              # over this and it counts as a failure
  retry-policy:             # try again on failure
    max-attempts: 3
    backoff:
      type: EXPONENTIAL
      initial-delay: 500ms
    retry-on: ["429", "5xx"]
  input:
    ...

For the details → 10. Executions and Monitoring


Next05. Connecting Data with Expressions