Skip to main content
Glama
using-template-expressions.mdx6.94 kB
--- title: "Using Template Expressions" description: "Understand how template expressions work across integrations, tools, and steps." --- 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 configuration** – `urlHost`, `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: ```typescript headers: { "Authorization": "Bearer <<stripe_apiKey>>" }, queryParams: { user_id: "<<userId>>" } ``` or in an integration: ```text postgres://<<username>>:<<password>>@<<host>>:<<port>>/<<database>> ``` ### Arrow function expressions (recommended) 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. ```js <<(sourceData) => { // read from sourceData and return the value to insert }>> ``` <Note> 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. </Note> **Examples:** ```typescript headers: { "Authorization": "<<(sourceData) => `Bearer ${sourceData.credentials.apiKey}`>>" } ``` ```typescript 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: ```json { "username": "db_user", "password": "secret123", "host": "db.example.com", "port": "5432", "database": "production" } ``` <Note> Integration templates are only resolved at tool execution time and get merged with tool-specific credentials. </Note> ### 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: ```json { "payload": { "userId": "12345", "startDate": "2024-01-01" }, "credentials": { "apiKey": "sk_test_..." }, "getCustomers": { "data": [{ "id": "cus_123", "email": "user@example.com" }] } } ``` ### Pagination variables When pagination is configured on a step, the following variables are available in the request configuration (`urlPath`, `queryParams`, `headers`, `body`): | Variable | Description | | ---------- | ---------------------------------------------------- | | `page` | Current page number (starts at 1) | | `offset` | Current offset (starts at 0, increments by pageSize) | | `cursor` | Cursor value extracted from the previous response | | `limit` | Same as pageSize | | `pageSize` | The configured page size | **Examples:** Page-based pagination: ```typescript queryParams: { "page": "<<page>>", "per_page": "<<limit>>" } ``` Offset-based pagination: ```typescript queryParams: { "offset": "<<offset>>", "limit": "<<limit>>" } ``` Cursor-based pagination: ```typescript queryParams: { "cursor": "<<cursor>>", "limit": "<<pageSize>>" } ``` ### Stop condition The stop condition is a JavaScript function that determines when to stop fetching pages. It receives two arguments: 1. **`response`** – object containing: - `data` – the parsed response body - `headers` – response headers 2. **`pageInfo`** – object containing: - `page` – current page number - `offset` – current offset - `cursor` – current cursor value - `totalFetched` – total number of items fetched so far The function should return `true` to **stop** pagination, or `false` to continue. **Examples:** Stop when no more pages (using response metadata): ```javascript (response, pageInfo) => !response.data.has_more; ``` Stop when data array is empty: ```javascript (response, pageInfo) => response.data.items.length === 0; ``` Stop when cursor is null or missing: ```javascript (response, pageInfo) => !response.data.next_cursor; ``` Stop after fetching a specific number of items: ```javascript (response, pageInfo) => pageInfo.totalFetched >= 1000; ``` Stop when on last page (from total pages header): ```javascript (response, pageInfo) => pageInfo.page >= parseInt(response.headers["x-total-pages"] || "1"); ``` Combine multiple conditions: ```javascript (response, pageInfo) => { const items = response.data.results || []; return ( items.length === 0 || !response.data.next || pageInfo.totalFetched >= 5000 ); }; ``` ### 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: ```json { "payload": { "userId": "12345" }, "getCustomers": { "data": [{ "id": "cus_123", "email": "user@example.com" }] }, "createPaymentIntent": { "data": { "id": "pi_456", "status": "succeeded" } } } ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/superglue-ai/superglue'

If you have feedback or need assistance with the MCP directory API, please join our Discord server