Create and build a function
Create a function in OmniLab Studio, write its handler, save a draft, and compile it to a running WebAssembly version.
Create a function, write its TypeScript handler, and compile it so it can be invoked. At the end of this article the function is Ready but not yet triggered by anything — wiring it up is covered on the page for its kind, platform event or hook.
Before you begin
- Your user role must be Admin. Contributors cannot see the Functions surface.
- You must be working in the Global Organization. The Functions tab only appears there — if you switch to another organization, it disappears.
- Decide the function's kind first. It is permanent.
- If your handler will call an external API, have the hostnames ready. You will need to allow-list them before any outbound call works.
The Functions interface is English only
Unlike the rest of OmniLab Studio, the Functions screens are not translated. Labels stay in English regardless of your interface language.
Steps
Open the Functions tab
In the left sidebar, switch to the Global Organization, then open General Settings. On the Enterprise Settings page, select the Functions tab.

Create the function
Select New function and fill in the form:
| Field | What to enter |
|---|---|
| Display name | A label your team will recognize, such as Loyalty award processor. The identifier is generated for you. |
| Kind | Platform event or Hook. This choice is permanent. |
| Hook point | Only for the Hook kind. Pick the platform decision your function should take part in. |
| Source (TypeScript) | Your handler. Choosing a kind drops in a working starting point. |
Choosing a kind or hook point replaces the editor contents with a matching starter handler — but only until you edit the code yourself. Once you have typed in the editor, switching the kind leaves your code alone.
Select Create. OmniLab type-checks the source and saves the function as Draft.

Write your handler and save the draft
Open the function and use the Source tab. Your file must export the name that matches your kind, or the build fails with a type error.
The starter handler the create form dropped in already exports the right name and compiles as-is, so you can build it unchanged to confirm the setup works before writing your own logic.
Working examples for each kind, from a hello world up to something useful, live on the kind's own page:
The editor shows a live size counter against the 1 MB source ceiling, and the header of the field confirms the entry point is user.ts.
Select Save source. Save source stays greyed out until you actually change something, so a freshly opened function has nothing to save. This stores your code and type-checks it. It does not deploy anything — a function that is already live keeps serving its current version until you build.
If the type check fails, a Lint failed panel replaces the success message and lists each problem with its file, line, and column. Select a row to jump to that line in the editor. Nothing is saved while the check is failing, so fix the issues and save again.

Build it
Open the Build tab and select Build. The status changes to Building and the editor refreshes itself every few seconds until the build finishes, so you do not need to reload.
A build normally takes a few seconds to a minute. When it succeeds the status becomes Ready, the version number increases, and the WASM sha and WASM size fields are filled in. When it fails, the tab shows the error and a truncated build log.
Rebuilding source you have not changed since the last successful build returns almost immediately, because there is nothing new to compile.

Confirm it runs
Open the Test tab, select Load example to drop in a sample payload matching your kind, and select Run test. A successful platform event run shows exit code 0; a hook run shows the decision it made.
Test runs use the real sandbox and the real SDK calls, so an allow-listed HTTP request really goes out and a contact field write really lands. They also appear in the execution log, marked as tests.

If something's blocked
The Functions tab is not there. You are either not an Admin, or you are not in the Global Organization. Switch organizations using the picker at the top of the sidebar.
Saving reports a type error you do not recognize. The most common cause is the export name. A hook function for contact.create.pre must export exactly onContactCreatePre; a platform event function must export onPlatformEvent. The name is derived from the kind and hook point, and a mismatch is reported as a missing or wrongly shaped export.
The build fails on an error you cannot locate in your own code. This usually means your handler does not match the type it was declared with — a wrong parameter, a wrong return value, or the wrong handler type imported for the kind. Compare your handler against the example on your kind's page.
The build has been Building for a long time. A build that stalls is released after about fifteen minutes, and you can then start another. If it happens repeatedly, contact support with the build id from the Build tab.
Your handler cannot reach an external API. A function with no allowed hosts is refused every outbound request. See Configure runtime and secrets.
The function is Ready but nothing happens. A built function is not triggered by anything until you add a subscription or a hook binding.