Skip to main content
Version: 2026-05

Actions & Hooks

Entity types can declare callable actions via has_action and lifecycle hooks via has_hook. Both point to an action entity (or one of its subtypes). Actions provide a mechanism to execute logic in the context of an entity -- either as inline Lua scripts or as calls to external HTTP services.

Declaring Actions

Actions are declared on an entity type via the has_action relationship:

"has_action": [
{
"properties": { "name": "bark", "label": { "en_us": "Bark" } },
"target": "action/bark"
}
]

The target can be either an executable_script (inline Lua) or a service_function (external HTTP).

Action Subtypes

executable_script

Runs an inline Lua script. The script is evaluated in the context of the entity and returns a string result.

{
"properties": { "name": "bark", "label": { "en_us": "Bark" } },
"target": {
"type_name": "entity_type/executable_script",
"properties": {
"name": "bark",
"script": "return \"wau wau!\""
}
}
}

See Lua Scripting for the scripting reference.

service_function

Calls an external HTTP endpoint. This is the primary mechanism for integrating business logic implemented in external microservices (Python, Go, Rust, etc.).

{
"properties": { "name": "bark_net", "label": { "en_us": "Bark (Remote)" } },
"target": {
"type_name": "entity_type/service_function",
"properties": {
"name": "bark_net",
"endpoint": "http://localhost:12810/bark_service"
}
}
}

When invoked, the platform sends the entity context to the configured endpoint and returns the result to the caller.

Invoking an Action via the API

Actions are invoked through the @action sub-route on any entity:

POST /api/v1/by-key/<type>/<key>/@action/<action_name>

Response 200:

{ "result": "<action output string>" }

Response 409: Action execution failed.

Example

POST /api/v1/by-key/dog/rex/@action/bark
{ "result": "wau wau!" }

Lifecycle Hooks

Hooks are declared via has_hook and use the same action subtypes. The difference is when they execute:

  • Actions (has_action) are explicitly triggered by a user or API call.
  • Hooks (has_hook) are automatically triggered by lifecycle events (e.g. status transitions, entity creation, entity updates).
"has_hook": [
{
"properties": { "name": "on_release", "label": { "en_us": "On Release" } },
"target": {
"type_name": "entity_type/service_function",
"properties": {
"name": "on_release",
"endpoint": "http://localhost:12810/release_handler"
}
}
}
]

Architecture Flow

When an action is triggered from the frontend or API:

sequenceDiagram
participant UI as Frontend
participant API as API Service
participant Core as Core Service
participant Ext as External Service
UI->>API: POST /@action/bark
API->>API: Check permissions
API->>Core: Resolve action definition
Core-->>API: Action target (script or endpoint)
alt executable_script
API->>API: Execute Lua script
else service_function
API->>Ext: HTTP request to endpoint
Ext-->>API: Response
end
API-->>UI: { result: "..." }
tip

Use executable_script for simple, self-contained logic (string formatting, basic calculations). Use service_function for complex business logic that benefits from a dedicated service with its own dependencies, testing, and deployment cycle.