Functions extend Spice's SQL engine with custom scalar and table logic. Each entry in the top-level functions: block is registered as a callable SQL function and (for scalar functions, by default) as an LLM tool.
For an overview, examples, and execution-tier details, see Functions.
:::warning[Registration is off by default]
The functions: section is only honored when runtime.functions.enabled is set to true.
:::
functionsThe functions: section in your configuration declares one or more scalar or table functions.
Example:
nameA unique identifier for the function. The name is used to register the UDF in the SQL session and as the tool name when surfaced to LLMs.
fromSource URI selecting the execution tier:
sql — Inline SQL body executed in-process.http://... / https://... — Remote endpoint invoked over HTTP + JSON.Other schemes are rejected at startup. See Execution Tiers.
enabledOptional. Defaults to true. Set to false to keep the declaration in the spicepod without registering the function — useful for staged rollouts. Disabled functions are also hidden from list_udfs() and GET /v1/functions.
descriptionOptional. Free-form description surfaced in list_udfs(), GET /v1/functions, and the LLM tool registry.
kindOptional. Defaults to scalar.
| Value | Description |
|---|---|
scalar | (default) Returns a single value per row. Called as SELECT my_fn(x) FROM .... |
table | Returns multiple rows and columns. Called as SELECT ... FROM my_fn(x). Always SQL-only (as_tool is ignored). |
volatilityOptional. Defaults to volatile. Controls how the optimizer treats the function across calls.
| Value | Description |
|---|---|
immutable | Same inputs always yield the same output. May be constant-folded and cached. |
stable | Stable within a single query but may change across queries. Cached per query. |
volatile | (default) Unpredictable on every call. Never cached. |
Choose the strongest level that's actually true. See Volatility.
signatureRequired. Typed argument list and return type.
signature.argsOptional. Positional argument list. Empty for niladic functions.
Each entry has:
name — Argument name. Used inside SQL body expressions and as the JSON key for remote tier requests.type — Arrow type. Accepts Spicepod aliases (int64, utf8, list<int64>, decimal(38,10), timestamp(us, utc)) and Arrow display forms (Int64, List(Int64), etc.). See Types.signature.returnsRequired. For scalar functions, a single Arrow type string (e.g., int64, utf8). For table functions, a list of output column definitions:
bodyInline SQL body. Required when from: sql (unless body_ref is set instead). For scalar functions, must be a single SQL expression referencing the function's arguments by name. For table functions, must be a single SELECT query; scalar arguments are available via a virtual args table.
The body can call any DataFusion built-in scalar function (math, string, datetime, JSON, regex, etc.).
Mutually exclusive with body_ref. Must not be set for non-SQL from: schemes.
body_refPath to a local filesystem file whose contents are the SQL body. Resolved relative to the runtime's current working directory at registration time.
body_ref is not read from object stores when a spicepod is loaded remotely — use inline body: for portable remote spicepods.
Mutually exclusive with body.
paramsOptional. Tier-specific parameters. Supports ${secrets:KEY} and ${env:KEY} interpolation at registration time.
For the Remote tier (from: http://... / https://...):
| Parameter | Default | Description |
|---|---|---|
timeout | 30s | Per-call timeout. Plain integer seconds or Ns / Nms strings. |
batch_size | 1024 | Maximum rows per HTTP request. Capped at 100 000. |
batch_concurrency | 4 | Maximum in-flight HTTP batches per invocation. Capped at 64. |
auth_bearer | unset | When set, adds Authorization: Bearer <value> to each request. Use ${secrets:...}. |
The SQL tier does not currently use params.
metadataOptional. Free-form key/value pairs surfaced alongside the function definition. Useful for tagging, ownership, or custom metadata consumers.
as_toolOptional. Defaults to true for scalar functions. When true, the function is registered as an LLM tool with the same name and description and becomes callable from chat completions, POST /v1/tools/<name>, and the /v1/tools listing. Table functions (kind: table) are always SQL-only regardless of this setting.
Set to false to keep the function SQL-only:
dependsOnOptional. Names of other Spicepod components that must be loaded before this function (e.g. a dataset the function queries internally).
metricsOptional. Per-function metrics configuration. See Component Metrics.
After startup, registered functions can be inspected:
SELECT * FROM list_udfs() WHERE source = 'user';GET /v1/functions returns a JSON array of user functions.