Skip to main content
Most of the time you don’t have to write template expressions yourself—the agent generates them for you. Still, understanding how they work helps when you’re debugging or tweaking a tool. At their core, template expressions use the <<expression>> pattern, where expression is evaluated at runtime.

Where template expressions are used

The same template engine is used across superglue:
  • Integrations – connection strings and URL templates
  • Step configurationurlHost, urlPath, headers, queryParams, body
  • Transforms – final transforms and data selectors

Template expression modes

There are two kinds of template expressions: simple expressions and arrow function expressions.

Simple expressions (legacy)

Simple expressions resolve values directly from the context (payload, credentials, previous step results) without any JavaScript. Syntax:
  • <<variable>>
  • <<variable.key>> for nested fields
Examples: In the context of a tool step:
headers: {
  "Authorization": "Bearer <<stripe_apiKey>>"
},
queryParams: {
  user_id: "<<userId>>"
}
or in an integration:
postgres://<<username>>:<<password>>@<<host>>:<<port>>/<<database>>
Arrow function expressions use JavaScript arrow functions that receive the context as a single parameter (typically named sourceData) and return the value to insert. superglue runs these functions in a sandboxed JavaScript VM.
<<(sourceData) => {
  // read from sourceData and return the value to insert
}>>
Arrow function expressions are also used in places that are pure code (for example, the finalTransform field), where you don’t wrap them in << >>. They still receive the same sourceData context object and behave the same way.
Examples:
headers: {
  "Authorization": "<<(sourceData) => `Bearer ${sourceData.credentials.apiKey}`>>"
}
body: {
  posts: "<<(sourceData) => {
    const fromJsonPlaceholder =
      (sourceData.fetchJsonPlaceholderPosts ?? []).map(p => ({
        id: p.id,
        title: p.title,
        source: 'jsonplaceholder'
      }));

    const fromDummyJson =
      (sourceData.fetchDummyJsonPosts?.posts ?? []).map(p => ({
        id: p.id,
        title: p.title,
        source: 'dummyjson'
      }));

    return [...fromJsonPlaceholder, ...fromDummyJson];
  }>>"
}

Template context

Template expressions evaluate against a context object that depends on where they’re used (step config, integration, or transform).
  • Arrow function expressions – context is passed as the function parameter (typically sourceData)
  • Simple expressions – the string inside << >> is resolved against the same context object
The context looks different depending on where the expression is used:

Integration context

The context is built from the integration credentials (for example, username, password, access_token). The sourceData might look like this:
{
  "username": "db_user",
  "password": "secret123",
  "host": "db.example.com",
  "port": "5432",
  "database": "production"
}
Integration templates are only resolved at tool execution time and get merged with tool-specific credentials.

Tool step context

The context is the aggregated step input, which includes:
  • payload – workflow input payload
  • credentials – resolved credentials for the integration
  • Previous step results keyed by step ID (for example, getCustomers)
  • currentItem – current iteration data when the step runs in a loop
The sourceData object might look like this:
{
  "payload": { "userId": "12345", "startDate": "2024-01-01" },
  "credentials": { "apiKey": "sk_test_..." },
  "getCustomers": {
    "data": [
      { "id": "cus_123", "email": "user@example.com" }
    ]
  }
}

Final transform context

The context is a combined view of the entire workflow execution:
  • All step results keyed by step ID
  • The original payload
The sourceData object might look like this:
{
  "payload": { "userId": "12345" },
  "getCustomers": {
    "data": [
      { "id": "cus_123", "email": "user@example.com" }
    ]
  },
  "createPaymentIntent": {
    "data": { "id": "pi_456", "status": "succeeded" }
  }
}