How to create a Cloud Function
A full walkthrough — from a fresh workspace to a deployed function in IXON Cloud — using a realistic example.
This guide walks you through creating a Cloud Function from scratch and getting it running both locally and in IXON Cloud. We'll build a small service logbook — two functions that let operators add and retrieve maintenance notes, stored persistently in the Document Store.
The function does not require a UI Component — we'll trigger it directly from the terminal via curl. To pair it with a UI Component, see How to visualize a Cloud Function in a UI Component after this guide.
A basic understanding of Python is assumed.
What you need
- Linux, macOS, or Windows with WSL2. Windows users: complete Prerequisites for Microsoft Windows systems first.
- Python 3.12 or higher (matching
ixoncdkingress 1.x). Download from python.org. - Docker — see docker.com. The local Document Store runs in a Docker container.
- A code editor that understands Python — VS Code or PyCharm Community work well.
curl— pre-installed on macOS and Linux; included with WSL on Windows.- A user account in IXON Cloud with the Develop apps permission (for the deploy step).
Part 1 — Set up the workspace
Do not edit the MakefileThe
Makefilein the workspace is part of IXON's tooling contract. Modifying it will break local builds.
-
Download the workspace from ixoncloud/backend-component-workspace as a ZIP and extract it. (Don't clone — the workspace is intended to be checked into your own repository, and cloning IXON's directly creates Git history conflicts.)
OR
Open any terminal in the folder where you want to store your project, and use the following command to create a clean, unversioned workspace:
npx degit ixoncloud/backend-component-workspace notes-project -
Open the workspace folder in your editor.
Windows users: open it inside a WSL session (see Prerequisites). In VS Code, navigate to View > Command Palette > WSL: Open folder in WSL...
-
Run
make runfrom the workspace root in your terminal.Note: Before you run this command, make sure that your Docker engine is running, or you will receive an error.
$ make runOn the first run, the Makefile creates a Python virtual environment, installs dependencies, starts a MongoDB Docker container for the local Document Store, and starts the Ingress on
http://127.0.0.1:8020/. You'll see something like:CBC_PATH=./functions ./venv/bin/python3 -m ixoncdkingress 2026-04-03 11:54:24 - ixoncdkingress - INFO - Starting DocumentDB server 2026-04-03 11:54:29 - ixoncdkingress - INFO - DocumentDB server started successfully 2026-04-03 11:54:29 - ixoncdkingress - INFO - wsgiref listening on http://127.0.0.1:8020/ 2026-04-03 11:54:29 - ixoncdkingress - INFO - CBC_PATH: ./functionsLeave this terminal open — your function host runs here, and you'll see logs in this window every time the function is called.
Ifmake runfails with a.venverrorsudo apt update sudo apt install python3.12-venv rm -rf venv make run
Part 2 — Write the function
As a very first step,
Create a new file functions/logbook.py in your editor and add the following:
from datetime import datetime, timezone
from bson.json_util import dumps
import json
from ixoncdkingress.function.context import FunctionContext
@FunctionContext.expose
def add_note(context: FunctionContext, text: str) -> dict:
"""
Add a maintenance note to the logbook.
The note is tagged with the calling user's name and the current timestamp.
"""
if not context.document_db_client:
return {'success': False, 'error': 'Document Store is not available.'}
note = {
'text': text,
'author': context.user.name if context.user else 'Unknown',
'timestamp': datetime.now(timezone.utc).isoformat(),
}
context.document_db_client.insert_one(note)
return {'success': True}
@FunctionContext.expose
def get_notes(context: FunctionContext) -> list:
"""
Return the most recent logbook notes.
The number of notes returned is controlled by the `maxNotes` setting.
"""
if not context.document_db_client:
return []
limit = context.config.get('maxNotes', 50)
notes = list(context.document_db_client.find({}))
return json.loads(dumps(notes[-limit:]))Code workflow
-
The decorator
@FunctionContext.exposeis what makes a function callable from outside the workspace. Without it, the function would be unreachable. A single file can expose as many Python functions as you need. -
Both functions guard against
context.document_db_clientbeingNone— the Document Store is not guaranteed to be available in all contexts. See Document Store for details. -
context.useris populated when a real user is calling the function —add_noteuses it to automatically tag the author of each note. See Resources for details. -
context.configreads fromcontext_values.yamllocally, and from the encrypted Settings in IXON Cloud. The.get('maxNotes', 50)provides a sensible default if no limit is configured. -
bson.json_util.dumpsis needed to serialize the documents returned by the Document Store, because MongoDB assigns a BSONObjectIdas_idon insert — a type that Python's standardjsonmodule cannot handle on its own.Auto-reloadThe Ingress reloads function code on save. You don't need to restart
make runafter editinglogbook.pyorcontext_values.yaml.
Part 3 — Test the functions in your terminal
Open a second terminal and add a note via curl:
curl -X POST http://127.0.0.1:8020/ \
-H 'Content-Type: application/json' \
-d '{"name": "logbook.add_note", "arguments": {"text": "Replaced motor belt on conveyor line 3."}, "context": {"company": {"publicId": "1111-2222-3333-4444-5555", "name": "My Company", "custom": {}}}}'You should see a response like:
{"success": true}Now retrieve the notes you've added:
curl -X POST http://127.0.0.1:8020/ \
-H 'Content-Type: application/json' \
-d '{"name": "logbook.get_notes", "arguments": {}, "context": {"company": {"publicId": "1111-2222-3333-4444-5555", "name": "My Company", "custom": {}}}}'You should see a response like:
[{"_id": {"$oid": "..."}, "text": "Replaced motor belt on conveyor line 3.", "author": "Unknown", "timestamp": "2026-05-21T10:00:00+00:00"}]
Notes on Author and Company
- The
authorfield shows"Unknown"here because no user is set when calling viacurllocally. When a real user triggers the function from a UI Component,context.user.namewill be populated automatically. In the terminal runningmake run, you'll see an HTTP log entry for each call.- For the same reason, the
publicIdandnameof acompanymust be simulated and added to thecURLcommand.
Registering the function in IXON Cloud
Before you can deploy, you need to register the function in IXON Cloud.
- Open Studio > Cloud Functions.
- Click Add new Cloud Function.
- Enter a name end-users will recognise, then click Add.
- Copy the Public ID that's displayed — you'll need it for deploying and publishing the function.
Deploy and publish
To deploy and publish your local code as a new version of the registered function, the workspace needs two values in a .env file at the workspace root:
IXON_API_COMPANY_ID— your company's Public ID. You can find it in the URL of the IXON Portal when your company is open.IXON_API_TEMPLATE_ID— the Public ID of the Cloud Function you just registered.
Create .env:
IXON_API_COMPANY_ID=your-company-public-id
IXON_API_TEMPLATE_ID=your-function-public-idMake sure .accesstoken exists in the workspace root. Then deploy following the steps in the workspace's deployment section.
Notes
- The user account used for deploying must have the Develop apps permission.
- The deploy uploads a new version. To make it active, publish the new version from Studio > Cloud Functions > your function.
- The bearer token can be automatically generated when logging in from a UI Component's workspace: You can do that and copy the bearer token in the
.accesstokenfile and then paste it in thebackend-component-workspaceroot folder, or you can get the token by inspecting the browser with F12 when visiting the IXON Portal.
Finally, deploy and publish your function with the following command:
make deployOnce published, the function becomes available under Admin > Apps for anyone in your company to enable.
Downloading a Cloud Function's logs
To inspect what happened during real calls:
- Studio > Cloud Functions > your function > More options (three dots) > Download logs.
Logs cover the current version of the Cloud Function deployed and published in the Portal, for the last 48 hours, with up to a 5-minute delay between a call and its log entry. Anything you print() or send via Python's logging module at level INFO or higher will appear in the download. Be careful not to log secrets — anyone with the Manage Apps permission can see the log file.
Sharing your Cloud Function
To share the function with another company, go to Admin > Apps and use the share option on your function. Linked UI Components are shared automatically.
Where to go next
- How to visualize a Cloud Function in a UI Component — pair the function you just built with a custom UI.
- Cloud Functions SDK — the full surface area of
FunctionContext, the API client, and resources. - Common errors — if
make runis misbehaving or Docker is throwing errors.
Updated about 11 hours ago
