Skip to main content
Ponder is a first-party Plot Plugin that runs a language model for every input row and returns a typed SQL value. Use it for classification, extraction, and other row-wise reasoning that is awkward to express with ordinary SQL.
Every row that reaches ponder() creates a model call. Filter the source and keep a LIMIT while developing. Scheduled Plots should also set external-call and cost budgets.

Classify rows

Named arguments use =>. Supply model coordinates inline or leave them out to use the default model, make the instruction and output type constant strings, and label every input with named_struct.
Classify Linear issues

Arguments

Do not mix named and positional arguments. The named form is the documented interface; Parable lowers it to the positional DataFusion function before planning. An argument ponder() refuses, such as an unknown argument name, a Struct output without schema, or an output type it does not support, fails while the query is planned, before any row is sent. Through Query Layer it returns gRPC INVALID_ARGUMENT with error code QL-PL-013 (INVALID_FUNCTION_ARGUMENT). The message names the argument and what it must be, never the value you gave, for example Missing required ponder() argument 'schema' for Struct output.

Choose the model

A call that names a model, inline or through model, runs that model. A call that names none runs the Workspace’s default model for ponder(), which a Workspace administrator sets in the Workspace’s AI policy. Without a Workspace default it runs Parable’s default, Gemini 3.5 Flash-Lite on Vertex (model id gemini-3.5-flash-lite). Vertex serves that model from its global endpoint, so Google chooses the region that processes each call.
Use the default model
Every model runs on an AI processor, named by its server: The Workspace’s AI policy lists the processors ponder() may use; production allows only vertex. A call whose processor the policy does not allow, a call that names no model when no default’s processor is allowed, and any call while the Workspace’s policy cannot be read are refused while the query is planned, before any row is sent: A scheduled Plot run records the same code when the policy refuses it, and the run fails: a refused call never produces NULL. A run whose planning could not read the policy is retried at the Plot’s next fire.

Choose an output type

Primitive output supports Utf8, Int64, Float64, Boolean, Date32, and Timestamp. A failed call produces NULL for a primitive cell while the rest of the query continues. Use Struct when downstream SQL needs more than one typed field:
Extract structured output
All declared Struct fields are nullable in Arrow. Ponder appends a reserved meta Struct; do not declare meta in the supplied schema. partial means the response parsed but omitted at least one required field. error means the model call failed. Struct output keeps the metadata alongside the row so SQL can inspect either state.

Execution and limits

Interactive queries execute Ponder as an asynchronous DataFusion scalar function. Scheduled Plot runs split it into a separate inference stage, pin the output-affecting model and instruction content, and account provider calls and cost before completing the result. A scheduled run pins the model it resolved, including a Workspace default, and the AI policy it planned under: a later policy change reaches the next run, never one already planned. A new default is a new model, so the Plot’s next run recomputes its results. The inference stage runs the same Ponder code as a query. Every row gets the same prompt, with its inputs labelled as named_struct names them, and a Report run stores the value a Preview returns: every output type, NULL for a failed primitive call, and meta for a Struct. The run records each column with its output type, so the Report reads it back as the Preview returns it. Report runs planned before Plots recorded these types stored every non-Utf8 ponder() column as String, which does not match the stored table, so their Plot output cannot be read; the Plot’s next Report run records the real types. A scheduled run retries a failed call before it stores the failure, and is charged one external call for each request that reached the provider. A call that cannot reach its provider at all, such as a route without a configured credential, fails the query with its cause instead of returning a NULL per row. A scheduled run fails with QR-QU-010 and is charged nothing, and its Report shows that the Plot’s AI functions could not reach their AI processor. When every input is constant, such as inputs => named_struct('topic', 'billing'), every row has the same prompt. A query sends it once for each batch of rows the engine passes to ponder(), at most PONDER_MAX_CONCURRENCY rows (8 by default), and every row in the batch reads that answer. A scheduled run asks it once. The service caps input rows and concurrency. A longer per-call timeout can lower the effective row cap because it consumes more of the query timeout budget. Run ponder() with the same SDK query method as any other Parable SQL. See Query with the SDKs.