Skip to main content

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:

TypeTriggered byTypical use
workflowA CUSTOM_FLOW_ACTION component references it ({ "type": "function", "function_name": "โ€ฆ" }); org admins add that action in the flow builder and it runs with the triggering entity as inputEnrich an entity, call your API through the API Proxy, validate data, reserve something in an external system
scheduledA cron schedule, automatically, once per installationPoll a system that has no webhooks, sync a catalog nightly, refresh cached data
manifest.json
{
"functions": [
{
"name": "reserve-slot",
"type": "workflow",
"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 workflow function is wired into the flow builder through a CUSTOM_FLOW_ACTION component that references it โ€” the component carries the org-facing name and config UI; the function carries the code. (external_integration components remain for webhook calls to your servers.)
  • A scheduled function 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 through their referencing component, under the component's name.
  • The installed app's details page shows scheduled functions in a compact summary on the Configuration tab โ€” label plus a plain-language cadence ("every 30 minutes") โ€” transparency about what the app runs on the org's behalf in the background. Workflow functions need no extra listing: they appear as their flow-action component cards right above.
  • 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.