Skip to content

Custom functions#

CEL runtimes can be extended with custom functions to call application-specific logic.

Custom functions are runtime-specific. Expressions using custom functions only work with runtimes that implement them.

Function signatures#

A custom function has a name, parameter types, and a return type. Functions can be overloaded with multiple signatures.

// Example function signatures (not CEL syntax)
greet(string) -> string
greet(string, string) -> string

The runtime selects the appropriate overload based on argument types.

Receiver syntax#

Functions can be defined to use function or receiver (method) syntax. Both styles can be supported for the same function.

// Function syntax
greet("Alice")
// Receiver syntax
"Alice".greet()

Type safety#

Custom functions participate in CEL type checking. The compiler verifies that arguments and return values match the declared parameter types.

greet(123)
// error: no matching overload for 'greet' applied to '(int)'

Error handling#

Custom functions can return errors that propagate through the expression.

// input: order = example.v1.Order{}
validate(order) && process(order)

If validate returns an error, process is not called.

Runtime specifics#

The mechanism for defining custom functions varies by runtime:

  • cel-go: Use cel.Function() with cel.Overload()
  • cel-java: Use CelRuntime.FunctionBinding
  • cel-cpp: Use FunctionRegistry

See also#