Build
Functions reference
A function has two independent axes — its kind (the sort of data source it runs against, set when you pick a connection) and its output shape and execution model, which you choose in the builder. This page is the full catalog of all three.
6 min read
Function kinds
The kind is inferred from the connection you build on. Each maps to one family of data source; the builder shows the fields that kind needs (a SQL query, an HTTP request, a collection filter, and so on).
http— a REST/HTTP request: method, URL template, query, headers, and body, with parameters bound from the formula arguments.graphql— a GraphQL query with variables against a GraphQL endpoint.database— a parameterized SQL query. The dialect follows the connection: Postgres, MySQL, SQL Server, Oracle, Azure Synapse, or AWS Athena.mongo— a MongoDB find, aggregate, or count on a collection (filter, pipeline, sort, limit).cosmos— an Azure Cosmos DB SQL query against a container.dynamodb— an AWS DynamoDB get-item or query by partition/sort key.lambda— an AWS Lambda invocation with a JSON payload, optionally reading a field out of the response.azure_function— an HTTP-triggered Azure Function.gcp_function— an HTTP-triggered Google Cloud Function.file— reads a remote file (over HTTP(S), S3, SFTP, FTP, Azure Blob, or Google Cloud Storage) parsed as CSV, JSON, or JSONL.kv— a read from a key-value cache (get / mget / scan) against a Valkey- or Redis-compatible store.
Four of these — database, mongo, dynamodb and
cosmos — can also write; see Write operations below.
Output shapes
The shape decides how the result lands in the grid.
single— one value into the calling cell (number, string, boolean).row— one record across a row of cells.table— rows × columns that spill into a range, with headers and number formats mapped from the response.json— the raw JSON response as text.entity— an Excel linked data type: a cell chip whose properties become field accessors like=A2.Price. Async-only; these appear under the taskpane's Data types tab.
Execution models
sync— computed locally in the add-in, with no call to the agent. Best for lightweight transforms.async— the default. The agent fetches while Excel shows#GETTING_DATA; the add-in batches many cell calls into one request.streaming— the cell updates live as new values arrive. Server-Sent Events on desktop, with a polling fallback on Excel for the web.
Kind is not output shape
The kind (data source) and the output shape are independent — a database function can return a single value, a table, or an entity, and an http function can too. You pick the source once, then decide how its result appears.
Streaming details
A streaming function's stream block controls exactly how updates reach the cell:
- Transport —
sse(Server-Sent Events) orpolling. SSE is only available when the function's connection ishttp— every other connection kind streams by polling, and Excel for the web always falls back to polling, since long-lived SSE connections aren't reliable across every browser sandbox. Polling carries its own interval, in seconds; SSE has none — the agent forwards events as they arrive. emitOnChangeOnly— when set, the agent only pushes a new value into the cell when it actually changed, instead of re-emitting the same value on every tick.cancelUpstream— on by default. When the cell is deleted or the user navigates away, the agent tears down its upstream subscription instead of continuing to poll or hold a connection open for nobody.
Write operations
Four kinds send data the other way. The operation is picked in the builder, and a function has exactly one.
| Field | Type | Description |
|---|---|---|
databaseOptional | insert | A parameterized multi-row INSERT into one table. You name the target table and the parameter that carries the rows — an array of objects — and the columns are the union of the row keys, with a key a row omits written as NULL. Available on all nine pooled SQL engines: Postgres, MySQL, MariaDB, SQL Server, Oracle, Azure Synapse, Redshift, TimescaleDB, and Supabase. |
mongoOptional | insertOne · insertMany · updateMany · deleteMany | Document writes against a collection. A deleteMany must carry a filter — an empty one would match every document, so it is refused outright. |
dynamodbOptional | put_item · put_items | put_item writes one object; put_items writes a whole array, batched 25 items at a time. Both are upserts by table key, so re-writing a row whose key already exists replaces it instead of adding a second copy. |
cosmosOptional | upsert | Writes the rows parameter into a container, keyed by document id. There is no query on this path — the rows are the payload. |
The SQL path never assembles a statement from free text: the table name and every column name must be a plain identifier — a letter or _ followed by letters, digits, and _ — and the values ride as bound parameters. A workbook header can't smuggle SQL into a statement.
A write function is taskpane-only
Every write function must be marked taskpaneOnly, with result caching and volatile both off — publishing fails otherwise. Excel re-runs a registered custom function on every workbook recalculation, so a write reachable from a cell would silently re-fire and multiply its rows; a cache hit would skip the write altogether. Writes are invoked from the taskpane instead — a function button, or an Upload range block.
Uploads are safe to retry by construction. Every chunk of one upload carries the same identity (the ${upload.*} variables below): the SQL insert stamps _upload_id and _chunk onto each row and replaces that chunk inside a single transaction, Cosmos derives its document ids from the upload identity, and DynamoDB overwrites by table key. Re-clicking after a partial failure therefore replaces what was already written instead of duplicating it.
Function flags
Three independent switches, available regardless of kind:
| Field | Type | Description |
|---|---|---|
volatileOptional | boolean | Recalculates every time the workbook recalculates, not just when its own inputs change. Mutually exclusive with persistent. |
persistentOptional | boolean | Caches the last result and reuses it across recalculations instead of re-running. Forced off for streaming functions. |
batchSizeAsync only | integer | When greater than zero, lets the agent receive many simultaneous cell invocations as one batched call instead of one request per cell — most useful for a column of similar calls against a rate-limited source. |
Template variables
Anywhere a function definition takes free text that is sent to the data source — an HTTP endpoint path, header or query values, the body template, a SQL statement, or a parameter's default — you can reference predefined variables with ${...}. The agent resolves them fresh on every call, server-side; the workbook never sees or supplies the values, so they can't be spoofed from a cell. An unknown ${...} reference is left untouched rather than blanked.
Built-ins — always available
| Field | Type | Description |
|---|---|---|
${today}Optional | string | The call date as YYYY-MM-DD, in the agent host's local time zone. |
${now}Optional | string | The call instant as an RFC 3339 UTC timestamp (e.g. 2026-07-10T14:30:00Z). |
${timestamp}Optional | string | The call instant as Unix seconds. |
${uuid}Optional | string | A fresh random UUID, different on every call. |
The signed-in user — ${auth.*}
Resolved from the end user's validated sign-in token. Each is an empty string when no user is signed in — combine with a user_token connection or access control when a value must be present.
| Field | Type | Description |
|---|---|---|
${auth.sub}Optional | string | The provider's stable subject identifier for the user — the right key for per-user attribution, since it never changes even if the email does. |
${auth.email}Optional | string | The user's email address. |
${auth.name}Optional | string | The user's display name. |
${auth.picture}Optional | string | The user's avatar URL, when the provider supplies one. |
${auth.provider}Optional | string | Which identity provider the user signed in with. |
Upload identity — ${upload.*}
Set only when the call comes from a taskpane Upload range block; each is an empty string otherwise. Large uploads are sent in chunks, and a retried click re-sends the same identity — so your API can deduplicate by (id, chunk) instead of storing duplicates.
| Field | Type | Description |
|---|---|---|
${upload.id}Optional | string | One UUID per upload click, shared by every chunk of that upload. |
${upload.chunk}Optional | string | The 0-based index of this chunk within the upload. |
${upload.chunks}Optional | string | The total number of chunks in the upload. |
${upload.rows}Optional | string | The total number of rows across the whole upload. |
Values are escaped for the context they land in (a SQL statement escapes differently from a JSON body), so a name containing a quote can't break the request.
Using functions in Excel
Once the add-in is installed, your functions behave like any other Excel function — type a formula, pass cell references, and let the result fill in. Behind the scenes Excel talks to your agent, and your data never leaves your network.
Mutual TLS (mTLS)
The agent authenticates to this backend by enrolling for its own mTLS client certificate — there is no API key, no bearer token to configure at runtime, and no alternative auth mode. You never have to create or handle the certificate yourself; the agent generates its own key and gets it signed during enrollment.