App Functions
Functions are server-side JavaScript that runs inside epilot โ no infrastructure of your own, no exposed endpoints, no credentials in the browser. You write a handler, declare it in your app's manifest, deploy with the CLI, and epilot executes it in a secured sandbox on your behalf.
Functions are the unit for all custom server-side logic in an app. Where they run is decided by their type:
| Type | Triggered by | Typical use |
|---|---|---|
workflow | An org admin adds your function as an action in the flow builder; it runs whenever the flow reaches that step, with the triggering entity as input | Enrich an entity, call your API through the API Proxy, validate data, reserve something in an external system |
scheduled | A cron schedule, automatically, once per installation | Poll a system that has no webhooks, sync a catalog nightly, refresh cached data |
{
"functions": [
{
"name": "reserve-slot",
"type": "workflow",
"label": { "de": "Slot reservieren", "en": "Reserve slot" },
"handler": "./functions/reserve-slot/dist/handler.js"
},
{
"name": "sync-open-requests",
"type": "scheduled",
"handler": "./functions/sync-open-requests/dist/handler.js",
"schedule": "rate(30 minutes)"
}
]
}
Functions vs. componentsโ
Components are the surfaces of your app โ journey blocks, custom pages, portal blocks, API proxies. Functions are its behavior. They complement each other:
- A
workflowfunction appears automatically in the flow builder of every organization that installs your app โ you do not create a component for it. (Flow action components still exist, but only for external integrations: webhook calls to your servers.) - A
scheduledfunction runs without any user interaction at all. - Functions can call external APIs through your app's API Proxy component, so external credentials stay on the installation and never appear in function code.
Code-first by designโ
There is no code editor in the epilot UI. Functions live in your app repository, are validated at deploy time, versioned with your app, and reviewed when you publish. This is deliberate: scheduled and flow-triggered code must be reproducible per version and per installation โ a UI-edited snippet can be neither.
npx @epilot/cli app add-function reserve-slot --type workflow --label "Reserve slot"
npm run build
npx @epilot/cli app deploy
What installing organizations seeโ
- Workflow functions show up in the flow builder's action picker under your app's name, using the function's
label. - The installed app's details page has a read-only Functions tab listing every function with its label, type and โ for scheduled functions โ the cron expression: full transparency about what the app runs on the org's behalf.
- Every run is recorded in the app's Insights, so you (the developer) can monitor failures per version and component.
Continue with Writing functions for the runtime contract.