Serverless Functions
Serverless Functions let you run your own TypeScript inside Cortex — triggered by domain events or invoked over HTTP — without standing up any infrastructure. They’re the right tool when you want custom logic close to your voice data: email a meeting summary, push a transcript to your CRM, escalate a toxic message, or expose a small HTTP endpoint.
You write the code in the dashboard editor (full IntelliSense), publish it, and Cortex transpiles, snapshots and deploys it to ODIN Fleet. Events are delivered to it automatically.
A function at a glance
A function exports an HTTP handler and any number of event handlers:
Named event handlers
Subscribe to a domain event simply by exporting a handler named after it. The rule:
split the event type on ., PascalCase each segment, and prefix on.
| Event | Handler export |
|---|---|
message.created | onMessageCreated |
participant.joined | onParticipantJoined |
gathering.member.joined | onGatheringMemberJoined |
session.annotation.created | onSessionAnnotationCreated |
Each handler’s event argument is fully typed, so your editor knows the shape of
event.payload.data. Exporting the handler is all it takes — there’s no separate
subscription list to keep in sync.
For wildcard subscriptions (message.*, *) or platform/Fleet events that have no named
handler, export an eventScopes array plus a generic eventHandler:
ctx.cortex — a pre-authenticated client
Every handler receives a ctx whose ctx.cortex is a ready-to-use, project-scoped
Cortex SDK client. No keys, no setup — call the API straight away:
The runtime authenticates ctx.cortex for you and keeps the underlying credential out of
reach of your code — you never handle a secret. (Available on runtime v2 and newer.)
Dependencies & environment variables
Functions can declare npm dependencies and environment variables — configured per
project. Declared packages are available to import/require, and their types are loaded
into the editor so IntelliSense works.
Environment variables are encrypted at rest and injected into the runtime; read them with
process.env. This is exactly what the
“email a meeting summary” guide uses
(node-mailjet + Mailjet credentials).
The runtime image preinstalls @4players/odin-cortex and @4players/fleet, so you can
import them without declaring them as dependencies. ctx.cortex is already an authenticated
instance of the Cortex SDK.
The lifecycle: edit → publish → deploy
- Activate Functions for the project once — Cortex provisions the Fleet resources it needs.
- Create & edit a function in the dashboard. The editor type-checks your TypeScript and blocks publishing while there are errors.
- Publish — Cortex transpiles your TypeScript to JavaScript, snapshots it as an immutable version, and analyzes which events it subscribes to.
- Deploy the version to Fleet. Cortex records the running endpoint and wires up event delivery.
Invoking over HTTP
A deployed function is reachable at a per-project URL and can be configured to be public, require an API key, or require a signed request:
The handler export receives the request (method, path, query, headers, body)
and returns a { statusCode, body }.
Runtime versions
The function runtime is published as immutable versions (v1, v2, …) and each
project is pinned to a specific one, so a platform update can never silently change your
function’s behavior. When a newer runtime is available, the dashboard shows an upgrade
option; you upgrade when you’re ready.
Errors & debugging
When a handler throws, the response (HTTP or event) includes the error message, a trimmed
stack, and a parsed location (file, line, column) pointing at the failing line in
your original TypeScript — so you can jump straight to the problem. console.log output is
captured per invocation.