Skip to content

Custom Actions

Produce Custom Action Messages

You can use Custom Actions to enable communication between two Applications on either the same cluster or across different clusters.

Note

To understand the purpose of Custom Actions or view the overall structure of how they work, check out the documentation in the overview page here.

To ensure the Custom Action being sent is handled properly, the app.yaml outputs needs to be declared:

Note

You can choose any name for the type.

This is how the Custom Action Manager chooses which Consumer Application (Executor) will receive the Custom Action object.

app.yaml Example
1
2
3
custom_actions:
  outputs:
    - type: custom-action-name

The Custom Action Object in the main.py script supports the following attributes :

Attribute Required Default Value Description
resource required N/A The KRNAsset that this Custom Action is meant for.
type required N/A The name of Custom Action.
title required N/A Title of the Custom Action
description required N/A Description details of the Custom Action
expiration_date required N/A Absolute datetime or a timedelta (from now) when the Control Change will expire.
payload required N/A The custom information of the Custom Action that will be required by the Consumer Application
trace_id optional N/A A custom id for tracking the Custom Action status

Custom Action UI Schemas

You can define a UI schema for each Custom Action type your Application produces. This creates an input form in the Kelvin UI's Applications section where users can configure settings specific to this publisher application.

Example

A publisher that sends email actions might expose a field for a default subject line. This is set on the publisher application and applies to the actions it generates.

Note

The producer UI schema is independent of the consumer UI schema. Each serves a different purpose and neither defines the payload data exchanged between the two applications -- that is handled in code.

Declare the schemas in the ui_schemas.custom_actions section of your app.yaml, keyed by action type name:

app.yaml Example
1
2
3
4
5
6
7
8
9
custom_actions:
  outputs:
    - type: send-email
    - type: apply-setpoint

ui_schemas:
  custom_actions:
    send-email: "ui_schemas/send_email.json"
    apply-setpoint: "ui_schemas/apply_setpoint.json"

Each file is a JSON Schema that defines the configuration fields presented to users in the Kelvin UI for this publisher application:

ui_schemas/send_email.json
{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Email Publisher Settings",
    "description": "Configuration specific to this publisher application.",
    "type": "object",
    "properties": {
        "from_address": {
            "type": "string",
            "title": "From Address",
            "description": "Email address to send from for this application."
        },
        "default_subject": {
            "type": "string",
            "title": "Default Subject",
            "description": "Default subject line used by this application when sending email actions."
        }
    },
    "required": ["from_address"],
    "additionalProperties": false
}

Note

Custom Action payload schemas are optional. If not provided, the payload field is treated as free-form JSON with no UI validation.

See UI Schemas in the app.yaml reference for full details on the schema format.

Example

In this example we will create a Producer Application that will;

  1. Package the email details into a Custom Action Object
  2. Send the Custom Action object directly to the Consumer Application (Executor) for processing.
  3. Package the Custom Action object in a Recommendation and publish the "Recommendation with Custom Action" to the Kelvin UI for approval. (Typically, you would choose either direct sending or publishing with a Recommendation—not both.)

Check out the Consume Custom Actions documentation here to see how to receive this Custom Action in a Consumer Application (Executor).

app.yaml

app.yaml Example
spec_version: 5.0.0
type: app            # Any app type can handle and/or publish custom actions.

name: hello-app
title: Hello App
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit
version: 1.0.0

custom_actions:
  outputs:
    - type: email

  ...

Publisher Application

main.py Example
import asyncio
from datetime import timedelta, datetime

from kelvin.application import KelvinApp
from kelvin.krn import KRNAsset
from kelvin.message import Recommendation, CustomAction

app = KelvinApp()

@app.timer(interval=10)
async def publish_data():

    asset = KRNAsset("air-conditioner-1")

    # Direct Custom Action
    action = CustomAction(resource=asset,
    type="email",
    title="Recommendation to reduce speed",
    description="It is recommended that the speed is reduced",
    expiration_date=datetime.now() + timedelta(hours=1),
    payload={
        "recipient": "operations@example.com",
        "subject": "Recommendation to reduce speed",
        "body": "This is the email body",
    })
    await app.publish(action)


    # Or embedded the Custom Action into a Recommendation   
    rec = Recommendation(resource=asset,
    type="Reduce speed",
    actions=[action],
    )
    await app.publish(rec)

app.run()