# Low-Code Microservices & AI Agent Platform

Rierino is a low-code microservices and AI agent development platform with an architecture designed for scale and flexibility

{% hint style="info" icon="magnifying-glass" %}
**In brief:** Rierino is a low-code backend platform for building microservices, orchestration flows, and AI agents. You assemble services from configuration-first building blocks, then deploy them across environments as APIs, async triggers, and workflows. It also includes an internal Admin UI builder plus plug-in adapters for data stores, streaming, and external integrations. The goal is fast iteration at scale, without losing governance.
{% endhint %}

## What Rierino does

* Build microservices with configuration-first building blocks.
* Orchestrate services into APIs, async triggers, and workflows.
* Use pluggable storage, query, and integration adapters.
* Add rules, ML scoring, and AI-assisted operations where needed.

For common product and delivery patterns, see [Use Cases](/introduction/rierino-use-cases).

For the system structure and deployment model, see [Platform Architecture](/introduction/platform-architecture).

The following table compares [Rierino Core](https://rierino.com/platform/core) against different categories of traditional low code development platforms, along with the core capabilities provided out of box with Rierino:

<figure><img src="/files/s3c4ji95iHqpKI8mTs7Z" alt="Comparison of Rierino against other low-code development platform categories where Rierino provides more comprehensive backend automation capabilities."><figcaption><p>Rierino vs. Traditional Low Code Development Platforms</p></figcaption></figure>

{% embed url="<https://rierino.com/blog/low-code-platform-guide-2025>" %}

{% hint style="info" %}
Fastest way to start testing out and developing on Rierino is using our free 'Community Edition' on AWS Marketplace, which is deployed as a multi-service VM within the region and instance type of your choosing with 100% control.

<mark style="background-color:yellow;">**Click**</mark> [<mark style="background-color:yellow;">**here**</mark>](https://aws.amazon.com/marketplace/pp/prodview-up2fcxku3k742) <mark style="background-color:yellow;">**to start with AWS now.**</mark>

You can also check all alternative ways to start using Rierino [here](https://rierino.com/start).
{% endhint %}

## Admin UI for internal operations

### Internal User Experience

Rierino provides a low-code UI builder for web forms and data lists. It is typically used by internal users and partners.

It fits product, content, and asset management scenarios. It is also used for workflow task interactions and triggering automation.

The UI includes embedded BI capabilities. This keeps decision data close to the operational screens.

It also supports AI-assisted operations, such as summarizing, translating, and rewording.

You can extend the UI with 3rd party webcomponents. You can also use Handlebars templates for deeper customization.

#### Explore internal UI capabilities

* [User Interface](/design/user-interface)
* [Data Visualizations](/data-science/data-visualizations)

## Backend services, orchestration, and automation

### Microservices Development

Rierino lets you build microservices with a low-code, drag\&drop interface. Services can range from simple database operations to complex logic and ML steps.

You can build them without writing a single line of code.

You can deploy services to many environments. This includes public clouds, private clouds, on-prem, and bare metal.

#### Explore microservices

* [Microservices](/devops/microservices)

### Microservices Orchestration

Rierino can orchestrate your microservices and 3rd party services. You can model them as real-time API flows, async trigger flows, and workflows.

This lets you extend the platform using any language. It also lets you bring existing services into a consistent execution model.

#### Explore orchestration and APIs

* [API Flows](/devops/api-event-and-process-flows)
* [Gateway & Security](/devops/api-gateway-and-security)

### Workflow Management

Rierino can be used to design workflows and assign tasks to users. Users can review and add process data from customizable UI screens.

You can escalate tasks when they are not completed on time.

You can incorporate business rules and ML into workflows. This supports decision automation and process automation.

#### Explore workflow automation

* [Orchestrate User Task](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/orchestrate-user-task)

### Rule Management

Rierino includes a flexible and customizable business rule engine. Use it to configure real-time decisions for any domain. Common examples include pricing and fraud detection.

Depending on the modules deployed, rule domains may be preconfigured. You can then customize them for your business requirements.

#### Explore rule configuration

* [Business Rules](/configuration/business-rules)

### ML Automation

Rierino provides real-time ML scoring and MLOps automation capabilities. You can automate training and deploy models for real-time scoring.

Once configured, ML models built in R or Python can be converted and uploaded. They can then be used as a step in any API flow.

#### Explore machine learning capabilities

* [ML Models](/data-science/ml-models)
* [Complex Event Processing](/data-science/complex-event-processing)

### AI Agents

Rierino lets you build AI agents as first-class, deployable backend capabilities. You can develop agents with the same low-code approach used across the platform.

Agents are usually composed from:

* **Models** governed centrally, so you can swap providers safely.
* **Tools** backed by existing microservices and flows.
* **Orchestration** that controls prompts, context, and multi-step execution.

Once configured, agents can be exposed as APIs. This makes them easy to embed into apps and workflows.

For the broader AI capability model, see [Built with ML & AI](/introduction/built-with-ml-and-ai).

#### Explore AI agent development

* [GenAI Models](/data-science/genai-models)
* [Service MCP Requests](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/ml-and-ai-actions/service-mcp-requests)

## Data stores, APIs, and event integration

### Database Systems

Rierino has an open architecture for data sources. It integrates with SQL, NoSQL, search engines, and caches.

The platform also provides an abstraction layer for operations and queries. This helps you switch data systems without migrating all logic.

#### Explore data systems

* [State Managers](/devops/microservices/building-blocks/data-sources)
* [Query Managers](/devops/microservices/building-blocks/query-and-search-sources)

### External APIs

Rierino can integrate with public and private 3rd party APIs. It supports different auth mechanisms and formats (e.g. JSON, XML, SOAP, OData, GraphQL).

#### Explore external integration patterns

* [Call Rest API](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/call-rest-api)
* [Call SOAP API](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/specialized-actions/call-soap-api)
* [Integrate with Camel](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/specialized-actions/integrate-with-camel)

### Streaming Events

Rierino can consume and produce real-time event streams (for example, Kafka). This enables patterns that are hard with request-only architectures. Examples include async tasks, CDC feeds, and some analytics use cases.

#### Explore streaming and event delivery

* [Streams](/devops/microservices/building-blocks/data-and-event-streams)


# Rierino Use Cases

Rierino can boost development of any large scale backend heavy application, such as information management, decision automation, BPM, agentic operations & orchestration

{% hint style="info" icon="magnifying-glass" %}
**In brief:** Rierino is a backend heavy development platform for many modules and systems. It is most useful when you need one or more of these traits:

* **Large scale operations.** Handle millions of requests with millisecond latency.
* **Dynamic business environment.** Ship frequent changes without heavy rewrites.
* **Automation needs.** Execute critical decisions and processes at high volume.
* **Data-heavy domains.** Turn data into real-time actions and insights.
* **Modernization.** Reduce monolith debt with incremental migration to services.
* **Many integrations.** Connect internal and external systems without fragile glue.
  {% endhint %}

Rierino keeps teams focused on domain logic. It provides consistent building blocks for services and orchestration. It reduces the operational cost of scaling and integrating.

Typical applications that can be built using Rierino include:

## Information Management

Rierino's flexible data and UI model fits information management well. It works for [PIM](https://rierino.com/solutions/pim), [CMS](https://rierino.com/solutions/cms) and MDM.

These use cases usually center on data entry, enrichment, and publishing. They also need strong validation and fast retrieval at scale.

### Common scenarios

* Manage large catalogs with frequent edits and approvals.
* Enrich records using internal rules and external signals.
* Publish structured content to multiple channels and systems.

### Typical elements to start with

Start with a clean CRUD backbone and an admin UX:

* [Apps](/design/user-interface/apps) & [UIs](/design/user-interface/uis) for admin screens. Use them for listing and editing records.
* [State Managers](/devops/microservices/building-blocks/data-sources), especially [MongoDB Collection](/devops/microservices/building-blocks/data-sources/shared-states/mongodb-collection), for persistence. Use it as the operational store.
* [Runners](/devops/microservices/service-runners), especially [Spring Runners](/devops/microservices/service-runners/deploying-runners/spring-runners), for REST APIs. Keep reads and writes consistent.
* [API Flows](/devops/api-event-and-process-flows) and [Queries](/configuration/queries) for orchestration. Use them for enrichment and advanced reads.

### More advanced elements (frequently used)

These show up when you need derived views and performance layers:

* [Loading Strategies](/devops/microservices/building-blocks/data-sources/loading-strategies) and [CDC Feed](/devops/microservices/building-blocks/data-and-event-streams/cdc-feed) for CQRS patterns. Use them for cache and read models.
* [Generate Text/Html](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/generate-text-html) actions for server-side rendering. Use it for templates and rich outputs.

## Decision Automation

Rierino includes a flexible business rule engine and ML capabilities. It fits decision automation use cases like recommendations, risk scoring, and pricing.

These use cases combine deterministic rules and ML scoring. They also benefit from tight visibility into outcomes.

### Common scenarios

* Real-time eligibility and policy decisions.
* Next-best-action recommendations at request time.
* Continuous scoring from event streams.

### Typical elements to focus on

* [Apply Advanced Rules](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/specialized-actions/apply-advanced-rules) action and [Business Rules](/configuration/business-rules) configuration. Use them for rule-based decisions.
* [Use ML Models](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/ml-and-ai-actions/use-ml-models) action and [ML Models](/data-science/ml-models) configuration. Use them for AI-based decisions.
* [Data Visualizations](/data-science/data-visualizations) for insights. Use them for explainability and scenario checks.

### More advanced elements (frequently used)

These help when decisions are event-driven and time-sensitive:

* [Kafka Topic](/devops/microservices/building-blocks/data-and-event-streams/kafka-topic) and [Samza Runners](/devops/microservices/service-runners/deploying-runners/samza-runners) for real-time streams. Use them for async decisions.
* [Calculate Real-time Metrics](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/specialized-actions/calculate-real-time-metrics) action and [Complex Event Processing](/data-science/complex-event-processing) configuration. Use them for windows and joins.
* [Run Python Procedure](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/custom-code-actions/run-python-procedure) action for custom analytics. Use it for bespoke feature logic.

## Business Process Management

Rierino includes flexible authentication and task management. It fits [BPM](https://rierino.com/solutions/bpm) applications like HR, intranets, and ERP modules.

These use cases need secure access and traceable task execution. They often require human-in-the-loop steps.

### Common scenarios

* Approvals with audit trails and escalation.
* Case management with user tasks and SLAs.
* Data capture workflows with strict validation.

### Typical elements to focus on

* [Authenticate](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/gateway-actions/authenticate) action and [Gateway Servers](/devops/api-gateway-and-security/gateway-servers) for identity. Use them for role-based access.
* [Orchestrate User Task](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/orchestrate-user-task) action and [Object Widgets](/design/user-interface/uis/widgets/object-widgets) for work. Use them for task screens.
* [Condition](/devops/api-event-and-process-flows/configuring-saga-steps/condition-step) & [Transform](/devops/api-event-and-process-flows/configuring-saga-steps/transform-step) steps for control flow. Use them for branching decisions.

### More advanced elements (frequently used)

These are common once processes include files and strict validation:

* [Perform File Operation](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/perform-file-operation) and [Value Widgets](/design/user-interface/uis/widgets/value-widgets) for uploading, editing and displaying process documents and media.
* [Validate Event](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/flow-actions/validate-event) action and [Data Schema](/design/data-schema) for validation of user inputs against content structure.
* [Run Scripts](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/custom-code-actions/run-scripts) action for implementing customized logic. Use it for edge cases.

## Integration & Orchestration

Rierino includes a microservices orchestration layer. It can incorporate external services and APIs into business flows. It can act as middleware for open APIs and enterprise integrations.

These use cases focus on connecting services reliably. They need transformations, batching, and controlled execution.

### Common scenarios

* Sync master data across systems with consistent mappings.
* Orchestrate multi-step API calls with retries and fan-out.
* Integrate file-based processes into service workflows.

### Typical elements to focus on

* [Call Rest API](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/call-rest-api) and [Call SOAP API](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/specialized-actions/call-soap-api) actions for third-party calls. Use them for integrations.
* [Odata Service](/devops/microservices/building-blocks/data-sources/specialized-states/odata-service) & [Odata Queries](/configuration/queries/query-platforms/odata-queries) for OData sources. Use them for data-backed integration.
* [API Flows](/devops/api-event-and-process-flows) & [Orchestrate Saga](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/flow-actions/orchestrate-saga) action for orchestration. Use them for multi-step flows.
* Actions such as [Buffer Payloads](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/flow-actions/buffer-payloads), [Loop Each Entry](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/flow-actions/loop-each-entry) for control. Use them for batching and fan-out.

### More advanced elements (frequently used)

These help when integrations require extra dependencies or file orchestration:

* [Deployments](/devops/microservices/deployment-packages) for incorporating custom client libraries for integration.
* [Integrate with Camel](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/specialized-actions/integrate-with-camel) for integrations with less conventional services.
* [Perform File Operation](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/perform-file-operation) for orchestrating files across different systems.


# Platform Architecture

Headless, multi-tier microservices architecture with full control over security, scalability, integrations and deployment model

{% hint style="info" icon="magnifying-glass" %}
**In brief:** Rierino is a headless, micro-composable platform. The architecture has three layers:&#x20;

1. A flexible front-end with a customizable Next.js Admin UI and headless APIs for any customer channel
2. A scalable back-end with API gateways, composable Java service runners, and Python batch tasks
3. Plug-and-play storage supporting cache, NoSQL/SQL, search engines, real-time analytics stores, and data lakes
   {% endhint %}

Key components included in a full deployment are:

<figure><img src="/files/GgyBP2GDQ9JLriJKlzOO" alt="External channels → API Gateway → Service Runners → Data Stores (Cache, Operational, Search, Real-Time, Data Lake). Admin UI connects to runners via admin APIs. Batch tasks (Python) connect to data stores and external systems."><figcaption><p>Platform Architecture</p></figcaption></figure>

{% embed url="<https://rierino.com/platform/core>" %}

## Hyper-Flexible Front-end

### External UIs & Systems

Rierino is headless. It integrates with any customer-facing channel through APIs. This includes web, apps, social, video, and virtual channels.

This decoupling gives you freedom on UX and tech choices. It also keeps backend teams focused on performance and cost.

### Admin UI

Rierino ships with a highly customizable Next.js front-end for internal users. This is the **Admin UI**.

You can still integrate any custom admin UI through admin APIs. The built-in Admin UI is the fastest path to a production-ready setup.

Customize the Admin UI using Apps, UIs, Sources, and Options. See the [user interface](/design/user-interface) section.

The Admin UI also includes embedded [data visualization](/data-science/data-visualizations). Use it for BI dashboards, ML outputs, and data-quality insights. Keep insights close to the screens where users work.

## Hyper-Scalable Back-end

### API Gateways

Rierino deployments include a gateway layer. It covers request routing, authentication, and session management.

You can use an external gateway (for example, Kong). Rierino’s built-in gateway layer is often simpler to deploy and customize.

This layer typically uses a dedicated Spring Webflux deployment for Gateway Server. It communicates with runner(s) for authentication and session management.

Authentication and session management are implemented as API flows. This keeps them fully customizable. It also makes it easier to integrate existing security systems and policies.

Customize the gateway layer using Systems, Channels, Services, and Tokens. See [Gateway & Security](/devops/api-gateway-and-security).

{% hint style="info" %}
While it is possible to deploy a single gateway layer for all types of users and requests, it is recommended to have dedicated instances for different user types (e.g. internal users, sellers, buyers) to allow customized network security and performance management configurations for each.
{% endhint %}

### Micro-Composable Services

Micro-composable service runners sit at the heart of Rierino. You can design, deploy, and control them through the Admin UI.

Each runner is composed from a set of [elements](/devops/microservices/building-blocks). Elements define:

* Which data sources a runner can access
* Which functions it can execute
* Which message channels it can use

This makes it easy to build specialized micro-services.

While it is possible to develop and deploy service runners using any language or platform, Rierino is shipped with 3 main types of Java based runners:

* **Spring Runners:** Use Spring Webflux to deploy reactive web runners.
* **Samza Runners:** Use Apache Samza to deploy message-based runners.
* **Camel Runners:** Use Apache Camel to deploy runners for custom integrations.

### Batch Tasks

Rierino ships with Python libraries for common analytics and batch tasks. Use cases include data integration, segmentation, recommendation models, and data quality. It also supports import and export workloads.

Batch tasks are usually deployed and triggered by a scheduler (for example, Airflow). This improves traceability and operational resilience.

Rierino also includes DevOps features for runner deployment and maintenance. You can integrate these with external CI/CD platforms.

### 3rd Party Platforms

Rierino integrates with 3rd party solutions like payments, OMS, and WMS. It supports both REST API integration and data-based integration approaches.

## Storage and Data Systems

### Data Stores

Rierino supports multiple data systems with different latency and proximity. Each system is replaceable with minimal effort. In some cases you may only need a new adapter.

* **Cache:** Local and shared (In-Memory, Redis, Couchbase, etc.) caching options for lowest latency operations
* **Operational:** NoSQL & SQL (MongoDB, MySQL, PostgreSQL, Oracle, MS SQL, etc.) data stores used as master or read/write stores
* **Search:** Specialized search engines (Elasticsearch, Algolia, etc.) for use cases such as product search
* **Real-Time:** Columnar or similar real-time analytics data stores for insights
* **Data Lake:** Big data store for high latency and analytics use cases

### File Systems

In addition to structured and semi-structured data stores, Rierino supports file systems. Common options include FTP, HDFS, and S3. Use them for assets like trained ML models, digital assets, and documents.


# Built with ML & AI

Rierino natively supports embedding GenAI as well as traditional ML models and features into any UI, workflow or API through low-code configurations

{% hint style="info" icon="magnifying-glass" %}
**In brief:** Rierino supports extensive ML and AI capabilities out of the box. These capabilities are designed to work together. They cover productivity, agent development, protocol-based exposure, and real-time inference. You can use them independently. You can also combine them into end-to-end flows.
{% endhint %}

## 'Empowered' AI Agent Development

<figure><img src="/files/HwhHAFBJpNk1e376zA4W" alt=""><figcaption></figcaption></figure>

[Rierino AI Agent Builder](https://rierino.com/platform/agent) lets you rapidly create AI agents. Agents can access internal data sources and call enterprise systems and APIs. They can also trigger automated actions when tasks require execution, not just answers.

This enables assistants that are more than Q\&A bots. Agents can retrieve, decide, and act. They can also coordinate multiple tools in a single interaction.

### Typical agent capabilities

* Retrieve domain data (products, customers, tasks, documents).
* Enrich or validate information before taking action.
* Execute actions through APIs and flows (create orders, open tickets, send emails).
* Keep context and guide users across multi-step processes.

### Governance by default

Agent tools follow existing security policies and user access rights. This keeps assistants structured and safe for different user types. It also supports using the same agent across teams with different permissions.

### Multiple Agent Patterns

In addition to building and running individual AI agents, Rierino also allows buildings ecosystems of agents, in different formats, such as:

* **Agent Panels:** Multiple agents voting or returning responses which are processed & judged by a 'panelist' agent
* **Agent Teams:** Multiple agents working together with complementing skills, with oversight by a 'manager' agent

### When to use agents vs. flows

Use agents when users need a conversational interface. Use agents when the “next step” depends on context. Use flows alone when you want strict, fixed-step execution.

{% embed url="<https://www.youtube.com/watch?ab_channel=Rierino&v=jgKj4_019Ps>" %}

For more details [click here](/data-science/genai-models), for details on training AI agent example [click here](/examples/training-examples/ai-agent-example).

### Related Blog Posts

{% embed url="<https://rierino.com/blog/from-automation-to-agentic-ops-enterprise>" %}

{% embed url="<https://rierino.com/blog/openai-frontier-ai-orchestration-llms-vs-workflows>" %}

{% embed url="<https://rierino.com/blog/ai-agent-interfaces-a2ui-apps-sdk>" %}

## MCP Server & Middleware

<figure><img src="/files/HdLbrhkC0yxhmskNgYQb" alt=""><figcaption><p>MCP Server</p></figcaption></figure>

Rierino can service its functionality over Model Context Protocol (MCP). This is done through configuration. You select which flows become MCP tools. You select which states become MCP resources.

Security policies and user roles stay in place. This is important for enterprise use cases. It prevents tools from bypassing platform governance.

Any API, event processing, or CDC flow can be exposed as an MCP tool. Tools can still be triggered through protocols Rierino already supports. Examples include REST, WebSocket, and event streaming. This goes beyond basic MCP implementations that only wrap HTTP calls.

### Common patterns

* Build MCP servers from scratch using database access, rule evaluation, and ML prediction.
* Wrap external integrations using existing handlers and flows.
* Act as middleware by routing requests to 3rd party MCP servers when needed.

This keeps the “tool layer” consistent across internal and external capabilities.

### When MCP is a good fit

* You want to expose tools and resources to an LLM client with a standard protocol.
* You want to reuse existing API, event, or CDC flows without rebuilding tool wrappers.
* You need enterprise governance to apply to the tool layer by default.

For more details [click here](/data-science/mcp-servers).

## A2A Server & Middleware

Similar to MCP, Rierino can service functionality over Agent2Agent (A2A) protocol. This allows other agents to delegate tasks to Rierino.

You configure which LLM flows are exposed for agent-to-agent task execution. This makes it easier to build agent ecosystems. It also supports splitting responsibilities across agents and teams.

### Typical A2A use cases

* Centralize “enterprise tools” in Rierino, used by multiple agents.
* Route specialized tasks to dedicated agents (support, ops, data, commerce).
* Keep agent coordination decoupled from UI channels and client apps.

For more details [click here](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/ml-and-ai-actions/service-a2a-requests).

## AI-Powered Productivity with RAI

<figure><img src="/files/iCjr7B6ZxglylHl72QN4" alt=""><figcaption></figcaption></figure>

At the heart of Rierino’s AI-supported development experience is the AI assistant, [RAI](https://rierino.com/platform/rai). RAI is embedded directly into the Rierino UI. This keeps AI assistance close to where users configure apps, services, and data.

RAI helps both technical and non-technical users move faster. It provides a conversational interface to accelerate common tasks. It also reduces handoffs between teams by turning intent into structured changes.

### What RAI is used for

* Generate and improve content (summaries, translations, rewrites).
* Assist with creating and updating UI screens and menus.
* Help configure workflows and automation steps.
* Analyze data and suggest next actions based on context.

### Why it matters

RAI is not a separate “chat tool”. It is designed to operate inside the platform. That means it can be guided by the same roles and security controls as the UI.

### Typical teams that benefit

* Business users who need help producing and reviewing content at scale.
* Product and operations teams who need guided automation.
* Developers who want faster iteration on UI and workflow configuration.

For more details [click here](/design/user-interface/uis/menus/rai-menu-actions).

## Real-Time ML Inference

Rierino enables real-time machine learning with specialized handlers. These handlers are designed to work with a variety of ML model types. They let you score models inside APIs and workflows with millisecond-level latency.

This is useful when decisions must happen “in the transaction”. It also helps when you want consistent scoring behavior across many services.

### Typical use cases

* Dynamic pricing decisions during checkout.
* Personalized recommendations on search and browse pages.
* Fraud and risk scoring on payments and account actions.
* Real-time classification or routing of incoming requests.

### What you get

* A consistent interface for inference across models.
* Low operational overhead for integrating scoring into flows.
* A path to scale scoring as part of your backend architecture.

### Design notes

Keep feature extraction close to the scoring call. Prefer deterministic inputs and explicit versions. This makes results easier to debug and audit.

For more details [click here](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/ml-and-ai-actions/use-ml-models).

## External AI API Integration

Rierino integrates with REST API-based AI services, including OpenAI and others. This lets you access generative AI and predictive capabilities without heavy middleware.

It is useful when you want to adopt new models quickly. It is also useful when you need to call AI providers from controlled backend flows.

### Typical use cases

* Text generation, summarization, and rewriting in business workflows.
* Classification, extraction, and sentiment analysis at request time.
* Hybrid patterns that combine external LLM calls with internal data and rules.

### Why this approach scales

Calls to external AI services can be modeled like any other integration step. This keeps authentication, retries, transformation, and observability consistent. It also makes it easier to swap providers and evolve prompts over time.

### Operational considerations

External model calls have cost and latency implications. Treat prompts and model parameters as versioned configuration. Monitor both output quality and throughput over time.

For more details [click here](/data-science/genai-models).

## Python ML Training and Scoring

You can also build custom ML capabilities in Python. This includes training, evaluation, and scoring. It is a good fit when you need domain-specific models or custom feature logic.

Python integration supports both experimentation and operational execution. It also makes it easier to reuse existing data science assets and libraries.

### Typical use cases

* Predictive analytics and forecasting.
* Customer segmentation and clustering.
* Custom scoring logic for operational optimization.
* Feature engineering pipelines used by multiple services.

### How it fits into the platform

Python procedures can be orchestrated alongside other steps. This includes calls to databases, rules, and external APIs. It keeps ML work connected to the same deployment and governance model.

### What this enables

* A clear path from notebooks to scheduled jobs.
* Shared scoring logic between batch and real-time flows.
* Custom libraries and domain-specific model pipelines.

For more details [click here](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/custom-code-actions/run-python-procedure).


# Rierino Claude Plugin

Connect Claude Code and Claude Desktop to Rierino with platform-aware skills, specialist agents, slash commands, and an authenticated MCP proxy.

## Rierino Claude Plugin

Rierino Claude Plugin connects Claude to the Rierino low-code development platform so teams can work with Rierino configurations, flows, schemas, UI definitions, rules, scripts, and AI assets directly from their AI-assisted development workflow.

{% hint style="info" %}
**In brief:** Use this plugin when you want Claude to understand Rierino platform concepts and help you build, review, explain, or operate Rierino assets. It packages Rierino-specific skills, specialist agents, slash commands, and an authenticated MCP proxy for platform operations.
{% endhint %}

### At a glance

* Connects Claude Code and Claude Desktop to Rierino.
* Adds Rierino-aware development skills and specialist agents.
* Provides `/rierino-status` for platform connectivity checks.
* Provides `/rierino-mcp` for listing available MCP tools, resources, templates, and prompts.
* Uses an authenticated MCP proxy to reach Rierino REST and MCP endpoints.
* Discovers MCP capabilities dynamically from the connected Rierino server.
* Helps generate and maintain configuration-first assets such as schemas, queries, sagas, UIs, rules, handlers, templates, and AI agent definitions.

### Why it matters

Rierino is designed around configuration-first development for microservices, orchestration flows, internal applications, integrations, ML, GenAI, and AI agents. The Claude plugin brings that same model into Claude: instead of asking a generic assistant to guess Rierino conventions, you can use a plugin that already includes Rierino-specific instructions, standards, and task-focused agents.

This makes Claude more useful for:

* creating new Rierino assets from a business requirement,
* reviewing existing platform configuration,
* explaining complex flows in plain language,
* generating valid JSON configuration structures,
* producing transformation logic, templates, scripts, and test data,
* discovering available MCP tools and resources from a live Rierino environment.

### How it works

```mermaid
flowchart LR
    U[User] --> C[Claude Code or Claude Desktop]
    C --> S[Rierino skills and agents]
    C --> CMD[Slash commands]
    C --> MCP[Authenticated MCP proxy]
    MCP --> AUTH[Rierino authentication]
    AUTH --> R[Rierino MCP / REST APIs]
    R --> TOOLS[Tools, resources, prompts, templates]
```

The plugin has four main parts:

| Component     | What it adds                                                                              | Why it is useful                                                            |
| ------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| **Skills**    | Task-specific instructions for building Rierino assets                                    | Keeps Claude aligned with Rierino conventions and expected output formats   |
| **Agents**    | Specialized assistants for schemas, queries, UIs, sagas, scripts, rules, agents, and more | Lets users delegate focused platform tasks to the right assistant           |
| **Commands**  | `/rierino-status` and `/rierino-mcp`                                                      | Gives quick connectivity and capability checks inside Claude                |
| **MCP proxy** | Authenticated bridge between Claude and the Rierino server                                | Enables live platform operations while keeping tool discovery server-driven |

### Included capabilities

#### Authenticated MCP proxy

The plugin includes a Node.js MCP proxy that bridges Claude's stdio-based MCP communication to a Rierino HTTP JSON-RPC MCP endpoint.

Key behavior:

* authenticates against the configured Rierino instance,
* forwards JSON-RPC MCP calls to Rierino,
* discovers tools at runtime instead of hardcoding tool definitions in the plugin,
* refreshes authentication tokens automatically,
* retries once after a `401` response by refreshing credentials,
* masks raw JWTs before responses are returned to Claude,
* uses built-in Node.js modules only, with no separate build step.

{% hint style="warning" %}
Do not commit Rierino credentials to source control. Prefer passing credentials through the MCP configuration `env` block or through a `.env` file stored outside the project folder. Add local MCP and environment files to `.gitignore` when they contain instance-specific values.
{% endhint %}

#### Rierino-aware skills

Skills provide reusable instructions for Claude. They tell Claude how to handle Rierino-specific structures, naming rules, data conventions, output formats, and task-specific requirements.

All skills follow the same general pattern:

1. Read the global conventions and operational rules.
2. Read the task-specific `SKILL.md` file.
3. Use any local references before making platform calls.
4. Return clean output that can be copied into Rierino or used by another workflow.

The plugin includes skills for:

| Skill                 | Use it for                                                         |
| --------------------- | ------------------------------------------------------------------ |
| `schema_builder`      | JSON Schema definitions and data model structure                   |
| `query_builder`       | Structured query definitions, filters, aggregations, and pipelines |
| `ui_assistant`        | Screen and UI configuration JSON                                   |
| `component_builder`   | React editor components for the page builder                       |
| `lister_builder`      | React list and lister display components                           |
| `code_assistant`      | Groovy scripts and JavaScript event handlers                       |
| `saga_assistant`      | Saga flow definitions for APIs, events, and workflows              |
| `template_assistant`  | Handlebars templates for storefront and experience layers          |
| `jmespath_assistant`  | JMESPath expressions and transformation pipelines                  |
| `element_assistant`   | SYSTEM Element configuration for integrations                      |
| `drools_assistant`    | Drools Rule Language rule generation                               |
| `test_data_generator` | Realistic mock JSON records for testing                            |
| `workflow_explainer`  | Human-readable explanations of saga flows                          |
| `ai_agent_assistant`  | Rierino AI agent configuration and design support                  |

#### Specialist agents

Agents are higher-level assistants that delegate to the matching skill. They are useful when a task needs multiple steps, interpretation, or iteration.

Examples:

| Agent                 | Typical request                                                                          |
| --------------------- | ---------------------------------------------------------------------------------------- |
| `schema_builder`      | “Create a customer profile schema with marketing preferences.”                           |
| `query_builder`       | “Build an aggregation query for monthly order revenue by channel.”                       |
| `saga_assistant`      | “Design an API flow that validates an order, calls inventory, and writes a reservation.” |
| `ui_assistant`        | “Generate an admin screen for editing product content.”                                  |
| `workflow_explainer`  | “Explain what this saga does for a business analyst.”                                    |
| `test_data_generator` | “Generate ten realistic records for this schema.”                                        |
| `ai_agent_assistant`  | “Design an agent that can look up product data and trigger a support workflow.”          |

#### Slash commands

The plugin adds commands that are available from Claude after installation.

| Command           | Purpose                                                                                                  |
| ----------------- | -------------------------------------------------------------------------------------------------------- |
| `/rierino-status` | Checks Rierino platform connectivity using health and ping-style requests.                               |
| `/rierino-mcp`    | Lists available MCP tools, resources, resource templates, and prompts from the connected Rierino server. |

Common verification flow:

```
/rierino-status
/rierino-mcp tools
```

#### Runtime MCP discovery

Rierino MCP tools are registered by the Rierino server and discovered at runtime. This means the plugin does not need to ship a fixed list of tools. As the connected Rierino environment exposes new tools, resources, prompts, or templates, Claude can discover them through the MCP list commands.

This is especially useful when your Rierino MCP server maps:

* saga flows as tools,
* prompts as reusable prompt assets,
* state managers as static resources,
* state managers as dynamic resource templates.

### How it fits into the Rierino development model

Rierino development commonly spans Devops, Configuration, Design, and Data Science assets. The Claude plugin supports work across all of these areas.

| Rierino area      | Plugin support                                                                                                     |
| ----------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Devops**        | Build and explain sagas, API flows, workflow flows, scripts, and backend orchestration logic.                      |
| **Configuration** | Create and refine queries, business rules, dynamic handlers, JMESPath expressions, and reusable logic definitions. |
| **Design**        | Generate schemas, screen configurations, listers, UI components, templates, and admin experience assets.           |
| **Data Science**  | Help define AI agents, GenAI-related configurations, MCP-facing tools, mock data, and test scenarios.              |

### Example use cases

#### Build an API flow faster

Ask the `saga_assistant` to draft a saga from a business requirement. Then use `workflow_explainer` to produce a plain-language explanation for reviewers.

```
Create a saga that receives an order request, validates the customer, checks stock, creates a reservation, and returns a confirmation response.
```

#### Generate a schema and matching UI

Use `schema_builder` to define the data structure, then `ui_assistant` to create a matching admin screen.

```
Create a JSON Schema for a product bundle and then generate a Rierino admin UI for editing it.
```

#### Create transformation logic

Use `jmespath_assistant` when you need to reshape JSON between services, normalize API responses, or prepare data for a UI or template.

```
Transform this external product response into our internal product schema using JMESPath.
```

#### Discover live MCP capabilities

Use `/rierino-mcp` to inspect what the connected Rierino server currently exposes.

```
/rierino-mcp tools
/rierino-mcp resources
/rierino-mcp prompts
```

#### Create realistic test records

Use `test_data_generator` to produce varied, realistic payloads that match a schema or service contract.

```
Generate 20 test customers with realistic addresses, consent flags, and order summaries.
```

### Installation

#### Claude Code

Claude Code supports plugins through the plugin manager.

**Option A — Add the Rierino marketplace**

Open Claude Code and run:

```
/plugins
```

Add this marketplace source:

```
https://raw.githubusercontent.com/rierino-open/rierino-claude-plugin/main/.claude-plugin/marketplace.json
```

Then install:

```
rierino-development
```

**Option B — Install directly from the plugin URL**

Open Claude Code and run:

```
/plugins
```

Choose **Add Plugin from URL**, then enter:

```
https://raw.githubusercontent.com/rierino-open/rierino-claude-plugin/main/development/.claude-plugin/plugin.json
```

#### Claude Desktop

1. Open Claude Desktop.
2. Go to **Customize**.
3. Open **Personal plugins**.
4. Choose **Create plugin** or add a marketplace/repository source.
5. Add the repository:

```
rierino-open/rierino-claude-plugin
```

6. Install `rierino-development`.

{% hint style="info" %}
After installation, restart Claude if the plugin commands do not appear immediately. Some Claude clients register plugin commands at startup.
{% endhint %}

### Configuration

The MCP proxy needs a Rierino base URL and credentials. The recommended approach is to pass credentials through the MCP server configuration rather than storing them inside the plugin folder.

Example MCP configuration:

```json
{
  "mcpServers": {
    "rierino": {
      "command": "node",
      "args": ["/absolute/path/to/rierino-claude-plugin/development/servers/rierino-mcp/proxy.js"],
      "env": {
        "RIERINO_BASE_URL": "https://your-instance.rierino.com",
        "RIERINO_USERNAME": "your-username",
        "RIERINO_PASSWORD": "your-password"
      }
    }
  }
}
```

For direct links back into the Rierino UI, also configure the UI base URL in a local project `.env` file:

```bash
RIERINO_UI_BASE_URL=https://your-instance.rierino.com
```

Suggested local ignore rules:

```gitignore
.mcp.json
.env
```

### Security model

The plugin is designed to keep authentication handling inside the MCP proxy process.

Important behavior:

* Rierino credentials are read by the proxy process.
* The proxy authenticates with Rierino and forwards MCP requests with the active token.
* JWTs returned by the backend are replaced with opaque handles before Claude sees them.
* Handles are backed by an in-memory AES-256-GCM token vault.
* The vault key is generated when the proxy starts and is not persisted.
* Access to platform operations is still governed by the connected Rierino environment and the configured user credentials.

{% hint style="success" %}
The practical result is that Claude can work with Rierino capabilities through MCP without needing raw token values in the conversation context.
{% endhint %}

### Troubleshooting

| Problem                               | What to check                                                                                              |
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Plugin commands are not available     | Confirm the plugin is installed, then restart Claude.                                                      |
| MCP tools do not appear               | Run `/rierino-mcp tools` and confirm the MCP proxy path and credentials are correct.                       |
| Login fails with `401`                | Check `RIERINO_USERNAME`, `RIERINO_PASSWORD`, and the target `RIERINO_BASE_URL`.                           |
| Platform health check fails           | Run `/rierino-status`, then confirm the Rierino gateway is reachable from your machine.                    |
| Plugin seems outdated after an update | Remove and reinstall the plugin, then restart Claude. If needed, remove and re-add the marketplace source. |
| Token errors after restart            | Re-authentication is expected because the token vault key is generated per proxy process.                  |

### When to use this plugin

Use Rierino Claude Plugin when you want Claude to help with any of the following:

* building APIs, event flows, and workflow sagas,
* creating schemas and data contracts,
* designing admin screens and UI mappings,
* writing Rierino-compatible scripts and handlers,
* building structured queries and transformations,
* creating business rules and decision logic,
* explaining flows to technical and non-technical stakeholders,
* preparing realistic test data,
* exploring live MCP tools and resources,
* designing AI agents that use Rierino services as tools.

### Where to go next

* [Development](https://docs.rierino.com/quick-start/development) — understand how Rierino development apps fit together.
* [Built with ML & AI](https://docs.rierino.com/introduction/built-with-ml-and-ai) — learn how Rierino supports RAI, AI agents, MCP, A2A, and ML automation.
* [MCP Servers](https://docs.rierino.com/data-science/mcp-servers) — learn how Rierino exposes sagas, prompts, resources, and templates over MCP.
* [Rierino Claude Plugin on GitHub](https://github.com/rierino-open/rierino-claude-plugin) — view the plugin source, README, and latest installation instructions.


# Rierino FAQ

This page lists frequently asked questions about Rierino platform positioning and architecture

## Frequently asked questions

### What is low-code?

<details>

<summary>Show answer</summary>

Low-code is a way to build software mostly through configuration, visual tools, and reusable components.

It reduces the amount of hand-written code needed for common features such as APIs, workflows, forms, and integrations.

Teams still use code for edge cases, custom logic, or deeper extensions.

</details>

### What are the types of low-code platforms?

<details>

<summary>Show answer</summary>

Low-code platforms usually focus on one or more of these areas:

* **Internal app builders** for forms, lists, and back-office screens
* **Workflow and BPM platforms** for process automation and task management
* **Integration platforms** for connecting APIs, events, and external systems
* **Database and CRUD app builders** for data entry and record management
* **Backend and microservices platforms** for APIs, orchestration, business logic, and automation

</details>

### How does low-code compare with vibe coding?

<details>

<summary>Show answer</summary>

Low-code and vibe coding solve different parts of the same problem.

Low-code gives teams structured building blocks, reuse, governance, and operational control. It is strong for production systems that need consistency, security, and maintainability.

Vibe coding is strong for rapid exploration, prototyping, and generating custom logic with AI assistance. It helps teams move faster when they need something more tailored.

They complement each other instead of replacing each other.

In practice, teams can use vibe coding to create or refine custom pieces, while low-code provides the stable platform for deploying, integrating, governing, and evolving the full solution.

</details>

### What is Rierino?

<details>

<summary>Show answer</summary>

Rierino is a low-code backend platform for building microservices, APIs, workflows, and AI agents.

It combines service development, orchestration, integrations, and an internal Admin UI in one platform.

</details>

### Is Rierino only for low-code teams?

<details>

<summary>Show answer</summary>

No.

It works for business and technical users together. Teams can move fast with configuration-first building blocks. Developers can still extend the platform when needed.

See [Overview](/) and [Pro-Code](/devops/pro-code).

</details>

### What kinds of applications can I build?

<details>

<summary>Show answer</summary>

Rierino fits backend-heavy applications with many workflows, integrations, or data operations.

Common examples include:

* Information management systems such as PIM, CMS, and MDM
* Decision automation such as pricing, risk, and recommendations
* BPM and task-driven internal applications
* Integration and orchestration layers across many systems
* AI-enabled services and agents

See [Use Cases](/introduction/rierino-use-cases).

</details>

### Does Rierino include a user interface?

<details>

<summary>Show answer</summary>

Yes.

Rierino includes a built-in Admin UI for internal users. You can use it for forms, data lists, workflows, and operational screens.

It is best suited for internal tools, partner portals, and back-office processes.

See [User Interface](/design/user-interface).

</details>

### Can I use my own front-end?

<details>

<summary>Show answer</summary>

Yes.

Rierino is headless. You can connect any customer-facing web, mobile, or external system through APIs.

The built-in Admin UI is optional. It is simply the fastest path for internal tooling.

See [Platform Architecture](/introduction/platform-architecture).

</details>

### What does the platform architecture look like?

<details>

<summary>Show answer</summary>

Rierino has three main layers:

* A front-end layer for internal UIs and external channels
* A back-end layer with gateways, service runners, and orchestration
* A storage layer with pluggable databases, caches, search, and analytics stores

This structure keeps the platform flexible and scalable.

See [Platform Architecture](/introduction/platform-architecture).

</details>

### Can I build microservices without writing code?

<details>

<summary>Show answer</summary>

Yes.

You can assemble services from runners, handlers, states, queries, and flows through configuration. This covers common CRUD, orchestration, integration, and automation use cases.

You can also add custom code when you need deeper specialization.

See [Microservices](/devops/microservices) and [API Flows](/devops/api-event-and-process-flows).

</details>

### Can Rierino orchestrate existing services?

<details>

<summary>Show answer</summary>

Yes.

Rierino can orchestrate its own services and external services in the same flow. That includes REST APIs, SOAP services, event streams, and file-based processes.

This makes it useful as both an application platform and an integration layer.

</details>

### Which data systems does Rierino support?

<details>

<summary>Show answer</summary>

Rierino supports multiple storage types through adapters.

That includes SQL databases, NoSQL databases, caches, search engines, file systems, and analytics-oriented stores.

This helps teams switch or combine data systems without rewriting all service logic.

See [State Managers](/devops/microservices/building-blocks/data-sources) and [Query Managers](/devops/microservices/building-blocks/query-and-search-sources).

</details>

### Does Rierino support event-driven and async patterns?

<details>

<summary>Show answer</summary>

Yes.

Rierino can consume and produce streams such as Kafka. It also supports async triggers, CDC-based flows, and real-time processing patterns.

This is useful for high-volume automation and loosely coupled architectures.

See [Streams](/devops/microservices/building-blocks/data-and-event-streams).

</details>

### What AI and ML capabilities are included?

<details>

<summary>Show answer</summary>

Rierino supports both traditional ML and generative AI.

You can use ML for real-time scoring. You can use GenAI for assistants, content generation, and AI agents. You can also expose capabilities through MCP and A2A protocols.

See [Built with ML & AI](/introduction/built-with-ml-and-ai).

</details>

### Can I build AI agents on Rierino?

<details>

<summary>Show answer</summary>

Yes.

Rierino lets you build agents that use governed models, call internal tools, access enterprise data, and trigger actions.

This makes the agents useful for real business tasks, not only Q\&A.

See [GenAI Models](/data-science/genai-models).

</details>

### Can Rierino use external AI services?

<details>

<summary>Show answer</summary>

Yes.

You can call external AI APIs from backend flows just like any other integration. This helps with summarization, extraction, classification, and prompt-driven automation.

It also keeps authentication, retries, and observability consistent.

</details>

### Which deployment environments does Rierino support?

<details>

<summary>Show answer</summary>

Rierino can be deployed in public cloud, private cloud, on-prem, or bare metal environments.

This gives teams full control over security, scale, and operating model.

</details>

### When is Rierino a good fit?

<details>

<summary>Show answer</summary>

Rierino is strongest when you need one or more of these:

* Large-scale operations
* Frequent business change
* Many integrations
* Data-heavy workflows
* Decision automation
* Incremental modernization from monoliths

See [Use Cases](/introduction/rierino-use-cases).

</details>

### What is the fastest way to get started?

<details>

<summary>Show answer</summary>

Start with the [Overview](/), then move into [Installation](/quick-start/rierino-installation) and [Quick Start](/quick-start/rierino-installation).

If you already know what you want to build, use [I would like to start with...](/quick-start/i-would-like-to-start-with...).

</details>


# Rierino Installation

Our dedicated installation documentation provides step-by-step guidance and our AWS marketplace offering can get you started immediately

## Easy Access to Rierino

Fastest way to start testing and developing on Rierino is using our free **Community Edition** on AWS Marketplace. It is deployed as a multi-service VM. You can choose the region and instance type. You also get full control of the environment.

<mark style="background-color:yellow;">**Click**</mark> [<mark style="background-color:yellow;">**here**</mark>](https://aws.amazon.com/marketplace/pp/prodview-up2fcxku3k742) <mark style="background-color:yellow;">**to start with AWS now.**</mark>

### What you get with Community Edition

* A ready-to-use environment for exploring the platform.
* A good baseline for running MVPs and small projects.
* A fast path to validate the architecture before scaling up with a custom installation.

## Custom Installation

For installing Rierino yourself, follow the [Installation](https://docs.rierino.com/installation/) documentation. Custom installation requires licensing. You can check alternative ways to start using Rierino [here](https://rierino.com/start).

### Common installation options

* **Single VM:** use the Docker Compose setup in [Sandbox Deployment](/installation/deployment-alternatives/sandbox-vm-deployment).
* **Kubernetes:** use the fully automated Helm Chart option in [Kubernetes Deployment](/installation/deployment-alternatives/kubernetes-deployment).

The standard configuration uses **MongoDB** as the main data store. This is a good default for most training and initial development.

## Secrets and Configurations

Integrating Rierino with external systems, such as database solutions, enterprise systems and file systems require configuration of connection details as well as credentials. While it is possible to define such configurations directly within Rierino UI, it is recommended to keep these values inside external configuration files (especially for secrets). Depending on the deployment option the most common way to define these configurations are as follows:

* **Single VM:** globalconfig.properties and globalsecrets.properties files under admin\_runner folder are used
* **Kubernetes:** global-config ConfigMap and global-secrets Secret under admin-backend namespace are used


# Layout & Navigation

Rierino provides an "App" level, which allows grouping of user screens into departmental and business domain specific groups

## Global Home Page

The global home page is the default landing page for the Admin UI. It lists the screens and AI agents you can access, plus quick links, favorites, and recently visited screens.

<figure><img src="/files/d8H9Sfjz3uN4Smrv0cWK" alt=""><figcaption><p>Global Home Page</p></figcaption></figure>

Open it at `https://[YOUR_ADMIN_UI_DOMAIN]`.

{% hint style="info" %}
The global home page is fully configurable using templates. The screenshots show the default template shipped with Rierino Core.
{% endhint %}

## App Home Page

Each app has its own home page. It summarizes the app and links to its screens, split across three tabs.

{% tabs %}
{% tab title="Modules" %}

<figure><img src="/files/D1IoMfwxhS632nDaRLUA" alt=""><figcaption><p>App Home Page - Modules</p></figcaption></figure>

Lists the app’s screens, grouped by category.
{% endtab %}

{% tab title="Profile" %}

<figure><img src="/files/KxIYfO4gk8zJqJ41vO3W" alt=""><figcaption><p>App Home Page - Profile</p></figcaption></figure>

Gives an overview of the app, including useful links and the AI accelerators used in the app.
{% endtab %}

{% tab title="FAQs" %}

<figure><img src="/files/5LgrHTcXSVfiZxWfZcj9" alt=""><figcaption><p>App Home Page - FAQs</p></figcaption></figure>

Lists common questions and answers for the app.
{% endtab %}
{% endtabs %}

Open it at `https://[YOUR_ADMIN_UI_DOMAIN]/app/[ID]`.

{% hint style="info" %}
App home pages are fully configurable using templates. The screenshots show the default template shipped with Rierino Core.
{% endhint %}

## Listing Page

A typical screen in Rierino within an App consists of 3 main building blocks, used for navigation, listing records and editing them.

<figure><img src="/files/N3KEpqjFPBt4FjNZMeZH" alt=""><figcaption><p>Listing Page Layout</p></figcaption></figure>

### 1) Navigation Bar

The navigation bar is the main way to move around the Admin UI. It provides access to the global home page, apps, screens, AI agents, and the user menu.

You can hide it on specific screens using the `noNav` parameter. Most deployments keep it visible for consistent navigation.

#### Typical navigation flow

Most users follow this pattern:

1. Go to the global home page.
2. Switch to the right app.
3. Pick a screen from the screen icons.
4. Use the lister to find a record.
5. Use the editor to view or change details.

#### Global home

The top logo icon takes users back to the global home page. This logo can be customized from the icon UI.

The global home page usually lists:

* All accessible apps
* User favorites and pinned entries (if configured)

#### App switcher

Below the logo is the app icon. It opens the app switch menu. Selecting an app routes the user to that app’s landing page.

<figure><img src="/files/PjLFvclPBsK5pMlEaOwt" alt="" width="375"><figcaption><p>App Switch</p></figcaption></figure>

#### Screen shortcuts

Under the app switcher is a list of icons. Each icon represents a screen in the current app. Most screens combine a records lister and an object editor.

#### AI agents

Just above the bottom is the AI icon ✨. It lets users connect to AI agents for help and task execution.

<figure><img src="/files/mwdvrAScep4u3c60AgcD" alt=""><figcaption><p>AI Agent Listing</p></figcaption></figure>

{% hint style="info" %}
The agent listing page is fully configurable using templates. The screenshots show the default template shipped with Rierino Core.
{% endhint %}

#### User menu

At the bottom is the user menu. It shows the current user. It also provides quick access to common settings:

* Changing the language of admin UI
* Changing the theme / style of admin UI
* Changing the active branch (if enabled)
* Listing and accessing recently visited screens
* Accessing help center
* Logging out of the admin UI

<figure><img src="/files/hoHfm0kcD0TUQ4bNveki" alt="" width="220"><figcaption><p>User Menu</p></figcaption></figure>

### 2) Records Lister

Most screens include a list of records. These can be technical records or business records. Common examples include products, customers, and tasks to be completed.

Two common layouts are used:

* A **collapsible menu lister** for quick navigation and smaller datasets.
* A **full-page lister** (for example, a table or a map) for larger views and richer filtering.

#### What the lister is responsible for

In practice, the lister is the “finding and selecting” layer. It typically handles:

* Searching and filtering
* Sorting and paging
* Selecting one record to edit, or a set of records to act on
* Showing compact context before opening an editor

### 3) Object Editor

The object editor is used to view and edit a selected record. It is also used to create new records.

Editors can be shown:

* Inline on the page, next to the lister
* As a pop-up dialog, to keep the user focused on one task

#### What the editor is responsible for

The editor is the “detail and action” layer. It typically handles:

* Displaying the full record and related fields
* Validating user input before saving
* Triggering actions (for example, through menus and buttons)
* Supporting multi-step tasks where users need guided data entry

Object editors support the following shortcuts:

<table><thead><tr><th width="206.9393310546875">Shortcut</th><th>Action</th></tr></thead><tbody><tr><td>Ctrl + S</td><td>Save current record</td></tr><tr><td>Ctrl + .</td><td>Creates a new record</td></tr></tbody></table>


# Development with Rierino

Devops, Configuration, Design and Data Science apps allow users develop sophisticated enterprise applications rapidly through low-code interfaces

## Rierino Development Apps

Most development work in Rierino happens across four apps. Each app “owns” a slice of the platform, so you can iterate without mixing concerns.

### Devops

Use **Devops** to build and operate backend execution. This is where you define and deploy **runners** (microservices), design **sagas** (API flows), configure **gateway routing/security**, and manage deployments.

Start here when you are building APIs, orchestrations, or anything that needs to run in production. See [Devops Overview](/devops/devops-overview).

### Configuration

Use **Configuration** to store “logic as data”. This is where you define reusable **queries**, **business rules**, and **dynamic handlers**, which can then be executed by runners and sagas at runtime.

Start here when you want behavior to be editable without redeploying services. See [Configuration Overview](/configuration/configuration-overview).

### Design (Admin UI)

Use **Design** to build the admin UI. This is where you define **apps**, **UIs**, **listers/widgets**, and the **Source** mappings that connect screens to backend APIs. You also manage UI resources like options, translations, icons, and styles.

Start here when you want a screen for listing and editing data or operating flows. See [Design Overview](/design/design-overview).

### Data Science

Use **Data Science** to configure ML and GenAI assets that can be invoked from real-time APIs or batch processes. This includes ML models, GenAI models, MCP servers, CEP flows, visualizations, and customizations.

Start here when your use case needs inference, agents, personalization, or stream processing. See [Data Science Overview](/data-science/data-science-overview).

### How they fit together (typical workflow)

Most teams iterate in a loop: define runtime services in **Devops**, keep reusable logic in **Configuration**, expose operations through **Design** screens, and add intelligence through **Data Science** assets when needed. The boundaries are intentional, but the components are designed to compose cleanly.

## Where to Start

To start using Rierino right away, use the training microservices shipped with the standard installation. They let you explore the platform without building anything from scratch.

Focus on the following concepts first:

* Start using existing training microservices with [saga flows](/devops/api-event-and-process-flows).
* Perform [read](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/read-data) and [write](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/write-data) operations on existing runners.
* Perform [query](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/query-data) operations and visually design [queries](/configuration/queries).
* Integrate with 3rd party [API based systems](/devops/microservices/building-blocks/systems-integrations/api-based-systems) and [call their APIs](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/call-rest-api).
* Build new [UIs](/design/user-interface/uis) and add them to [Apps](/design/user-interface/apps).

If you prefer a guided path, complete the [self-paced interactive training](https://rierino-open.github.io/training/intro-core-capabilities/8912351230123.html). It introduces the main concepts and terminology using hands-on steps.

## Training Examples

Once you are comfortable with the basics, use the examples below to build confidence. They are also a good way to validate that your deployment is working end to end.

* Reviewing [Training APIs](/examples/training-examples/api-flow-examples) & creating an [API endpoint](/examples/training-examples/exercise-create-an-api-endpoint)
* Reviewing [Training Microservices](/examples/training-examples/microservice-examples) & creating a [CRUD service](/examples/training-examples/exercise-create-a-crud-service)
* Reviewing [Training UI](/examples/training-examples/ui-example) & creating a [UI screen](/examples/training-examples/exercise-create-a-ui-screen)
* Reviewing [Training AI Agent](/examples/training-examples/ai-agent-example)
* Building a complete [To-do List App](/examples/in-depth-exercise)

### Video walkthroughs

You can also visit our [YouTube channel](https://www.youtube.com/@rierino) for QuickBuild videos. These are useful when you want to see a full workflow, start to finish.

{% embed url="<https://www.youtube.com/watch?ab_channel=Rierino&v=iW_klLfvJuk>" %}

## Troubleshooting

Rierino provides multiple ways to audit and troubleshoot issues. Start with these quick checks:

* Checking meaning or [Error Codes](/troubleshooting/error-codes) returned
* Performing [checks for common errors](/troubleshooting/useful-checks)
* Checking feature availability by versions in [release notes](/troubleshooting/rierino-release-notes)

If you are stuck early, validate that:

* Your gateway is reachable.
* Your training microservices are deployed.
* Your data store is accessible (MongoDB by default).


# I would like to start with...

Use this page when you know what you want to build, but not where to start.

{% hint style="info" %}
If you are brand new to the platform, first skim [Development](/quick-start/development-with-rierino) and [Training Examples](/examples/training-examples). They give you the basic mental model fast.
{% endhint %}

## A CRUD service

**Typical use cases**

* You need a backend for a front-end or admin tool.
* You want standard create, read, update, and delete endpoints.
* You want to expose a collection or table quickly.

This is the fastest path in Rierino. In most cases, you only need to drag & drop an element to an existing runner and click on save.

**Start here**

* [Exercise: Create a CRUD Service](/examples/training-examples/exercise-create-a-crud-service)
* [Video: Build full CRUD under 60 seconds](https://www.youtube.com/watch?v=iW_klLfvJuk)

**Learn next**

* [State Managers](/devops/microservices/building-blocks/data-sources) for storage patterns
* [Runners](/devops/microservices/service-runners) for selecting microservices for your services
* [Gateway Channels](/devops/api-gateway-and-security/gateway-servers/gateway-channels) for granular control on RBAC

## An API endpoint

**Typical use cases**

* You need more than standard CRUD behavior.
* You want a custom request/response contract.
* You need validation, transformation, aggregation, or branching.
* You want an API-first architecture.

In Rierino, custom APIs usually start as **Sagas**. A saga is a flow. It can call handlers, states, queries, and other services.

**Start here**

* [Exercise: Create an API Endpoint](/examples/training-examples/exercise-create-an-api-endpoint)

**Most common flow steps**

* [Read Data](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/read-data)
* [Write Data](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/write-data)
* [Query Data](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/query-data)
* [Transform Step](/devops/api-event-and-process-flows/configuring-saga-steps/transform-step)
* [Condition Step](/devops/api-event-and-process-flows/configuring-saga-steps/condition-step)

**Learn next**

* [API Flows](/devops/api-event-and-process-flows) for details on how to build Sagas
* [Handlers](/devops/microservices/building-blocks/execution-handlers) for rich set of actions available in steps

## Multi-systems integration or orchestration

**Typical use cases**

* You need to call third-party APIs.
* You need to combine multiple internal services.
* You need fan-out, batching, retries, or transformations.
* You want middleware or ESB-like behavior.

This path is also saga-first. The difference is that the saga coordinates **multiple systems**, not just one endpoint.

**Start here**

* [Call Rest API](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/call-rest-api)
* [Video: Integrate External APIs in 2 Minutes](https://www.youtube.com/watch?v=4KXbjt1qylk)

**Learn next**

* [API Based Systems](/devops/microservices/building-blocks/systems-integrations/api-based-systems)
* [Call SOAP API](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/specialized-actions/call-soap-api)

## An internal application

**Typical use cases**

* You need an admin tool or back-office UI.
* You want forms, lists, editors, and actions without custom front-end code.
* You want internal users to manage data or trigger flows.

**Start here**

* [Exercise: Create a UI Screen](/examples/training-examples/exercise-create-a-ui-screen)
* [Video: Build a Functional UI in 2 Minutes](https://www.youtube.com/watch?v=qWVzLsIXTmA\&t=26s)

**Learn next**

* [Apps](/design/user-interface/apps) for grouping UIs into applications
* [UIs](/design/user-interface/uis) for creating data entry and workflow forms
* [API Mapping](/design/api-mapping) for mapping backend to frontend
* [Data Schema](/design/data-schema) for structuring your data model
* [Orchestrate User Task](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/orchestrate-user-task) for business process flows

## An AI agent

**Typical use cases**

* You want a conversational interface on top of your services.
* You want an agent that can call tools, not just chat.
* You want to expose capabilities as agent APIs, MCP, or A2A.

Rierino agents are usually built from:

* a governed **GenAI model**
* one or more **tool sagas** or **tool states**
* optional **interfaces** for richer responses

**Start here**

* [AI Agent Example](/examples/training-examples/ai-agent-example)
* [Video: Build Actionable AI Agents in 2 Minutes](https://www.youtube.com/watch?v=jgKj4_019Ps)
* [GenAI Models](/data-science/genai-models)

**Learn next**

* [AI Agent APIs](/data-science/genai-models/ai-agent-apis)
* [Service MCP Requests](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/ml-and-ai-actions/service-mcp-requests)
* [Service A2A Requests](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/ml-and-ai-actions/service-a2a-requests)

## If you are not sure which path fits

Use this quick rule:

* Need standard data APIs fast → start with **CRUD service**
* Need custom business endpoints → start with **API endpoint**
* Need multi-system coordination → start with **integration or orchestration flow**
* Need an internal screen → start with **internal application**
* Need conversational automation → start with **AI agent**

If you want one guided path that touches most core concepts, start with the [In-depth Exercise](/examples/in-depth-exercise).


# Quick Start FAQ

This FAQ helps new teams get started fast, it covers setup, navigation, which app to use, and where to begin for common build paths

## Frequently asked questions

### What is the fastest way to try Rierino?

<details>

<summary>Show answer</summary>

The fastest path is the free Community Edition on AWS Marketplace.

It gives you a ready-to-use environment for exploring the platform and validating the architecture quickly.

See [Installation](/quick-start/rierino-installation).

</details>

### Do I need to install everything myself first?

<details>

<summary>Show answer</summary>

No.

You can start with the hosted marketplace option first. Use custom installation when you need a licensed, self-managed setup for your own environment.

Common self-managed options are a single VM with Docker Compose or Kubernetes with Helm.

See [Installation](/quick-start/rierino-installation).

</details>

### Which data store should I expect by default?

<details>

<summary>Show answer</summary>

Most standard setups use MongoDB as the main data store.

That is a good default for training, initial development, and many early projects.

</details>

### Where do I define secrets and connection settings?

<details>

<summary>Show answer</summary>

Keep secrets and connection values outside the UI when possible.

On a single VM, they usually live in `globalconfig.properties` and `globalsecrets.properties`. On Kubernetes, they are commonly stored in ConfigMaps and Secrets.

See [Installation](/quick-start/rierino-installation).

</details>

### What is the main entry point in the Admin UI?

<details>

<summary>Show answer</summary>

The global home page is the main landing page.

It shows accessible screens, AI agents, quick links, favorites, and recent pages.

See [Layout & Navigation](/quick-start/layout-and-navigation).

</details>

### What is an app home page?

<details>

<summary>Show answer</summary>

Each app has its own landing page.

It usually includes modules, profile details, and app-specific FAQs. It acts as the local starting point once you enter an app.

See [Layout & Navigation](/quick-start/layout-and-navigation).

</details>

### How do users usually navigate in Rierino?

<details>

<summary>Show answer</summary>

Most users follow a simple flow:

1. Open the global home page.
2. Switch to the right app.
3. Open a screen.
4. Find a record in the lister.
5. Open or edit it in the editor.

See [Layout & Navigation](/quick-start/layout-and-navigation).

</details>

### What is the difference between a lister and an editor?

<details>

<summary>Show answer</summary>

The lister is for finding, filtering, sorting, and selecting records.

The editor is for viewing, creating, and updating a selected record.

Most screens use both together.

See [Layout & Navigation](/quick-start/layout-and-navigation).

</details>

### Which app should I use to build backend services?

<details>

<summary>Show answer</summary>

Use **Devops**.

That is where you define runners, sagas, gateway routing, security, and deployments.

See [Development](/quick-start/development-with-rierino).

</details>

### Which app should I use for reusable logic like queries and rules?

<details>

<summary>Show answer</summary>

Use **Configuration**.

That is where you define reusable queries, business rules, and dynamic handlers that can run at runtime without redeploying services.

See [Development](/quick-start/development-with-rierino).

</details>

### Which app should I use to build the admin UI?

<details>

<summary>Show answer</summary>

Use **Design**.

That is where you define apps, UIs, widgets, listers, and source mappings that connect the UI to backend APIs.

See [Development](/quick-start/development-with-rierino).

</details>

### Which app should I use for AI and ML features?

<details>

<summary>Show answer</summary>

Use **Data Science**.

That is where you manage ML models, GenAI models, MCP servers, visualizations, and related assets.

See [Development](/quick-start/development-with-rierino).

</details>

### What should I read first if I am brand new?

<details>

<summary>Show answer</summary>

Start with [Development](/quick-start/development-with-rierino).

Then review the training examples and the guided starting paths. That gives you the quickest mental model of how the platform fits together.

See [I would like to start with...](/quick-start/i-would-like-to-start-with...).

</details>

### I want a standard CRUD API. Where should I start?

<details>

<summary>Show answer</summary>

Start with the CRUD service path.

That is the fastest route when you need standard create, read, update, and delete behavior on a collection or table.

See [I would like to start with...](/quick-start/i-would-like-to-start-with...).

</details>

### I want a custom API endpoint. Where should I start?

<details>

<summary>Show answer</summary>

Start with an API endpoint built as a saga.

This is the right path when you need custom validation, transformation, branching, or aggregation logic.

See [I would like to start with...](/quick-start/i-would-like-to-start-with...).

</details>

### I want to integrate multiple systems. Where should I start?

<details>

<summary>Show answer</summary>

Start with the integration or orchestration path.

Use this when you need to call third-party APIs, combine internal services, or coordinate retries, batching, and transformations.

See [I would like to start with...](/quick-start/i-would-like-to-start-with...).

</details>

### I want to build an internal app. Where should I start?

<details>

<summary>Show answer</summary>

Start with the internal application path.

Use this when you need forms, lists, editors, and back-office workflows without building a custom front-end first.

See [I would like to start with...](/quick-start/i-would-like-to-start-with...).

</details>

### I want to build an AI agent. Where should I start?

<details>

<summary>Show answer</summary>

Start with the AI agent path.

Rierino agents usually combine a governed GenAI model with tool sagas or tool states, plus optional interfaces.

See [I would like to start with...](/quick-start/i-would-like-to-start-with...).

</details>

### What if I am not sure which path fits?

<details>

<summary>Show answer</summary>

Use this quick rule:

* Need standard data APIs fast → start with CRUD service
* Need custom business endpoints → start with API endpoint
* Need multi-system coordination → start with integration or orchestration
* Need an internal screen → start with internal application
* Need conversational automation → start with AI agent

If you want one guided path that touches most core concepts, start with the [In-depth Exercise](/examples/in-depth-exercise).

</details>

### What should I check first if something does not work?

<details>

<summary>Show answer</summary>

Start with the basics:

* Confirm the gateway is reachable
* Confirm the training microservices are deployed
* Confirm the main data store is accessible

Then review error codes, common checks, and release notes if needed.

See [Development](/quick-start/development-with-rierino).

</details>


# Training Examples

This section explains the training examples deployed with standard Rierino installations, which can be used as starter templates.

Training examples ship with a standard Core installation. Use them as starter templates. Use them to validate your setup end-to-end.

Most examples are intentionally small. They show one idea at a time. You can copy the pattern into real services.

{% hint style="info" %}
This section covers **Core** examples. Core is available to all users.

For Core vs Core+ feature comparison, see [Rierino Packages](/troubleshooting/rierino-packages).
{% endhint %}

### What’s included

You get three sets of assets. They map to the three main “build surfaces” in Rierino.

<table data-view="cards"><thead><tr><th>Title</th><th data-card-target data-type="content-ref">Target</th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>API Flow Examples</td><td><a href="/spaces/cnDk3J1AzTgg2NFrGPlh/pages/Ko3wiuL90M9Jp4HIHP5O">/spaces/cnDk3J1AzTgg2NFrGPlh/pages/Ko3wiuL90M9Jp4HIHP5O</a></td><td data-object-fit="contain"><a href="/files/j5vkpS9E67cpVqOsnz7C">/files/j5vkpS9E67cpVqOsnz7C</a></td></tr><tr><td>Microservice Examples</td><td><a href="/spaces/cnDk3J1AzTgg2NFrGPlh/pages/PKZAYsLL4AoFOMWHWhxy">/spaces/cnDk3J1AzTgg2NFrGPlh/pages/PKZAYsLL4AoFOMWHWhxy</a></td><td data-object-fit="contain"><a href="/files/2GE1TivzpAM6jSb2wXKb">/files/2GE1TivzpAM6jSb2wXKb</a></td></tr><tr><td>UI Example</td><td><a href="/spaces/cnDk3J1AzTgg2NFrGPlh/pages/GMZ1MKstQwayfkpJ3AQM">/spaces/cnDk3J1AzTgg2NFrGPlh/pages/GMZ1MKstQwayfkpJ3AQM</a></td><td data-object-fit="contain"><a href="/files/8uTfMTInlLo0XyfleZjL">/files/8uTfMTInlLo0XyfleZjL</a></td></tr></tbody></table>

### Recommended path (30–60 minutes)

Do these in order. Each step builds on the previous one.

1. Build a minimal API flow: [Exercise: Hello World API](/examples/training-examples/exercise-create-an-api-endpoint)
2. Expose a new CRUD collection: [Exercise: Test State](/examples/training-examples/exercise-create-a-crud-service)
3. Add a UI on top of that CRUD endpoint: [Exercise: Test UI](/examples/training-examples/exercise-create-a-ui-screen)

{% hint style="info" %}
If you already have a working environment, start with **Hello World API**. It is the fastest routing smoke test.
{% endhint %}

### Where to find the training assets

#### Devops → Sagas (API Flows)

Open the **Devops** app, then **Saga**.

Training sagas are grouped under the `training` domain. Start with:

* `/train_ping` (echo / smoke test)
* `/train_hello` (transform → response)
* `/train_get` and `/train_set` (read/write against state)

Full list and screenshots: [API Flow Examples](/examples/training-examples/api-flow-examples).

#### Devops → Runners + Deployments (Microservices)

Open the **Devops** app, then **Runner** and **Deployment**.

The training deployment typically includes:

* `train_rpc`: executes sagas as APIs
* `train_crud`: generic CRUD microservice
* `train_cdc`: listens to DB changes and triggers a saga

Details and videos: [Microservice Examples](/examples/training-examples/microservice-examples).

#### Design → UIs + Source + Apps (Admin UI)

Open the **Design** app.

The built-in training UI shows how to wire a lister + editor to a CRUD backend:

* **UI**: screen layout (tabs, widgets, lister columns)
* **Source**: API mapping (typically `train_crud/dummy`)
* **App**: menu packaging (a minimal `training` app)

Walkthrough: [UI Example](/examples/training-examples/ui-example).

### API endpoints cheat sheet

Use these patterns when testing from Postman or curl. Replace `YOUR_ADMIN_API_DOMAIN` with your gateway domain.

```
# Run a saga (RPC runner)
https://[YOUR_ADMIN_API_DOMAIN]/api/request/train_rpc/<SAGA_PATH>

# CRUD collection endpoint (CRUD runner)
https://[YOUR_ADMIN_API_DOMAIN]/api/request/train_crud/<ALIAS>
```

{% hint style="warning" %}
Sagas are case-sensitive. Runner configs may reload on a short interval (often \~10–30 seconds).
{% endhint %}

### Next step

Once these patterns feel familiar, build something end-to-end with the larger guided exercise:

* [In-depth Exercise](/examples/in-depth-exercise)


# API Flow Examples

This page lists example flows which can be viewed from Saga screen in Devops app, grouped under training domain

All API workflows can be accessed via DevOps → Saga in the admin UI. In that screen, you’ll find the flows listed below under the “training” group.

<figure><img src="/files/sU7NQmA0U8JGwipBcaKh" alt=""><figcaption><p>Training Sagas</p></figcaption></figure>

## Saga: /train\_ping

This is the smallest end-to-end flow in the training domain. It wires a `Start` step straight to a `Success` step. It then echoes the incoming request payload back in the response. Use it as a smoke test for routing, authentication, and payload shape.

<figure><img src="/files/M2vuZnio4Gd0sE7GR1AG" alt="" width="375"><figcaption><p>Ping Flow</p></figcaption></figure>

## Saga: /train\_hello

This flow adds a single transformation step to the basic ping pattern. It generates a deterministic output message, like `"Hello World"`, regardless of input. It is useful for learning how transform outputs become HTTP responses. It also helps confirm response mapping without touching any state.

<figure><img src="/files/XgR4ttLgLpEv8XFmRC9P" alt="" width="302"><figcaption><p>Hello Flow</p></figcaption></figure>

## Saga: /train\_redirect

This flow demonstrates redirecting one endpoint to another saga. It reuses `train_hello` without defining its own step graph. That pattern keeps multiple endpoints consistent, while avoiding duplicate logic. It is also handy for deprecations and versioned routes.

<figure><img src="/files/IylXetOtTayyIGM7Sekd" alt="" width="563"><figcaption><p>Redirect Mapping</p></figcaption></figure>

## Saga: /train\_condition

This flow shows how branching works in sagas. A condition is evaluated and step links route execution to `Success` or `Fail`. It is a good template for validation or eligibility checks. Use the pattern when you need explicit “happy path” and “rejection path” responses.

<figure><img src="/files/XNPQmgU8JCh1EdutWQ3V" alt="" width="375"><figcaption><p>Condition Flow</p></figcaption></figure>

## Saga: /train\_get

This flow demonstrates a read operation against a state manager. It calls a local read handler to fetch a `dummy` record by `id`. The response payload is built from the record returned by the handler. Use it to understand how saga inputs map to state reads.

<figure><img src="/files/x96OgeGcWMBsCTEuqXly" alt="" width="305"><figcaption><p>Get Flow</p></figcaption></figure>

## Saga: /train\_set

This flow demonstrates a write operation against a state manager. It calls a local write handler to create or update a record in the `dummy` state manager. The request payload becomes the write input, with IDs and fields mapped by parameters. Use it as a baseline for POST/PUT style endpoints.

<figure><img src="/files/8czQEacFaN4zUSqz3eIL" alt="" width="302"><figcaption><p>Set Flow</p></figcaption></figure>

## Saga: /train\_query

This flow demonstrates server-side filtering with a reusable query definition. It calls a local query handler and executes the `"Dummy Search"` query. The query filters records by fields such as `name` and returns a list. Use it to learn how query parameters travel from API input to the query engine.

<figure><img src="/files/zbrUIvlHgE9XuawkbmJ0" alt="" width="305"><figcaption><p>Query Flow</p></figcaption></figure>

The query is accessible from the Query screen of the Configuration application. This is where the stored query text and parameters live. Updating it changes this endpoint’s behavior without editing the saga.

<figure><img src="/files/g5AzpzCh6Jp2stCy165I" alt=""><figcaption><p>Dummy Search Query</p></figcaption></figure>

## Saga: /train\_rest

This flow demonstrates an outbound HTTP call from a saga. It uses the REST handler together with a configured `System` definition. The saga builds a request, sends a GET call to the remote system, then forwards the response. Use it for simple integrations and for validating network access from runners.

<figure><img src="/files/ffxsB8E0bGRYDZIUm2mD" alt="" width="375"><figcaption><p>Rest Flow</p></figcaption></figure>

This flow is also used in AI Agent example, and includes a simple input schema, which allows the AI agent to make calls to this flow in the correct data pattern. It also includes some optional instructions and mappings for the agent in AI tab.

## Saga: /train\_pattern

This flow builds on `train_rest` by parameterizing request and response mapping. It uses patterns in event metadata to inject values into the outbound request. It can also extract and reshape fields from the remote response into a clean API output. Use it when you need lightweight mapping without custom code.

<figure><img src="/files/Nyoe6v0C8mOHHkDT85Aa" alt=""><figcaption><p>Pattern Parameters</p></figcaption></figure>

## Saga: /train\_secret

This flow demonstrates basic crypto utilities in a saga. It encrypts an input value using a preconfigured key. It then decrypts the value back and returns it for verification. Use it to understand how secrets and encryption helpers fit into API flows.

<figure><img src="/files/ofL5MmpxEbiZ1wHKHRUp" alt="" width="366"><figcaption><p>Secret Flow</p></figcaption></figure>

## Saga: /train\_script

This flow executes a stored Groovy script from within the saga. The script reads parameters from the incoming payload. It then returns a computed payload, often echoing or reshaping inputs. Use it for fast prototyping when a transform step is not enough.

<figure><img src="/files/Td8bba92PXmCI61jUdXW" alt="" width="245"><figcaption><p>Script Flow</p></figcaption></figure>

The script itself is configured using the code editor accessible in Configuration application.

<figure><img src="/files/JIsH0QK42X0SudMvVNAI" alt=""><figcaption><p>Executed Groovy Script</p></figcaption></figure>

## Saga: /train\_template

This flow renders a text output using a stored Handlebars template. It passes inputs like `name` and `surname` into the template context. The rendered string is returned as the API response, which is useful for emails or HTML snippets. Use it to learn template parameter binding and output formatting.

<figure><img src="/files/YmmWZPdjUmCsGF517w5M" alt="" width="250"><figcaption><p>Template Flow</p></figcaption></figure>

The template itself is configured using the code editor accessible in Configuration application.

<figure><img src="/files/Fu5u6GVueF8f8hVxQF7i" alt=""><figcaption><p>Rendered Handlebars Template</p></figcaption></figure>

## Saga: /train\_hft

This flow demonstrates dynamic Java compilation and execution at runtime. It loads a Java class definition from stored configuration. It compiles the class and runs it as an event handler during the saga. Use it for advanced experiments, where you need real code without redeploying.

<figure><img src="/files/xC34pjV2KxK5B2U9k2jj" alt="" width="248"><figcaption><p>HFT Flow</p></figcaption></figure>

The class itself is configured using the code editor accessible in Configuration application.

<figure><img src="/files/5A4iiC7VYoUlnNVkY18T" alt=""><figcaption><p>Dynamic Java Class</p></figcaption></figure>

## Saga: /train\_rule

This flow evaluates a list of rules against the incoming payload. It returns the selected outcome value after rule matching. It is a good template for pricing, routing, or classification decisions. Use it to see how business rules can be changed without code changes.

<figure><img src="/files/yn0oTjKvhYxwZAQILhQ4" alt=""><figcaption><p>Simple Rule Flow</p></figcaption></figure>

The rule list for calculation is configured using the rule records accessible in Configuration application.

<figure><img src="/files/CVjoZeQqNRg2x35xkxZU" alt=""><figcaption><p>Rule Configuration</p></figcaption></figure>

## Saga: /train\_mock

This flow returns a fixed example response without calling any backend. It is intended for mocking endpoints during UI or integration development. You can keep contract tests moving while the real logic is not ready. Later you can swap the mock for real steps without changing the route.

<figure><img src="/files/peuRTJmMxdlCex7WE7VP" alt=""><figcaption><p>Mocking Configuration</p></figcaption></figure>

## Saga: /train\_for

This flow demonstrates looping over a list in the payload. It runs the same action for each item, such as rendering a template per entry. It typically produces an aggregated output list or concatenated result. Use it when you need per-item enrichment without writing code.

<figure><img src="/files/7GM5QzJEaRflQ3eZpvKE" alt=""><figcaption></figcaption></figure>

## Saga: /train\_parallel

This flow demonstrates fan-out execution. It triggers two independent branches at the same time. It then continues once both branches complete, typically combining their outputs. Use it to reduce latency when you call multiple systems.

<figure><img src="/files/1fVvRtwX01CYktCWPjkH" alt=""><figcaption></figcaption></figure>

## Saga: /train\_nested

This flow calls another saga from within a parent saga. It passes a payload into the nested saga and receives its output. This is the main reuse mechanism for shared business logic. Use it to keep complex flows modular and easier to test.

<figure><img src="/files/r3DXjo6l5XGeHiAolXtP" alt=""><figcaption></figcaption></figure>


# Exercise: Create an API Endpoint

This page lists an exercise for building a minimal saga on Train RPC that returns {message: "Hello World"}.

This exercise creates a tiny saga and exposes it as an API endpoint. You will run it through the **Train RPC** runner. The flow uses only three steps: `Start` → `Transform` → `Success`.

### Before you start

* You can access the **Devops** app and the **Saga** screen.
* The training deployment (including `train_rpc`) is installed and running.
* You know your API base URL: `https://[YOUR_ADMIN_API_DOMAIN]`.

### What you’ll build

* **Saga path**: `/HelloWorld`
* **Runner**: `train_rpc` (via **Allowed For: Train RPC**)
* **Response**: HTTP `200` with body `{message: "Hello World"}`

{% stepper %}
{% step %}

### Open the Saga screen

Open the [Saga](/devops/api-event-and-process-flows) screen from the [Devops](/devops/devops-overview) app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/devops/common/saga`.

<figure><img src="/files/sg7EtfeoIcIOaGkui34y" alt=""><figcaption><p>Saga Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create a new saga

Click **CREATE NEW** in the left menu area. This clears the editor and opens a blank saga.

You’ll define the saga metadata first. Then you’ll design the step graph.

<figure><img src="/files/Tj5rJXzLbYQxfxFKhcpw" alt=""><figcaption><p>Create New Button</p></figcaption></figure>
{% endstep %}

{% step %}

### Assign an ID

Click the pencil next to **ID:** and set a unique identifier.

For this exercise, use: `hello_world-0001`.

<figure><img src="/files/yFRTKzFPPZ9NR7AIsDCm" alt=""><figcaption><p>Saga ID Assignment</p></figcaption></figure>

<details>

<summary>ID conventions (optional)</summary>

IDs can be auto-generated if an ID generator is configured. For core assets like sagas and queries, human-readable IDs make debugging and audits much easier.

{% hint style="info" %}
If you assign IDs manually, prefer alphanumerics plus `-` and `_`. For high-volume assets, consider a 4‑digit partition suffix (like `-0001`). For low-volume assets, you can skip partitioning.
{% endhint %}

</details>
{% endstep %}

{% step %}

### Define the saga (name, path, allowed runner)

Click the **Definition** icon (circled edit icon) to open saga metadata.

<figure><img src="/files/mLS20vKYIgeNTuxlPIfS" alt=""><figcaption><p>Definition Button</p></figcaption></figure>

Fill in these fields:

<figure><img src="/files/tAvugs5AUAkZ0i7akQYz" alt=""><figcaption><p>Hello World Saga</p></figcaption></figure>

* **Saga Name:** `Hello World`
* **Saga Domain (optional):** `util`
* **Status:** `ACTIVE`
* **Saga Description (optional):** `Returns "Hello World"`
* **Saga Path:** `/HelloWorld`
* **Version:** `0`
* **Allowed For:** `Train RPC`
* **Auto Fail:** `true`

This means requests to `/HelloWorld` routed through `train_rpc` will execute this saga.

{% hint style="info" %}
**Allowed For** limits which runner can execute the saga. Leaving it empty allows any runner to execute it.
{% endhint %}
{% endstep %}

{% step %}

### Add steps (Start → Transform → Success)

Drag a **Start** step from the stencil.

<figure><img src="/files/M9wQdQ1NkHESh8PudyIj" alt=""><figcaption><p>Saga Stencil</p></figcaption></figure>

Drag a **Transform** step and a **Success** step.

Your canvas should look like this:

<figure><img src="/files/2QwSjLLbgXCsbUCouyMG" alt=""><figcaption><p>Saga Steps</p></figcaption></figure>

Connect `Start` → `Transform`.

<figure><img src="/files/ukn5JYZkNswYAyqvuTfv" alt=""><figcaption><p>Saga Link</p></figcaption></figure>

Connect `Transform` → `Success`.

Your graph should look like this:

<figure><img src="/files/rGWeioB5p02t6YySdpYB" alt=""><figcaption><p>Saga Links</p></figcaption></figure>
{% endstep %}

{% step %}

### Configure the Transform step

The flow runs now, but it does not yet return `"Hello World"`. You’ll add a static value to the payload.

Select the [Transform](/devops/api-event-and-process-flows/configuring-saga-steps/transform-step) step. Click its pencil icon to edit.

<figure><img src="/files/pezagvvyH9w8yjYHK08c" alt=""><figcaption><p>Transform Step Icons</p></figcaption></figure>

Set these values:

<figure><img src="/files/WFRctQBhuPh0tKexxbs1" alt=""><figcaption><p>Transform Definition Screen</p></figcaption></figure>

* **Step Name:** `Say Hello World`
* **Step Description (optional):** `This step adds a static "Hello World" message.`
* **Transform Class:** `Add Value to Payload`
* **Transform Parameters:**
  * **Key:** `value`
  * **Value:** `{message: "Hello World"}`

Click **Apply** to save the step configuration.

{% hint style="info" %}
**Why does Transform have a “Class”?**

Instead of adding a separate stencil shape for every transformation type, the step stays the same. You switch behavior by selecting a different **Class** (or **Action**) in the step config.

This makes it safer to evolve flows over time. You can change behavior without rebuilding the graph and breaking tracing continuity.
{% endhint %}

The step label should update on the canvas:

<figure><img src="/files/jCiuQoPwkZdTOO96dA41" alt=""><figcaption><p>Defined Transform Step</p></figcaption></figure>
{% endstep %}

{% step %}

### Save the saga

Click **SAVE** in the top-right corner.

<figure><img src="/files/mLL9EO8uluG9Ysyxc6sH" alt=""><figcaption><p>Save Button</p></figcaption></figure>

Wait for the runner to pick up changes. In most training setups this is quick. If your environment has a reload interval, give it \~10–30 seconds.

You should see a confirmation notification.
{% endstep %}

{% step %}

### Test the endpoint

Call the API endpoint from your REST client:

`https://[YOUR_ADMIN_API_DOMAIN]/api/request/train_rpc/HelloWorld`

Expected result:

* HTTP `200 OK`
* Body: `{message: "Hello World"}`

{% hint style="info" %}
Remember the saga path is case-sensitive. Use `/HelloWorld` exactly as configured.
{% endhint %}
{% endstep %}
{% endstepper %}

### Troubleshooting

* **404 Not Found**: confirm **Saga Path** and that you saved the saga. Also confirm it’s allowed for **Train RPC**.
* **403/401**: gateway auth is blocking the request. Check your token/session.
* **Saga does not trigger**: confirm the request is routed through `train_rpc` (URL contains `/train_rpc/`).


# Microservice Examples

This page lists example microservice runners which can be viewed from Runner and Deployment screens in Devops app

## Runners

### Train CRUD

Train CRUD is a basic HTTP CRUD microservice. It exposes standard `GET`, `POST`, `PUT`, `PATCH`, and `DELETE` operations on a single MongoDB collection named `dummy` in the `master` database. It is the fastest way to see “data in / data out” behavior across gateway → runner → state manager.

It supports the generic CRUD operation set and parameters described in [CRUD event runner](/devops/microservices/service-runners/deploying-runners/spring-runners#crud-event-runner). Use that reference when you want to understand supported query params, request bodies, and how partial updates work.

This runner is mapped to the `CRUD Train` gateway system and the `Train CRUD` gateway channel. You can reach it at `[{API_SERVER}]/api/request/train_crud/[PATH]`.

<figure><img src="/files/B50nRMvz0fmSPtz3Rimu" alt=""><figcaption><p>CRUD Runner</p></figcaption></figure>

A typical CRUD runner has three core handlers:

* **Read**: resolves `GET` operations.
* **Write**: handles create/update/delete operations.
* **Condition**: enables simple branching and checks during CRUD calls.

You can tighten access by limiting which states are readable or writable. You can also route certain operations through sagas when you need custom logic. This is the usual upgrade path from “generic CRUD” to “domain-aware API”.

{% hint style="info" %}
To create a new fully functional CRUD endpoint, all you need to do is add a `STATE` element named "Generic Master w/ ID", give it an alias and click on save for this runner. Within 30 seconds (rebuild window), your endpoints will be available on /train\_crud/\[alias].
{% endhint %}

To learn how to extend this CRUD runner, please watch the following video:

{% embed url="<https://www.youtube.com/watch?v=iW_klLfvJuk>" %}

### Train RPC

Train RPC is a general-purpose RPC runner that executes sagas. It also ships with a broad set of handlers for “do some work and return a response”, most of them inherited through its base runner configuration. Most training sagas are executed through this runner, including the ones listed under [API Flow Examples](/examples/training-examples/api-flow-examples).

This runner is mapped to the `RPC Train` gateway system and the `Train RPC` gateway channel. You can reach it at `[{API_SERVER}]/api/request/train_rpc/[PATH]`.

<figure><img src="/files/2GYmmRQAUtOPHGC9oEbq" alt=""><figcaption><p>RPC Runner</p></figcaption></figure>

This RPC runner inherits two base runners to provide it with the foundations:

* **Base RPC:** Provides most frequently used handlers and their supporting state managers, for read, write, query, saga, action and simple rule operations.
* **GenAI Base:** Provides configuration for AI agent use cases, including required handler and state managers.

Individual elements are added on top of this inheritance to showcase different use cases:

* **Script / Handlebars template / OpenHFT handlers** for dynamic logic. Code is stored in `handler_code` on the `devops` database. It is cached in-memory for fast reloads.
* **Secret handler** to encrypt, decrypt and hash different types of payloads.
* Sample **query and state managers** for testing read/write operations on `mongo_master` database.

To learn how to extend this RPC runner, please watch the following video:

{% embed url="<https://www.youtube.com/watch?v=qIJNBnN6v8U>" %}

### Train CDC

Train CDC is a change-data-capture runner. It listens to changes on the `dummy` collection in the `master` MongoDB database. On each change, it triggers the `/On_dummy` saga to process the event.

This runner is not called through the API gateway. Its “requests” are CDC records emitted by the underlying database stream.

<figure><img src="/files/RY5IaWkbruurdODVtlAC" alt=""><figcaption><p>CDC Runner</p></figcaption></figure>

A CDC runner usually includes:

* One or more **CDC streams** (here, the `dummy` collection change stream).
* An **offset/checkpoint mechanism** so it can resume after restarts.

Spring-based runners often store offsets in a state manager. Samza-based runners typically rely on their own checkpointing model. After you have CDC events, you can route them in multiple ways. You can trigger sagas (like this example). You can also enrich the change record and publish it downstream, like to a Kafka topic.

To learn how to extend this CDC runner, please watch the following video:

{% embed url="<https://www.youtube.com/watch?v=MCvRGhUhijg>" %}

## Deployments

### Training Core

Training Core is the deployment that bundles the training runners together. It is configured for the `admin-backend` namespace. This deployment is meant for learning, demos, and local validation. It gives you a complete working baseline without building your own runners first.

<figure><img src="/files/Pql5JdJ6iMoez8bsRlVL" alt=""><figcaption><p>Deployment Runner List</p></figcaption></figure>

{% hint style="info" %}
Training Core is typically installed automatically with the Core platform. You usually do not need to deploy it manually.
{% endhint %}


# Exercise: Create a CRUD Service

This page lists an exercise for adding a new MongoDB-backed state to Train CRUD and exposing it as a /test endpoint.

This exercise extends the existing **Train CRUD** runner with a new state. The result is a new CRUD endpoint under the runner. The endpoint reads and writes to a MongoDB collection automatically.

### Before you start

* You can access the **Devops** app.
* The training deployment is installed and `train_crud` is running.
* You know your API base URL: `https://[YOUR_ADMIN_API_DOMAIN]`.

### What you’ll build

* A new state with alias `test`.
* A new endpoint: `https://[YOUR_ADMIN_API_DOMAIN]/api/request/train_crud/test`

{% stepper %}
{% step %}

### Open the Runner screen

Open the [Runner](/devops/microservices/service-runners) screen from the [Devops](/devops/devops-overview) app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/devops/common/runner`.

<figure><img src="/files/LyPSe4s6GNT2ybVD2ek9" alt=""><figcaption><p>Runner UI</p></figcaption></figure>
{% endstep %}

{% step %}

### Select Train CRUD

In the left runner list, filter and select **Train CRUD**.

<figure><img src="/files/RRpyDJ1tc6KcVujZZ3OF" alt=""><figcaption><p>Train CRUD Runner</p></figcaption></figure>
{% endstep %}

{% step %}

### Add a new State element

Drag a **State** element (table icon) from the stencil onto the runner diagram.

Select the new element. Click the pencil icon to edit it.

<figure><img src="/files/oA4L3r6xEDaO5iORsKty" alt=""><figcaption><p>New State Manager</p></figcaption></figure>
{% endstep %}

{% step %}

### Configure it as Generic Master + alias `test`

In the editor:

* Choose **Generic Master**.
* Set **alias** to `test`.

`Generic Master` creates a simple MongoDB-backed state manager on the `master` database. The **alias** becomes:

* the CRUD URL segment (`/test`)
* the MongoDB collection name (`test`)

This is the simplest “new CRUD resource” configuration. For advanced options, use the Devops docs referenced from the CRUD runner section.
{% endstep %}

{% step %}

### Wait for rebuild and test the endpoint

The training Train CRUD runner is typically configured to rebuild every \~30 seconds. After you save, give it a moment to apply the new state.

Then call:

`https://[YOUR_ADMIN_API_DOMAIN]/api/request/train_crud/test`

Expected result:

* HTTP `200 OK`
* Body: `{list: []}` (the collection starts empty)

Full list of supported CRUD operations and parameters is in [CRUD event runner](/devops/microservices/service-runners/deploying-runners/spring-runners#crud-event-runner).
{% endstep %}
{% endstepper %}

### Troubleshooting

* **404 Not Found**: confirm the alias is `test` and that you saved the runner. Then wait for the rebuild interval.
* **500 errors**: `Generic Master` points to a MongoDB connection. Check the master DB is reachable.
* **Endpoint exists but returns nothing**: verify you are hitting `train_crud` (URL contains `/train_crud/`).


# UI Example

This page lists example UIs which can be viewed from UI and Source screens in Design app

This training UI is a small admin screen on top of the `dummy` data model. The data is served by the `train_crud` runner. It is a quick way to see how a UI, a source mapping, and a backend endpoint fit together.

You can browse the configuration in the Design app:

* **UIs**: the screen layout, lister, editors, and widgets.
* **Source**: the API endpoint mapping used by the UI.
* **Apps**: a minimal `training` app that exposes only this screen in its menu.

If you are new to UI building, skim [Apps](/design/user-interface/apps), [UIs](/design/user-interface/uis), and [API Mapping](/design/api-mapping) first.

### Record editor (tabs + widget types)

The record editor uses tabs to group fields. It combines a few common widget types. You can compare how each widget reads and writes values.

This example includes:

* a text editor for simple string fields
* a select editor backed by option values
* a Markdown editor for rich text
* a JSON editor for the full record payload

<figure><img src="/files/NbZuPtBtESSfH3reSR2Z" alt=""><figcaption><p>Tabs Example</p></figcaption></figure>

### Lister (columns + filters)

The list view uses a table lister. The visible columns are configured in the UI definition. The same goes for which filter inputs are available to users.

This is the part to copy when you want a “browse + search + click to edit” admin experience. See [Listers](/design/user-interface/uis/listers) for the available types and options.

<figure><img src="/files/cPqMx3r5LqNqOWsYGbVd" alt=""><figcaption><p>Lister Example</p></figcaption></figure>

### Source mapping (CRUD via `train_crud/dummy`)

On the Source screen, the `train_crud/dummy` endpoint is set as the UI’s data source. This enables standard CRUD behavior without writing custom API calls per action. The UI can list records, open a record, create, update, and delete using the default method mappings.

<figure><img src="/files/dammpweUtuKjzzYptJac" alt=""><figcaption><p>Source Example</p></figcaption></figure>

### App packaging (`training`)

A small `training` app is included as a container for the menu and navigation. It exposes only the `dummy` UI. This is the simplest pattern for shipping a focused admin experience to a specific user group.

<figure><img src="/files/f6DeAKv8vCszTJzNqWBA" alt=""><figcaption><p>Training App Design</p></figcaption></figure>

### Run it

Navigate to `[{UI_SERVER}]/app/train` to open the app. You should see the lister first. From there you can filter, open a record, edit fields, and save changes.

<figure><img src="/files/11n1T69YKET7jPE642iT" alt=""><figcaption><p>Training App</p></figcaption></figure>

{% hint style="info" %}
If the screen is empty or CRUD operations fail, verify the `train_crud` runner and gateway route are reachable first. The UI is only a client. It depends on the backend endpoint.
{% endhint %}


# Exercise: Create a UI Screen

This page lists an exercise for creating a minimal UI and source mapping for the /test CRUD endpoint.

This exercise creates a tiny admin UI for the `test` collection. It assumes you already created the backend CRUD endpoint in [Exercise: Test State](/examples/training-examples/exercise-create-a-crud-service).

### Before you start

* You can access the **Design** app.
* The `/test` CRUD endpoint exists under `train_crud`.
* You can reach the UI at `https://[YOUR_ADMIN_UI_DOMAIN]`.

### What you’ll build

* A new UI with ID `test`.
* A lister that shows test records.
* An editor with a single `name` field.
* A source mapping that points the UI to the `train_crud/test` endpoint.
* A menu entry under the `Training` app.

{% stepper %}
{% step %}

### Create a new UI

Open the [UI](/design/user-interface/uis) screen from the [Design](/design/design-overview) app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/design/common/ui`.

Click **Create New**.

<figure><img src="/files/4DbmvgrmO5BfX2fY3th5" alt=""><figcaption><p>UI Editor</p></figcaption></figure>
{% endstep %}

{% step %}

### Configure UI basics

Set the UI **ID** to `test`. This becomes the UI path segment.

Fill in name and status. Set the ID and name field mappings as shown.

Enable **Customizable ID**. This allows creating new records with custom IDs.

<figure><img src="/files/5V2jjgSJBRjZMYgO2Nmc" alt=""><figcaption><p>Test UI Configuration</p></figcaption></figure>
{% endstep %}

{% step %}

### Configure the lister

Open the **Lister** tab.

Select the **Menu** lister. Set a title.

This lister type is simple. It works well for small datasets.

<figure><img src="/files/kOF30ROVNQ3zeRUnpQFn" alt=""><figcaption><p>Test Lister Configuration</p></figcaption></figure>
{% endstep %}

{% step %}

### Add the editor

Open the **Tabs** tab.

Add a tab named `Definition`. Add a grid inside it.

<figure><img src="/files/v6z04kDoVVM1SiuCYbHC" alt=""><figcaption><p>Test Tab &#x26; Grid</p></figcaption></figure>

Click **Add** and create the `name` editor shown below.

<figure><img src="/files/bgKisWpa9ITqCDWinMhP" alt=""><figcaption><p>Name Editor</p></figcaption></figure>

Click **Apply**. Then click **Save**.

<figure><img src="/files/HZKDcZsWrVxq7qpm7RlN" alt=""><figcaption><p>Created Test UI</p></figcaption></figure>
{% endstep %}

{% step %}

### Create a source mapping

Open the **Source** screen from the [Design](/design/design-overview) app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/design/common/source`.

Click **Create New**.

<figure><img src="/files/0CM7j4qAoLnezfmJxexD" alt=""><figcaption><p>Test Source</p></figcaption></figure>

Configure the source to target the `train_crud/test` endpoint. This is what connects your UI actions to CRUD calls.

{% hint style="info" %}
Fastest path is duplicating the existing `dummy` source. Then change any `dummy` path segments to `test`. Save as a new source.
{% endhint %}
{% endstep %}

{% step %}

### Add it to the Training app menu

Open the [App](/design/user-interface/apps) screen from the [Design](/design/design-overview) app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/design/common/app`.

Select the existing **Training** app. Add a menu entry for the new `test` UI.

<figure><img src="/files/nfxTo3nE67A14JjEOVSg" alt=""><figcaption><p>Test Menu</p></figcaption></figure>
{% endstep %}

{% step %}

### Run it

Go to `[{UI_SERVER}]/app/train`.

Open the **Test** menu entry. Create a record. Save it.

You should see it appear in the lister afterwards.
{% endstep %}
{% endstepper %}

### Troubleshooting

* **Menu entry not visible**: confirm you edited the `Training` app. Save it.
* **Lister is empty after creating records**: confirm source points to `train_crud/test`.
* **Save fails**: confirm the backend `/test` endpoint exists. Retry after rebuild.


# AI Agent Example

This page lists example AI agent configurations, which can be viewed from GenAI Model screen in Data Science app

This training agent is a “chat + tools” example. It searches books by calling the `/train_rest` saga. It can also render results as a rich HTML card UI.

It is configured in the **Data Science → GenAI Models** screen. It depends on the training assets from the other examples.

### Before you start

* The training runners are installed and running.
* The `/train_rest` saga exists and is `ACTIVE`. See [API Flow Examples](/examples/training-examples/api-flow-examples).
* A runner is allowed to serve GenAI models (`train_rpc`). See [Microservice Examples](/examples/training-examples/microservice-examples).
* You have an LLM provider key stored as a secret.

{% hint style="info" %}
For OpenAI, store `rierino.system.openai.apikey` key as a secret. In local setups this is typically `globalsecrets.properties`. In Kubernetes this is typically the `global-secrets` Secret.
{% endhint %}

### What you’ll build

* A GenAI agent with sample system instructions and a book-search goal.
* A **tool saga** entry that lets the agent call `/train_rest`.
* An optional **tool state** entry (the training `dummy` model) for safe additional data access.
* An optional **interface** so the agent can respond with UI cards.

### End-to-end flow (what happens at runtime)

1. The user asks for books (author/title/keywords).
2. The LLM decides to call the `/train_rest` tool saga.
3. `/train_rest` calls Open Library via an outbound REST step.
4. The agent formats results.
5. It returns an HTML-based result card.

### Configure the model (walkthrough)

{% stepper %}
{% step %}

### 1) Define the agent (purpose + allowed runner)

Fill the model definition. Keep the instructions concrete. Limit **Allowed For** to the runner you want serving the agent, unless it should be running within all microservices.

<figure><img src="/files/FfgaF0K7OPqlSWFS1vZP" alt=""><figcaption><p>Training Agent Example</p></figcaption></figure>
{% endstep %}

{% step %}

### 2) Select the LLM provider + API key secret

Pick **OpenAI** (or your provider). Reference the API key through a secret entry.

<figure><img src="/files/fSiFEfHD7PWR4fY6uhHS" alt=""><figcaption><p>Training Agent LLM Model</p></figcaption></figure>
{% endstep %}

{% step %}

### 3) Add tools (make it actionable)

Add the `/train_rest` saga as a **Tool Saga**. This is what turns a chat-only agent into an agent that can act.

Add `dummy` as a **Tool State**. Keep it read-only unless you need writes.

<figure><img src="/files/c80vByWLzvviRYzrWupc" alt=""><figcaption><p>Training Agent Tools</p></figcaption></figure>

{% hint style="info" %}
Tool sagas work with an input schema. Schema nudges the LLM into correct parameter shapes.
{% endhint %}
{% endstep %}

{% step %}

### 4) Enable interfaces (optional, but recommended)

Enable interface responses. Add the book listing UI.

This example uses `HandlebarsDisplay`. That widget renders HTML from a template.

<figure><img src="/files/dld3xlSEY6ELoHtPDkHe" alt=""><figcaption><p>Training Agent UIs</p></figcaption></figure>

{% embed url="<https://www.youtube.com/watch?v=jMARJDxzk24>" %}
{% endstep %}

{% step %}

### 5) Add the Handlebars template

Add a Handlebars template for the interface. The training template was generated by the 'Template Assistant' agent.

<figure><img src="/files/JhbKRpNddWddIl4LV3xW" alt=""><figcaption><p>Agent Dynamic UI Template</p></figcaption></figure>
{% endstep %}
{% endstepper %}

### Run it

After you **Save**, the agent appears in the agent list.

<figure><img src="/files/lu3JCToqkkOMdNR2JMXG" alt=""><figcaption><p>AI Agent Listing</p></figcaption></figure>

Open the agent and try a prompt like:

* `Find books by "Isaac Asimov".`&#x20;
* `Show me the books with "The Hobbit" in title.`

You should see tool-backed results. With interfaces enabled, you’ll get a rich HTML response.

<figure><img src="/files/hEClK2Qy2H70CcuOjy88" alt=""><figcaption><p>AI Agent Interaction</p></figcaption></figure>

### Call it via API (optional)

Agents are also available as backend APIs. Use these endpoints from the runner channel that serves the agent:

* [AI Agent APIs](/data-science/genai-models/ai-agent-apis)

Use the **Call Path** from the agent’s Definition tab. That value is the stable identifier for calling the agent remotely.

### Troubleshooting

* **Model can’t be called**: the agent is not in **Allowed For** for your runner.
* **LLM auth error**: secret is missing or not resolved on the runner.
* **Agent never uses tools**: `/train_rest` is not listed in **Tool Sagas**.
* **Tool call fails**: verify `/train_rest` works directly first. Start from [API Flow Examples](/examples/training-examples/api-flow-examples).
* **UI response is plain text**: interfaces are disabled or no interface is assigned.
* **Broken HTML**: Handlebars template has invalid syntax. Simplify and retry.

### Next steps

* Deep dive into model tabs and governance in [GenAI Models](/data-science/genai-models).
* Extend the tool saga patterns in [API Flow Examples](/examples/training-examples/api-flow-examples).
* Build more admin screens like the training UI in [UI Example](/examples/training-examples/ui-example).


# In-depth Exercise

Build a complete to-do list feature end-to-end on Rierino, covering a CRUD microservice, MongoDB-backed storage, gateway exposure, an admin UI, and a simple search flow using queries and sagas.

This exercise walks through building a small, realistic app. It starts with the backend. It ends with a working admin screen.

You will create a `todo` data model, expose it over an API, and build a UI. You will also add a basic query endpoint for search.

{% hint style="info" %}
This exercise assumes you already understand the core Rierino concepts (Elements, Runners, Deployments, Sources, Schemas, UIs, and Sagas).

If you are new to the platform, start with the simpler [Training Examples](/examples/training-examples) first. They build the same mental model with smaller steps.
{% endhint %}

### Exercise sections

* [**To-do List Runner**](/examples/in-depth-exercise/to-do-list-runner)
  * Build a CRUD runner backed by a MongoDB collection named `todo`.
  * Define the required Elements (System + State) and attach them to the runner.
  * Deploy the runner and verify basic reads and writes with `curl`.
* [**To-do List Gateway**](/examples/in-depth-exercise/to-do-list-gateway)
  * Create a gateway channel that forwards external requests to your runner service.
  * Map a clean public path (for example `/api/todo`) to the runner’s internal base URL.
  * Test the gateway path and confirm you can list the records you created earlier.
* [**To-do List UI**](/examples/in-depth-exercise/to-do-list-ui)
  * Create a dedicated Admin app entry and menu route for the to-do feature.
  * Define a Source so the UI knows where to send list and edit requests.
  * Define a JSON Schema and a UI layout so users can create and edit items.
* [**To-do List Query**](/examples/in-depth-exercise/to-do-list-query)
  * Add search by creating a MongoDB Query (filtering by a field like `data.project`).
  * Expose that query through a Saga endpoint, so it is callable like an API.
  * Update the Source and UI lister to use the query endpoint and show filtered results.


# To-do List Runner

Create and deploy a CRUD runner backed by MongoDB. This runner will store to-do items in a \`todo\` collection and expose standard read/write endpoints for the rest of the exercise.

This exercise creates the backend microservice for the to-do list. You will define the MongoDB-backed state, wire it into a CRUD runner, deploy it, and confirm it responds to basic read/write calls.

### Before you start

* You can access the [Devops](/devops/devops-overview) app.
* The platform has a MongoDB system Element available (typically `system-mongo_master-0001`).
* You know your Admin UI base URL: `https://[YOUR_ADMIN_UI_DOMAIN]`.

{% hint style="warning" %}
If you are on a **Sandbox** deployment, UI-based deployments may be disabled. You can still complete the design steps. For runtime, you may need to add the runner to an existing deployment and restart the container(s).
{% endhint %}

### What you’ll build

* **State Element**: `state-todo-0001` backed by MongoDB collection `todo`
* **Runner**: `todo-0001` based on **Base CRUD**
* **Deployment (K8s example)**: `example-0001`
* **Runner endpoints (internal)**: `/api/todo/todo`

{% stepper %}
{% step %}

### Open the Elements screen

Open the [Elements](/devops/microservices/building-blocks) screen from the Devops app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/devops/common/element`.

<figure><img src="/files/23MCEuI7BqIV7yOj9TOQ" alt=""><figcaption><p>Element Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create a State Element (MongoDB collection)

Click **CREATE NEW** to start a blank Element.

<figure><img src="/files/Tj5rJXzLbYQxfxFKhcpw" alt=""><figcaption><p>Create New Button</p></figcaption></figure>

Assign the Element ID from the top-left **ID:** field:

* `state-todo-0001`

<details>

<summary>ID conventions (optional)</summary>

Prefer readable IDs for exercises and examples. It makes logs, tracing, and migrations easier to follow.

{% hint style="info" %}
Stick to alphanumerics plus `-` and `_`. Use a numeric suffix (like `-0001`) when you expect multiple copies.
{% endhint %}

</details>

Fill in the **DEFINITION** and **STATE DEFINITION** tabs and save:

<figure><img src="/files/IcRIlIiNgSBKapLpc8VT" alt=""><figcaption><p>State Definition Tab</p></figcaption></figure>

* **DEFINITION**
  * **Element Name:** `Todo`
  * **Element Type:** `STATE`
  * **Element Status:** `ACTIVE`
  * **Element Description (optional):** `Example todo list data store`
* **STATE DEFINITION**
  * **Manager:** `Mongo State Manager`
  * **System:** `mongo_master`
  * **Collection:** `todo`

This creates a state backed by [MongoDB Collection](/devops/microservices/building-blocks/data-sources/shared-states/mongodb-collection). It reuses the existing `mongo_master` system configuration.

{% hint style="info" %}
**Why define a State as an Element?**

Elements are reusable building blocks. They keep runners small and composable.

When you centralize state and system config as Elements, you avoid duplicating connection details across many runners.
{% endhint %}
{% endstep %}

{% step %}

### Open the Runner screen

Open the [Runners](/devops/microservices/service-runners) screen from the Devops app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/devops/common/runner`.

<figure><img src="/files/S4aBwlY41kz8QmdiUw33" alt=""><figcaption><p>Runner Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create a CRUD runner

Click **CREATE NEW** and set the Runner ID:

* `todo-0001`

Click the **Definition** icon (circled edit icon) to open runner metadata.

<figure><img src="/files/mLS20vKYIgeNTuxlPIfS" alt=""><figcaption><p>Definition Button</p></figcaption></figure>

Fill in:

<figure><img src="/files/XNurktREjCzJwY5FBoDn" alt=""><figcaption><p>Runner Definition Screen</p></figcaption></figure>

* **Runner Name:** `Todo`
* **Runner Status:** `ACTIVE`
* **Runner Domain (optional):** `admin`
* **Base Runners:** `Base CRUD`
* **Runner Description (optional):** `CRUD runner for todo list management.`

Close the dialog to apply changes.

{% hint style="info" %}
Using **Base CRUD** gives you standard read/write behavior. You only need to plug in a State.
{% endhint %}
{% endstep %}

{% step %}

### Add Elements to the runner graph (System + State)

Drag a **System** element and a **State** element from the stencil.

<figure><img src="/files/wGOgfEMaiSN925JOmHMI" alt=""><figcaption><p>Runner Stencil</p></figcaption></figure>

Your graph should look like this:

<figure><img src="/files/PYeRBS0PngtyyvfOiwzB" alt=""><figcaption><p>Runner Elements</p></figcaption></figure>
{% endstep %}

{% step %}

### Configure the System member (mongo\_master)

Select the **System** node. Click the pencil icon.

<figure><img src="/files/S6a6fgPsoTd6fFMkbi5F" alt=""><figcaption><p>System Selection Screen</p></figcaption></figure>

Set:

* **Element:** `system-mongo_master-0001`
* **Member Type:** `OPERATION`
* **Alias:** `mongo_master`
* **Description (optional):** `MongoDB system for master collections`

Click **APPLY**.

{% hint style="info" %}
**Why use aliases?**

Aliases let you swap the underlying Element later without rewriting every reference. They also let you reuse the same Element multiple times with different overrides.
{% endhint %}

Optional: open the **ELEMENT** tab to review the system parameters.

<figure><img src="/files/hGH0w0Vt0BTS0PuTygdJ" alt=""><figcaption><p>System Element Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Configure the State member (todo)

Select the **State** node. Click the pencil icon.

<figure><img src="/files/CVmxMzLQFoDk5JuCyrhh" alt=""><figcaption><p>State Selection Screen</p></figcaption></figure>

Set:

* **Element:** `state-todo-0001`
* **Member Type:** `OPERATION`
* **Alias:** `todo`
* **Description (optional):** `State for todo list records`

Click **APPLY**.

At this point, the runner has everything it needs to execute CRUD operations. Save the runner.
{% endstep %}

{% step %}

### Create a Deployment (K8s environments)

Open the [Deployments](/devops/microservices/deployment-packages) screen from the Devops app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/devops/common/deployment`.

Click **CREATE NEW** and set the Deployment ID:

* `example-0001`

Fill in **DEFINITION**:

<figure><img src="/files/dcfb8AVr7dsJCsp8uVaO" alt=""><figcaption><p>Deployment Definition Screen</p></figcaption></figure>

* **Name:** `Example Runners`
* **Status:** `ACTIVE`
* **Description (optional):** `Deployment package for execution of example runners`
* **Runners**
  * **Name:** `todo`
  * **Class:** `CRUD Runner`
  * **Element:** `todo-0001`
  * **Deployment Version:** `1`

{% hint style="info" %}
**Why deploy separately from the runner definition?**

Runners define behavior. Deployments define where and how it runs (namespace, replicas, versioning).
{% endhint %}

Switch to **PARAMETERS** and set (adjust to your environment):

<figure><img src="/files/tcvBpxrGqwuDkLUFqH4d" alt=""><figcaption><p>Deployment Parameters Screen</p></figcaption></figure>

* **rierinoVersion:** `ENTER YOUR VERSION`
* **template:** `spring`
* **namespace:** `admin-backend`
* **pool:** `admin-node-pool`

Click **SAVE**.

{% hint style="info" %}
For scale, set `replicaCount` to `2+`. For deeper logs, set `logLevel` to `DEBUG`.
{% endhint %}
{% endstep %}

{% step %}

### Trigger the deployment

From the top-right deployment menu, click **DEPLOY**.

<figure><img src="/files/w6T73U8JD15owHh8PFt7" alt=""><figcaption><p>Deployment Action Menu</p></figcaption></figure>

Wait for your pipeline to finish. You should also see a UI notification that the request was sent.
{% endstep %}

{% step %}

### Test the runner (without gateway)

In most K8s setups, runners are not publicly exposed. They are reachable from inside the cluster or through [Gateway Servers](/devops/api-gateway-and-security/gateway-servers).

If you want to test immediately, exec into the runner pod:

```shell
kubectl exec -ti --namespace=admin-backend deployment/runner-example-0001-deployment -- /bin/bash
```

Then call the local endpoints:

```shell
# should return status:"UP"
curl localhost:1235/actuator/health

# should return the newly created record
curl -X POST -H "Content-Type: application/json" \
  -d '{"data": {"name": "Take out trash", "project": "Personal"}}' \
  localhost:1235/api/todo/todo/1

# should return a list including the new record
curl localhost:1235/api/todo/todo
```

Once these work, you are ready to expose the service through the gateway.
{% endstep %}
{% endstepper %}

### Next step

Expose the runner over an external API path in [To-do List Gateway](/examples/in-depth-exercise/to-do-list-gateway).

### Troubleshooting

* **Can’t find `system-mongo_master-0001`**: confirm your installation includes the default Mongo system element. If not, create a Mongo System Element first.
* **State writes fail**: confirm `mongo_master` points to a reachable MongoDB and that the user has write access.
* **`/actuator/health` not reachable**: the deployment may still be starting. Check pod status and logs.
* **UI deployment disabled**: you are likely on Sandbox. Apply the runner to an existing deployment and restart the container(s).


# To-do List Gateway

Expose the to-do CRUD runner through an API gateway by creating a channel mapping. You will assign a public path and verify external access to the runner endpoints.

This exercise exposes the to-do runner outside the cluster. You will create a **Gateway Channel** that forwards requests to the CRUD runner service.

### Before you start

* You completed [To-do List Runner](/examples/in-depth-exercise/to-do-list-runner) and the runner is deployed.
* You can access the [Devops](/devops/devops-overview) app.
* You know your API base URL: `https://[YOUR_ADMIN_API_DOMAIN]`.
* You have a gateway instance to target (example: `admin-prod`).

{% hint style="warning" %}
This guide configures the endpoint as **public** for simplicity. For real environments, require auth and limit paths.
{% endhint %}

### What you’ll build

* **Gateway Channel ID**: `todo_crud`
* **Public request path**: `GET /api/request/todo_crud/todo`
* **Target runner base URL** (example, internal):\
  `http://runner-spring-example-0001-service.admin-backend.svc.cluster.local:1235`
* **Runner target prefix**: `/api/todo`

{% stepper %}
{% step %}

### Open the Gateway Channel screen

Open the [Gateway Channels](/devops/api-gateway-and-security/gateway-servers/gateway-channels) screen from the Devops app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/devops/common/gateway_channel`.

<figure><img src="/files/Qdc8Q33HOVHabSH8ja7z" alt=""><figcaption><p>Gateway Channel Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create a new channel (todo\_crud)

Click **CREATE NEW** and assign the channel ID:

* `todo_crud`

Fill in the channel details and save:

<figure><img src="/files/Duc9eqlUhiFWqPBRSJ6h" alt=""><figcaption><p>Gateway Channel Definition Screen</p></figcaption></figure>

* **DEFINITION**
  * **Channel Name:** `Todo`
  * **Channel Status:** `ACTIVE`
  * **Description:** `CRUD path to todo list runner`
  * **Applicable Gateways:** `admin-prod`
  * **System Executor:** `CRUD`
  * **System Parameters**
    * **Key:** `server.baseUrl`
    * **Value:** `http://runner-spring-example-0001-service.admin-backend.svc.cluster.local:1235`
  * **Target:** `/api/todo`
* **AUTHENTICATION**
  * **Path Authentications:** `{ "*": { "isPublic": true } }`

This mapping means:

* The gateway receives requests under the channel name (`todo_crud`).
* It forwards the request to the runner service at `server.baseUrl`.
* It prefixes the forwarded path with `/api/todo`.

So a request to:

* `GET https://[YOUR_ADMIN_API_DOMAIN]/api/request/todo_crud/todo`

is forwarded to:

* `GET http://...:1235/api/todo/todo`
  {% endstep %}

{% step %}

### Wait for reload (or trigger it manually)

Most environments auto-reload gateway config after a short interval.

If you need to force a reload, call:

```
POST https://[YOUR_ADMIN_API_DOMAIN]/api/control/system/example-admin
POST https://[YOUR_ADMIN_API_DOMAIN]/api/control/channel/todo_crud
```

{% hint style="info" %}
If your gateway is configured differently, your control endpoints or system name may differ. Keep the idea: reload the gateway system, then reload the channel.
{% endhint %}
{% endstep %}

{% step %}

### Test the gateway endpoint

List to-do items through the public gateway endpoint:

```
GET https://[YOUR_ADMIN_API_DOMAIN]/api/request/todo_crud/todo
```

Expected result:

* HTTP `200`
* A JSON array containing any records you created earlier

If you get an empty list, create one item first (either via direct runner testing or by sending a `POST` through this same gateway channel).
{% endstep %}
{% endstepper %}

### Next step

Build an admin screen on top of this endpoint in [To-do List UI](/examples/in-depth-exercise/to-do-list-ui).

### Troubleshooting

* **404 on `/api/request/todo_crud/...`**: the channel ID is wrong or not active. Confirm it is saved and `ACTIVE`.
* **502/504**: `server.baseUrl` is unreachable from the gateway. Verify the service name, namespace, and port (`1235`).
* **401/403**: authentication is enforced by your gateway policy. Update **Path Authentications** or provide the required token.
* **Old behavior after edits**: trigger a manual reload using the control endpoints (or wait for the reload interval).


# To-do List UI

Create an Admin app, Source mapping, JSON Schema, and UI layout so users can manage to-do items from the Rierino Admin UI.

This exercise builds the Admin UI on top of your to-do API. You will create an App entry, map the UI to the gateway endpoint with a Source, define a JSON Schema, and build a basic CRUD screen.

### Before you start

* You completed [To-do List Gateway](/examples/in-depth-exercise/to-do-list-gateway).
* The gateway endpoint works: `GET https://[YOUR_ADMIN_API_DOMAIN]/api/request/todo_crud/todo`.
* You can access the [Design](/design/design-overview) app.
* You know your Admin UI base URL: `https://[YOUR_ADMIN_UI_DOMAIN]`.

### What you’ll build

* **App ID**: `example`
  * Menu path: `/common/todo`
* **Source ID**: `todo`
  * Default URL: `request/todo_crud/todo`
* **Schema ID**: `todo` (JSON Schema)
* **UI ID**: `todo`
  * Grouped lister by `data.project`
  * Editor fields: `data.name`, `data.project`

{% stepper %}
{% step %}

### Open the App screen

Open the [Apps](/design/user-interface/apps) screen from the Design app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/design/common/app`.

<figure><img src="/files/LtSEL79cvFkJBjpr94NJ" alt=""><figcaption><p>App Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create an App (example)

Click **CREATE NEW** and set the App ID:

* `example`

Fill in:

<figure><img src="/files/3SrKwtS74p4NFBCmb6lO" alt=""><figcaption><p>App Definition Screen</p></figcaption></figure>

* **DEFINITION**
  * **App Name:** `Example`
  * **App Status:** `ACTIVE`
  * **Description (optional):** `Application dedicated to list of examples.`
  * **Home Image:** `/image/configuration.png`
  * **Home Title:** `Example Navigator`
  * **Home Description:** `Everything you need to manage your example services.`
* **MENUS**
  * **Label:** `Todo`
  * **Icon:** `rules`
  * **Path:** `/common/todo`

Save the App.

Open `https://[YOUR_ADMIN_UI_DOMAIN]/app/example` to verify:

<figure><img src="/files/DxPiLelsBSYEmUqEpro2" alt=""><figcaption><p>Example App Home Page</p></figcaption></figure>
{% endstep %}

{% step %}

### Open the Source screen

Open the [Sources](/design/api-mapping) screen from the Design app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/design/common/source`.

<figure><img src="/files/GE61lC4Pi27glF4XCLqs" alt=""><figcaption><p>Source Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create a Source (todo)

Click **CREATE NEW** and set the Source ID:

* `todo`

Set:

<figure><img src="/files/byD07fBQvPo5EE9nuVg1" alt=""><figcaption><p>Source Definition Screen</p></figcaption></figure>

* **Source Name:** `Todo`
* **Source Status:** `ACTIVE`
* **Urls**
  * **Action:** `default`
  * **URL:** `request/todo_crud/todo`

This directs UI CRUD traffic to your gateway channel endpoint:

* `/api/request/todo_crud/todo`

{% hint style="info" %}
**Why do you need a Source?**

Sources decouple UI screens from physical endpoints. You can move services later without rewriting UIs.

Sources are also a control point. Without a Source, the platform treats CRUD access as disabled for UI.
{% endhint %}
{% endstep %}

{% step %}

### Open the Schema screen

Open the [Data Schema](/design/data-schema) screen from the Design app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/design/common/schema`.

<figure><img src="/files/AvSEvqDNwdpUbhHtuS6F" alt=""><figcaption><p>Schema Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create a Schema (todo)

Click **CREATE NEW** and set the Schema ID:

* `todo`

Paste this JSON Schema and save:

<figure><img src="/files/e3Oll9Q8oWFtIbo4Ihm4" alt=""><figcaption><p>Schema Definition Screen</p></figcaption></figure>

```json
{
  "title": "Todo",
  "description": "A todo definition",
  "type": "object",
  "properties": {
    "id": {
      "title": "Todo ID",
      "description": "The unique identifier for a todo",
      "type": "string",
      "readOnly": true
    },
    "data": {
      "title": "Todo Information",
      "description": "Properties of the todo",
      "type": "object",
      "properties": {
        "name": {
          "title": "Todo Name",
          "description": "Name of the todo",
          "type": "string"
        },
        "project": {
          "title": "Project",
          "description": "Related project for the todo",
          "type": "string"
        }
      }
    }
  }
}
```

Schema titles and descriptions populate UI labels. They also standardize your data model.

{% hint style="info" %}
Schema definitions follow JSON Schema. You can reuse them outside Rierino.
{% endhint %}
{% endstep %}

{% step %}

### Open the UI screen

Open the [UIs](/design/user-interface/uis) screen from the Design app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/design/common/ui`.
{% endstep %}

{% step %}

### Create a UI (todo)

Click **CREATE NEW** and set the UI ID:

* `todo`

Fill in:

<figure><img src="/files/Fdj168ZNmRgFf5icwIOO" alt=""><figcaption><p>UI Definition Screen</p></figcaption></figure>

* **DEFINITION**
  * **Name:** `Todo`
  * **Status:** `ACTIVE`
  * **Description (optional):** `UI design for todo list management`
  * **ID Field:** `id`
  * **Name Field:** `data.name`
* **LISTER**
  * **Lister:** `Grouped`
  * **Lister Title:** `Todo List`
  * **Group By:** `data.project`

Switch to **TABS** and build the editor:

1. Click **Add Tab**.
2. Set the tab label to `DEFINITION`.
3. Click **Add Grid**.
4. Click **Add** and set **Path** to `data.name`. Select **Text**.
5. Click **Add** and set **Path** to `data.project`. Select **Text**.

You should see:

<figure><img src="/files/FS4FWwJHpU1vIsgXPpjN" alt=""><figcaption><p>UI Tabs Screen</p></figcaption></figure>

Save the UI.

{% hint style="info" %}
**Why is UI separate from Schema?**

One Schema can power many UIs. This helps with permissions and team-specific views.

It also supports headless usage. Your APIs can work without UI definitions.
{% endhint %}
{% endstep %}

{% step %}

### Test the UI

Open your Example app:

* `https://[YOUR_ADMIN_UI_DOMAIN]/app/example`

Click the **Todo** menu entry.

You should be able to list, create, edit, and delete todos. Items should be grouped by `data.project`.

<figure><img src="/files/xWpkD2AfpuFk4xUgL08s" alt=""><figcaption><p>Todo Screen</p></figcaption></figure>
{% endstep %}
{% endstepper %}

### Next step

Add search support with [To-do List Query](/examples/in-depth-exercise/to-do-list-query).

### Troubleshooting

* **Todo menu does not show up**: confirm the App is `ACTIVE` and the menu path is `/common/todo`.
* **UI opens but list is empty**: create a record via the runner/gateway first, or confirm Mongo is reachable.
* **403/401 from the UI**: your gateway channel requires auth, or your session/token is missing required claims.
* **404 from the UI**: confirm Source URL is `request/todo_crud/todo` and the gateway channel ID is `todo_crud`.


# To-do List Query

Add search to the to-do list by creating a MongoDB Query, exposing it as an API through a Saga, and wiring the UI lister to use the query endpoint with a filter.

This exercise adds a simple search flow on top of the to-do list. You will:

* define a **Query** that filters todos by `data.project`
* expose it as an API using a **Saga**
* update the UI lister to call the query endpoint and show filtered results

### Before you start

* You completed [To-do List UI](/examples/in-depth-exercise/to-do-list-ui).
* You can access:
  * the [Query](/configuration/queries) screen in the Configuration app
  * the [Saga](/devops/api-event-and-process-flows) screen in the Devops app
  * the [Source](/design/api-mapping) and [UI](/design/user-interface/uis) screens in the Design app
* You know your API base URL: `https://[YOUR_ADMIN_API_DOMAIN]`.

{% hint style="info" %}
Why use a Saga?

The `todo-0001` runner is a **CRUD runner**. CRUD runners are designed for standard read/write operations.

For querying, you typically expose a dedicated RPC endpoint using a Saga (or an RPC runner).
{% endhint %}

### What you’ll build

* **Query ID**: `todo`
  * Filters `data.project = %%project%%`
* **Saga path**: `/SearchTodos`
* **API endpoint**: `GET https://[YOUR_ADMIN_API_DOMAIN]/api/request/rpc/SearchTodos?project=Personal`
* **Source update**: add `query -> request/rpc/SearchTodos`
* **UI update**: switch lister to **Query Table** and add a `project` filter

{% stepper %}
{% step %}

### Open the Query screen

Open the [Query](/configuration/queries) screen from the [Configuration](/configuration/configuration-overview) app.

Unless you changed routing, the UI is at `https://[YOUR_ADMIN_UI_DOMAIN]/app/configuration/common/query`.

<figure><img src="/files/Sq56XbGKIMjbttczRUMJ" alt=""><figcaption><p>Query Screen</p></figcaption></figure>
{% endstep %}

{% step %}

### Create the Query (todo)

Click **CREATE NEW** and set the Query ID:

* `todo`

Fill in the **DEFINITION** tab:

<figure><img src="/files/ybnsQ9lvStf87U4P7GQf" alt=""><figcaption><p>Query Definition Screen</p></figcaption></figure>

* **Query Name:** `Todo`
* **Query Status:** `ACTIVE`
* **Query Description (optional):** `Search todo list by project.`
* **Query Type:** `SIMPLE`
* **Query Platform:** `MONGODB`
* **Source Table:** `todo`
  {% endstep %}

{% step %}

### Add a WHERE condition (project)

Open the **WHERE** tab.

Hover on the plus icon and select **Simple**.

Edit the new condition:

<figure><img src="/files/6FXtfMtckAfvsDQuRRU3" alt=""><figcaption><p>Query Condition Dialog</p></figcaption></figure>

* **Use a Function:** `false`
* **Expression:** `data.project`
* **Operator:** `EQUALS`
* **Value:** `%%project%%`

Save the query.

{% hint style="info" %}
`%%project%%` is a parameter placeholder. You’ll pass it at runtime through the API call.
{% endhint %}
{% endstep %}

{% step %}

### Open the Saga screen

Open the [Saga](/devops/api-event-and-process-flows) screen from the [Devops](/devops/devops-overview) app.

If you need a refresher on the basics, follow the structure in [Exercise: Hello World API](/examples/training-examples/exercise-create-an-api-endpoint).
{% endstep %}

{% step %}

### Create a Saga (SearchTodos)

Create a new saga and set:

<figure><img src="/files/iwxWY0kTZBhejH3ruadE" alt=""><figcaption><p>Search Todos Saga Definition Screen</p></figcaption></figure>

* **Saga Name:** `Search Todos`
* **Status:** `ACTIVE`
* **Saga Path:** `/SearchTodos`
* **Version:** `0`
* **Allowed On:** `saga`
* **Saga Domain:** `util`
  {% endstep %}

{% step %}

### Add steps (Start → Event → Success)

Add **Start**, **Event**, and **Success** steps from the stencil.

Link them to form:

* `Start` → `Event` → `Success`
  {% endstep %}

{% step %}

### Configure the Start → Event link (local execution)

Edit the link from **Start** to **Event**:

<figure><img src="/files/sQ0zYHKbnS3LiapzwP5G" alt=""><figcaption><p>Saga Link Definition Dialog</p></figcaption></figure>

* **Stream:** `local`

`local` means the gateway executes the step without delegating to a remote runner.
{% endstep %}

{% step %}

### Configure the Event step (GetQuery)

Edit the **Event** step:

<figure><img src="/files/pHYi87gzHZ919IgbHhFx" alt=""><figcaption><p>Saga Event Definition Dialog</p></figcaption></figure>

* **DEFINITION**
  * **Step Name:** `Get Project Todos`
* **EVENT META**
  * **Event Version:** `0`
  * **Event Action:** `GetQuery`
  * **Event Domain:** `master`
  * **Input Element:** `parameters`
  * **Output Element:** `$`
  * **Parameters Map**
    * **Key:** `queryId`
    * **Value:** `todo`

This step executes [GetQuery](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/query-data) against the `master` system, using the Query ID `todo`.

It reads query parameters from `parameters` (so `project=...` becomes available as `%%project%%`).
{% endstep %}

{% step %}

### Save the Saga

Click **SAVE** to activate the saga. Wait for the gateway/runner reload interval if your environment uses one.
{% endstep %}

{% step %}

### Test the API endpoint

Call:

```
GET https://[YOUR_ADMIN_API_DOMAIN]/api/request/rpc/SearchTodos?project=Personal
```

Expected result:

* HTTP `200`
* A list of todos where `data.project` equals `Personal`
  {% endstep %}

{% step %}

### Update the Source (add the query URL)

Open the `todo` Source in the Design app (`.../app/design/common/source?id=todo`).

Add a new URL row:

* **Action:** `query`
* **URL:** `request/rpc/SearchTodos`

Save the Source.
{% endstep %}

{% step %}

### Update the UI lister (use Query Table + filter)

Open the `todo` UI in the Design app (`.../app/design/common/ui?id=todo`).

Update the **LISTER** tab:

<figure><img src="/files/C0ND8GEQKjpdrtlrh0LG" alt=""><figcaption><p>UI Lister Screen</p></figcaption></figure>

* **Lister:** `Query Table`
* **List Columns**
  * **Title:** `Name`, **Path:** `data.name`
  * **Title:** `Project`, **Path:** `data.project`
* **Main Filters**
  * **Path:** `project`, **Widget:** `TextFilter`, **Properties:** `{ "label": "Project" }`

Save the UI.
{% endstep %}

{% step %}

### Verify in the app

Open your Example app and go to the Todo screen.

You should now see a filter input for **Project**. Searching should call the saga endpoint and return filtered results.

<figure><img src="/files/IzeUlNUUd7p89sbe6RQo" alt=""><figcaption><p>Updated Todo Screen</p></figcaption></figure>
{% endstep %}
{% endstepper %}

### Next step

You now have a complete end-to-end example: CRUD + gateway + UI + query + saga.

If you want to expand it, add:

* multiple filters (name contains, status, date range)
* pagination/sorting in the query lister
* authentication on the gateway channel

### Troubleshooting

* **Empty results**: ensure you have at least one todo with `data.project = "Personal"`.
* **Saga returns an error about `queryId`**: confirm the Query ID is exactly `todo`.
* **Parameter not applied**: confirm the saga reads from **Input Element: `parameters`** and you call `?project=...`.
* **UI still does CRUD calls**: confirm you added the Source URL for action `query` and changed the lister to **Query Table**.


# Devops Overview

Overview of the Devops app for building API flows, microservices, gateways, deployments, and runtime operations in Rierino.

## **What the Devops app does**

The Devops app is where you design, deploy, and operate the platform’s core building blocks. It brings the runtime pieces (runners and deployments) together with orchestration (sagas) and the edge layer (gateway and security), so you can ship changes quickly and still keep control.

<figure><img src="/files/SNOhkvFq9sXa6yEkpmNX" alt=""><figcaption><p>Devops App</p></figcaption></figure>

## **Core Devops capability areas**

Devops capabilities fall into four main areas:

* **Runtime:** Sagas, actions, runners and elements used for implementing [API flows](/devops/api-event-and-process-flows) and building [microservices](/devops/microservices)
* **Gateway:** Key capabilities for configuring [API gateways](/devops/api-gateway-and-security), including authentication customizations
* **Rollout:** Key capabilities for creating & merging [branches](/devops/branching-and-migration), migrating to test & production environments and deployments
* **Control & Admin:** Key capabilities for [controlling](/devops/administration) deployed services and users

## **How Devops components work together**

These building blocks are tightly connected. A typical request starts at the gateway, gets routed to one or more runners, and is often orchestrated through a saga. Supporting configuration, such as queries or model definitions, is usually stored in state managers so it can be updated without redeploying code.

<figure><img src="/files/Xn7szBAFjuo0oiOLbEyv" alt=""><figcaption><p>Relations between Blocks</p></figcaption></figure>

* **Gateway configuration** maps API channels (URL paths) to backend runners and services.
* **Deployments** package and install microservices. Each deployment contains one or more **runners**, and each runner contains **elements** that define what it can do and what it is allowed to access (handlers, systems, states, streams, and so on).
* **Sagas** orchestrate work across runners. A saga is a step graph that calls specific elements, potentially across multiple microservices, and returns a response or emits downstream events.
* **Configuration data** required by steps (for example queries, rules, or ML model definitions) is stored in **state managers** as records. This keeps behavior editable at runtime and easier to migrate between environments.


# API, Event & Process Flows

Sagas are the API, event and process flow definitions across the platform, which can be distributed across multiple servers for execution.

![Saga UI](/files/5NIhahpQeNQee4gb1OiK)

A saga is Rierino’s orchestration layer for APIs and backend processes. It turns a trigger (usually a URL path) into an executable step graph.

Each saga step can run on the same runner or a different runner. This lets you combine microservices and shared logic into one flow. You build sagas with drag-and-drop steps and explicit success/fail routing.

Common use cases include API composition, validation, caching, and resilience. You can also run sagas on schedules or as “fire & forget” tasks.

{% hint style="info" %}
Changes in a saga flow or creation of a new saga are deployed in real-time, regardless of how distributed the saga event runners are.
{% endhint %}


# Using the Saga Screen

How to use the Saga screen to browse, edit, and manage API flow graphs in Rierino.

## At a glance

* Left panel: list of sagas, grouped by **domain** and **path**.
* Center canvas: drag-and-drop **step graph**.
* Top bar: edit saga details, add steps, and tidy layout.
* Save is “live”: changes propagate to runners in real time.

### Open the Saga screen

Open **Devops → Saga**. You’ll land on a visual graph editor for building flows step by step.

The screen behaves like other Rierino screens. You get save, delete, duplicate, and import/export menus.

### Pick the right saga (domain/path/stream)

Sagas are listed on the left, grouped by domain and path. The system can store multiple saga records for the same URL path.

<details>

<summary>How multiple sagas on the same path are selected</summary>

* If only one saga is **active**, it is used.
* If more than one saga is active, but each is allowed on different **streams**, the runner picks the one matching the incoming stream.
* If more than one saga is active on the **same** stream, only the first record is used.

</details>

### Use a meaningful saga ID

The saga ID field is editable. Use a meaningful unique ID for easier log searches.

<figure><img src="/files/5epiapVAZI76HCpqQShp" alt=""><figcaption><p>Icon Bar</p></figcaption></figure>

### Icon bar: edit, build, layout

{% columns %}
{% column %}

#### Left: edit saga details

Click the edit icon to open the saga definition popup. This is where you set path, allowed runners/streams, schema, caching, and more.
{% endcolumn %}

{% column %}

#### Middle: add steps

Drag step types onto the canvas. Then connect them with links to define the execution order.
{% endcolumn %}

{% column %}

#### Right: layout tools

Use alignment and grid controls to keep the flow readable. You can also change the grid size and visibility.
{% endcolumn %}
{% endcolumns %}

### Build a flow (recommended shape)

Each saga needs at least one **Start** step. Use **Success** and **Fail** steps as exit points. Add Event / Transform / Condition steps in between.

<details>

<summary>Parallel starts (multiple Start steps)</summary>

If a saga has more than one Start step, they run in parallel threads. This is available starting from version 1.8.0.

Parallel branches do not auto-merge payloads. Use the Merge event handler if you need a combined payload.

Keep parallel branches in the same runner when possible. Prefer synchronous links if distributing across runners.

</details>

### Save & deploy behavior (real-time)

Creating or updating a saga updates the runtime in real time. This depends on change data capture not being disabled.

<details>

<summary>How saves affect in-flight requests</summary>

* Requests already running on a different saga record (different ID) continue on the old flow. This is true even if you mark that other saga inactive.
* Requests running on the currently active saga may pick up your new graph mid-flight. Big changes (like removing steps) can break these requests.

If you need zero disruption, use a versioned or backup saga briefly. Switch traffic once you’re confident no requests are in-flight.

</details>

{% hint style="info" %}
To copy multiple steps at once, keep pressing Ctrl while clicking **Copy** on a selected step. This builds a multi-step clipboard and works across sagas.
{% endhint %}

## Saga Data Schema (reference)

{% code expandable="true" %}

```json
{
	"type": "object",
	"properties": {
		"id":{
			"type": "string"
		},
		"data":{
			"type": "object",
			"properties": {
				"path":{
					"type": "string",
					"description": "URL path from which the saga is called, in a single /Path format"
				},
				"name":{
					"type": "string",
					"description": "Logical name of the saga"
				},
				"description":{
					"type": "string",
					"description": "Logical description of what the saga does"
				},
				"allowedFor":{
					"type": "array",
					"description": "List of runners on which the saga is allowed to run",
					"items": {
						"type": "string",
						"description": "ID of the runner"
					}
				},
				"schema":{
					"type": "object",
					"properties": {
						"input": {
							"type": "object",
							"description": "JSON schema representing input data model and validation rules"
						},
						"output": {
							"type": "object",
							"description": "JSON schema representing output data model and example values for mocking APIs"
						}
					}
				},
				"steps":{
					"type": "array",
					"description": "List of connected steps in saga, which create a sequential execution logic for the flow",
					"items": {
						"type": "object",
						"properties": {
							"id": {
								"type": "integer",
								"description": "Unique ID of the step inside the saga, typically assigned in a sequential manner"
							},
							"name":{
								"type": "string",
								"description": "Logical name of the step"
							},
							"description": {
								"type": "string",
								"description": "Logical description of the step"
							},
							"type": {
								"type": "string",
								"description": "Type of the step",
								"enum": ["START", "FINISH", "FAIL", "EVENT", "CONDITION", "TRANSFORM"]
							},
							"position": {
								"type": "object",
								"description": "Visual positioning of the step in flow diagram. Try to use a logical layout, where the steps have spacing between them. Each step has 100 width and 50 height.",
								"properties":{
									"x":{
										"type": "number",
										"description": "X position on the diagram"
									},
									"y":{
										"type": "number",
										"description": "Y position on the diagram"
									}
								}
							},
							"links": {
								"type": "array",
								"description": "Links from this step to others defining next step to execute after this step".
								"items":{
									"type": "object",
									"properties": {
										"id": {
											"type": "integer",
											"description": "Unique ID of the condition inside the saga, typically assigned in a sequential manner"
										},
										"toStepID": {
											"type": "integer",
											"description": "Next step to execute"
										},
										"conditionValues":{
											"type": "array",
											"description": "Value for which this link should be traversed. This value depends on the output produced by conditionClass of the originating step. * can be used as a wildcard for a default 'else' branch. If the previous step is an event type step, SUCCESS and FAIL values can be used to route failed events to a different next step, but only if the user explicitly mentions following a different flow on failure. You do not need to provide conditionValues if there is a single next step and it will always be executed."
										}										
									}
								}
							}
						}
					}
				},
			}
		}
	}
}
```

{% endcode %}


# Defining a Saga

Reference for configuring a saga’s definition, execution rules, caching, resilience, scheduling, schema, and AI settings.

<figure><img src="/files/CXFRLseLOQ0e86qyjTgx" alt=""><figcaption><p>Saga Definition</p></figcaption></figure>

Click the edit icon on the Saga screen. This opens the saga definition form. The form is split into tabs.

## Definition

Fields marked with `*` are required.

* **Name:** Human-friendly name shown in lists and on the graph.
* **Domain:** Logical grouping (for example `customer` or `product`).
* **Status\*:** Only active sagas accept requests.
* **Description:** Short explanation for documentation and maintenance.
* **Path\*:** URL path that triggers this saga.
  * Must start with `/`.
  * Use alphanumerics and no spaces.
  * Runners select the saga by matching this path in request metadata.
  * You can keep multiple sagas on one path.
  * You can also define stream-driven sagas using `/On_[stream]`.
* **Version:** Numeric version for maintaining multiple flows per path.
* **Allowed On Streams:** Streams where this saga may run (HTTP, Kafka, etc.).
* **Allowed For Runners\*:** Runners allowed to execute this saga.
  * Use this alone if sagas run on a single stream.
  * Combine with streams for tighter control.
* **Allowed Roles:** Roles permitted to execute this saga.
  * You can also enforce this at the gateway.
  * Gateway enforcement can avoid an extra microservice call.
* **Allowed Methods:** REST methods allowed for this path (GET/POST/etc.).
  * Useful when you want to prevent GET-based caching.
* **Auto Fail:** Fail the entire saga when any step fails.
  * If disabled, handle failures per step and route explicitly.
* **Fire & Forget:** Return immediately and run the flow asynchronously.
  * Status and results are recorded if Fire & Forget state is configured.
  * Fire & forget sagas include "reference" data field including the unique ID returned to the user for querying status of the execution. At the end of saga execution, the status is automatically updated, but it can be manually edited (e.g. "Processing X Step") within the saga flow with an Update action as well.

## Configuration

* **Redirect To:** Always execute another saga instead of this one.
  * Useful for mapping multiple URLs to one flow.
* **On Fail Saga:** Execute another saga when this saga fails.
  * Useful for recovery actions or persistent error logging.
* **Extra Payload:** Add a static payload to every call.
  * Works with Redirect To.

### Caching

You can cache individual steps in some handlers. Saga-level caching caches the final response. The cache key is derived from the input payload.

* **Use Cache:** Enable caching on the runner.
* **Cache State:** State manager alias used as the cache store.
* **Cache Key Pattern:** JMESPath expression that produces the cache key.

### Resilience

You can configure resilience at the API gateway. You can also configure it per saga on the runner.

This is optional. It helps when a saga calls unstable dependencies. External APIs are a common example.

Circuit breakers support these settings:

* **Min. Number of Calls:** Minimum requests before error rate is calculated.
* **Sliding Window Threshold:** How many recent calls to evaluate.
* **No Reply Timeout Duration:** Milliseconds to consider the saga non-responsive.
* **Failure Rate Threshold:** Failure percentage that opens the circuit.
* **Slow Call Duration Threshold:** Milliseconds that count as a slow call.
* **Slow Call Rate Threshold:** Slow-call percentage that opens the circuit.
* **Wait Duration in Open State:** Milliseconds to stay open before half-open.
* **Calls Permitted in Half Open:** Test calls allowed in half-open.

Circuit breakers run at runner partition level. If one partition fails often, others are not blocked. This isolates the blast radius in distributed deployments.

### Scheduling

Use Python processors for complex scheduled jobs. Use saga scheduling for simpler and short-running tasks. Scheduling runs directly on the runner via timers.

* **Period:** Trigger interval (for example every 10 seconds).
* **Period Unit:** Seconds, minutes, and so on.
* **Initial Delay (ms):** Delay before the first run.
* **Max Repeat Count:** Maximum runs before stopping.
  * This counter resets on runner restart or rebuild.
* **Cron Expression:** Cron schedule for more complex timing.
* **Cron Time Zone:** Time zone for cron evaluation.
  * Defaults to server time zone.

{% hint style="warning" %}
To avoid same saga being scheduled on multiple replicas of a runner:

* Either, deploy the runner with a single replica
* Or, deploy the runner as a StatefulSet and configure only the partition 0 with a timer

Otherwise, the saga would be executed multiple times with each period.
{% endhint %}

{% hint style="warning" %}
When scheduling a saga, it is important to configure the "Allowed For Runners" setting, since scheduling does not use streams for triggering saga flows.

Otherwise, all runners with timers would trigger the same saga with each period.
{% endhint %}

## Schema

Schema defines the saga input and output models. It is used for documentation and optional validation. OpenAPI is generated from this configuration.

* **Method in Documentation:** HTTP method shown in OpenAPI.
* **Exclude in Documentation:** Hide this saga from OpenAPI.
* **Mock Output:** Return mock responses from Output Schema examples.
* **Validated:** Validate requests against Input Schema.
  * Invalid requests return an error response.
* **Input Schema:** JSON Schema for request payload.
* **Output Schema:** JSON Schema for response payload.

{% file src="/files/JZ2lCXfWQrUbMWGbVcof" %}
Example Saga Definition (Can be Imported on Saga Screen)
{% endfile %}

### Validation

When **Validated** is enabled, requests are checked against Input Schema. Standard JSON Schema constraints are supported. Examples include `minimum`, `minLength`, and `pattern`.

{% embed url="<https://json-schema.org/specification>" %}
JSON Schema Specification
{% endembed %}

For advanced validation, Rierino adds an `x-validation` extension keyword. It lets you attach custom validators to a schema. Use this structure (placeholders shown in ALL CAPS):

```json
"x-validation":{
    "VALIDATOR_1_NAME": {
        "validator": "VALIDATOR_CLASS",
        "scope":{
            "type": "TYPE",
            "fields": ["FIELD_PATH_1", "FIELD_PATH_2"]
        },
        "props": { "VALIDATOR_SPECIFIC_PROPERTIES": "..." }
    },
    ...
    "VALIDATOR_N_NAME": {...}
    ...
}
```

* **VALIDATOR\_NAME:** Any logical name for this validator instance.
* **VALIDATOR\_CLASS:** Fully qualified Java class extending `BaseJsonValidator`.
* **Scope (optional):** Apply the validator to nested fields.
  * **type:** Data type to match (for example `string`).
  * **fields:** JSON paths of nested fields to validate.
* **props:** Extra validator-specific configuration object.

Example: `JsoupValidator` detects unsafe HTML content.

```json
"x-validation":{
    "safeHtml": {
        "validator": "com.rierino.handler.util.jsonschema.JsoupValidator",
        "scope":{
            "type": "string"
        },
        "props": { 
            "safelist": "relaxed"
         }
    }
}
```

## AI

AI settings control how this saga is exposed as an agent tool. This is optional. It gives you tighter control over tool calls and responses.

* **Tool Name:** Tool name generated for this saga.
  * If empty, a unique name is generated.
  * Must match agent tool naming rules.
* **Tool Description:** Tool description shown to the agent.
  * If empty, the saga description is used.
  * Use this when you need AI-specific wording.
* **Tool Response Pattern:** JMESPath expression that maps saga output to text.
  * If empty, the agent expects a `message` field.
* **Tool Restriction:** Controls repeated calls with identical parameters.


# Configuring Saga Steps

Reference for the common settings, step types, and links used to build and control saga execution flows.

Saga flows start with a single START node and can have one or more SUCCESS / FAIL nodes as the exit point. Other nodes are linked as sequential steps in between them and have the following common parameters:

* **Name:** Descriptive name of the step, which will be displayed on saga graph
* **Description:** Detailed description of what this step will perform
* **Stroke:** Stroke color of the step on saga graph
* **Fill:** Fill color of the step on saga graph
* **Auto Fail:** Whether saga should automatically fail if this step fails
* **Continue on Fail:** Whether saga step should continue on fail (to override in case saga itself is configured as Auto Fail)

### Step types

Saga graphs are built from a small set of step types. Each type has different configuration fields and runtime behavior.

#### Control steps

These steps define entry and exit points of the flow:

* **Start:** Entry point for the saga execution.
* **Success:** A successful exit point.
* **Fail:** A failure exit point.

#### Action and logic steps

These steps do the work between Start and exit nodes:

* [Event Step](/devops/api-event-and-process-flows/configuring-saga-steps/event-step): calls an event handler action with parameters.
* [Transform Step](/devops/api-event-and-process-flows/configuring-saga-steps/transform-step): transforms the current payload and passes the output forward.
* [Condition Step](/devops/api-event-and-process-flows/configuring-saga-steps/condition-step): evaluates a condition and routes to different next steps.

#### Connecting steps

* [Step Link](/devops/api-event-and-process-flows/configuring-saga-steps/step-link): defines how the flow moves from one step to the next. Use condition values to model branching and default (`*`) paths.

{% hint style="info" %}
Double clicking on a step on stencil automatically adds it as a connected step for the currently selected node on saga flow.
{% endhint %}


# Event Step

Event steps pass event payload to an event handler, to execute selected action with given parameters.

<figure><img src="/files/1p2uST7Ee1tCHEjmpExr" alt=""><figcaption><p>Event Step Definition</p></figcaption></figure>

Dragging and dropping an event step from the icon bar of a saga adds a new step. It is possible to configure each step clicking on the edit icon displayed when hovering its node. The following fields are used for overall settings of the step:<br>

* **Name:** Descriptive name of the step, which will be displayed on the saga flow.
* **Auto Fail:** Whether failure of this step should automatically fail the whole saga flow. If not set to true (or the saga itself has auto fail setting), error status should be handled separately.
* **Description:** Verbal description of the step, for reference and documentation.
* **Stroke:** Color to use for drawing borders of the step, for visual purposes.
* **Fill:** Color to use for filling the step node, for visual purposes.

<figure><img src="/files/61OEgMffTqLFgZEbqYdw" alt=""><figcaption><p>Event Step Metadata</p></figcaption></figure>

The actual functionality of an event step is defined using event metadata settings listed below:<br>

* **Event Handler:** Alias of the event handler that should be used for calling a function on the runner receiving this event (e.g. read). This is an optional setting in some cases, as runners can match handlers to events based on streams the requests are received from. However, if the event is being processed locally (e.g. on "local" stream), this setting should be explicitly defined.
* **Event Version\*:** Numerical version of the action implementation to be used. Handlers allow versioning of their functions (i.e. actions) with new releases, so this setting defines which version should be used for a specific request. This is a mandatory setting, which should be set to 0 for unversioned actions.
* **Event Action\*:** Name of the function to be called on target event handler (e.g. Get) or alias of the preconfigured action on target runner (e.g. GetProduct). This is a critical setting, as it specifies actual action to execute for the step.
* **Event Domain:** Alias of a state, query or a system, which is used as the main target for event action (e.g. "Get" from "product" state). The meaning of this setting depends on the event handler configuration itself.
* **Input Element:** Json path for the data input from event payload (e.g. parameters). This parameter allows using events with different formats as input to the same event handler. If no input element is provided, full payload is used as the input.
* **Output Element:** Json path for the data output on event payload (e.g. list). This parameter allows outputing to different paths based on output format required by the API endpoint or the next saga step. If an input element is given, output element is relative to that path. If the output element starts with '$.', it is relative to the root of event payload, ignoring input element setting. If the output element is '-', it is ignored and no data is added to event payload as the output.
* **Deployments:** List of runner deployment ids which are allowed to execute this step. This is required when more than one runner deployment exists (e.g. v1, v2). If the deployment id is not specified in such scenario, both runners would process the same event, resulting in duplicate actions and responses. This is a rare case, typically used when deploying a new runner version while the old version is still running to avoid downtime (e.g. changing deployment id only after new version is up and running).
* **Inject:** Whether these settings (e.g. input element, domain, etc.) should allow injection of key-value parameters and secrets or not.
* [**Follow Ack**](#user-content-fn-1)[^1]**:** Whether event status ACK should continue saga flows [instead of immediately returning](#user-content-fn-2)[^2]
* **Response System:** Alias of the system for the receiving runner to reply on. This setting is used when communication is through an event streaming platform (e.g. Kafka) and the response should be sent through a system different than the default.
* **Response Stream:** Alias of the stream for the receiving runner to reply on. This setting is used when communication is through an event streaming platform (e.g. Kafka) and the response should be sent through a stream different than the default.
* **Parameter Map:** Handler and action specific list of parameters to use for the event. For a full list of these parameters, please refer to [Handlers](/devops/microservices/building-blocks/execution-handlers).

These settings work similar to a remote function call, where the handler and action define target function and other settings define its parameters for execution.

{% hint style="info" %}
An event step can be executed locally or sent out to other runners for async and more scalable execution, orchestrating multiple microservices.
{% endhint %}

## Event Step Data Schema

{% code expandable="true" %}

```json
{
		"eventMeta": {
			"type": "object",
			"description": "Event metadata defining details on the action call",
			"properties": {
				"handler": {
					"type": "string",
					"description": "Alias of the handler to be used for processing event step",
					"examples": ["read", "write", "query", "rest"]
				},
				"action": {
					"type": "string",
					"description": "Name of the action/function to call, which is specific to the handler selected",
					"examples": ["Get", "Create", "GetQuery", "CallRest"]
				},
				"domain": {
					"type": "string",
					"description": "Domain for which the action will be taken, which has a different meaning based on the action type (such as database table for Create action)"
				},
				"inputElement": {
					"type": "string",
					"description": "JSON path of the data field in event payload, which should be used as input for the action"
				},
				"outputElement": {
					"type": "string",
					"description": "JSON path of the data field where outputs of the action should be writted on. Output element uses input element as the root and creates children below that root, unless output element starts with $, which refers to the event payload making it the root."
				},
				"parameters": {
					"type": "object",
					"description": "Key-value pair parameters used by the specific action type (such as inputPattern for Create action)"
				}
			}
		}
	}
```

{% endcode %}

## Using Preconfigured Actions

While it is possible to define all settings for each event step inside a saga, especially for high volume and low latency requirements, it may be preferrable to define default values once and reuse them for each call.

There are 3 alternative ways of achieving this, which can be also combined together based on the use case:

1. Defining predefined "Action" records and using [Broken mention](broken://pages/vMEjRSndZzV2Kzyiepjy) handler to call them.
2. Defining structural [Actions](/devops/microservices/building-blocks/additional-elements/actions) runner elements with the default values and using them as event actions for requests to runners with these elements.
3. Defining metadata overrides to streams through which these action requests are sent to the target event runners.

This approach has 2 main benefits:

1. Not sending the same list of settings with each request decreases the size of data transferred and stored.
2. It becomes possible to update the list of parameters used for same type of request across all sagas at once.

[^1]: Since 0.5.0

[^2]: E.g. for TaskEventHandler, whether to return immediately, or allow custom logic in saga flow design using ACK event status with a condition step


# Core Actions

Core actions range from basic data read/write operations to Handlebars templates for HTML rendering, user task orchestration for business process automation


# Write Data

These actions provide ability to create, update, delete records on a state manager on demand, facilitating common REST API write calls

## Write Data Actions

Most write actions utilize the following event metadata fields:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Domain         | Name of the state manager to read data from        | product    | -       |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | $.product  | -       |

{% endtab %}

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Write Data action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the state manager to read data from",
          "example": "product"
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "$.product"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter       | Definition                                                                                                                                                                                            | Example                                               | Default |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ------- |
| Input Pattern   | JMESPath pattern to apply on data input                                                                                                                                                               | {id:parameters.id, data:parameters.data}              | -       |
| Output Pattern  | JMESPath pattern to apply on data output, before returning response                                                                                                                                   | {id:id, name:data.name, description:data.description} | -       |
| Use Diff        | Whether handler should generate journals keeping only actual updates from current data for the event                                                                                                  | true                                                  | false   |
| If Pattern      | JMES path pattern evaluating condition on current data to decide whether to execute update                                                                                                            | data.status == 'A'                                    | -       |
| Fail Stale      | Whether to fail in case a request with old instance version or offset arrives                                                                                                                         | false                                                 | true    |
| Return Result   | Whether the action should return updated data after the change                                                                                                                                        | false                                                 | true    |
| Immediate       | Whether the action should be executed immediately, or can be buffered for bulk execution                                                                                                              | false                                                 | true    |
| Keep Impact     | Whether the action should also return the impact created on current record                                                                                                                            | true                                                  | false   |
| Keep Undo       | Whether the action should also return the undo action required to revert the impact                                                                                                                   | true                                                  | false   |
| Structure       | Type of input to apply updates for (i.e. [array ](#user-content-fn-1)[^1]or [each ](#user-content-fn-2)[^2]= \[{id, data}, {id, data}], multi[^3] = \[ids: \[id, id], data: {}], single = {id, data}) | array                                                 | single  |
| Data Path       | Json path for the data to use in update, when form is "multi"                                                                                                                                         | newData                                               | data    |
| IDs Path        | Json path for the ids to update, when form is "multi"                                                                                                                                                 | productids                                            | ids     |
| Item Path       | Json path for the array field to update (for SetElement and RemoveElement)                                                                                                                            | parameters                                            | -       |
| Allow Manual ID | When creating a new record, whether IDs can be given manually, if there is already an ID generator                                                                                                    | true                                                  | false   |
| {% endtab %}    |                                                                                                                                                                                                       |                                                       |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Write Data action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data input",
              "example": "{id:parameters.id, data:parameters.data}"
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": "{id:id, name:data.name, description:data.description}"
            },
            "useDiff": {
              "type": "boolean",
              "definition": "Whether handler should generate journals keeping only actual updates from current data for the event",
              "default": false,
              "example": true
            },
            "ifPattern": {
              "type": "string",
              "definition": "JMES path pattern evaluating condition on current data to decide whether to execute update",
              "example": "data.status == 'A'"
            },
            "failStale": {
              "type": "boolean",
              "definition": "Whether to fail in case a request with old instance version or offset arrives",
              "default": true,
              "example": false
            },
            "returnResult": {
              "type": "boolean",
              "definition": "Whether the action should return updated data after the change",
              "default": true,
              "example": false
            },
            "immediate": {
              "type": "boolean",
              "definition": "Whether the action should be executed immediately, or can be buffered for bulk execution",
              "default": true,
              "example": false
            },
            "keepImpact": {
              "type": "boolean",
              "definition": "Whether the action should also return the impact created on current record",
              "default": false,
              "example": true
            },
            "keepUndo": {
              "type": "boolean",
              "definition": "Whether the action should also return the undo action required to revert the impact",
              "default": false,
              "example": true
            },
            "structure": {
              "type": "string",
              "definition": "Type of input to apply updates for (array / each / multi / single)",
              "default": "single",
              "example": "array"
            },
            "dataPath": {
              "type": "string",
              "definition": "Json path for the data to use in update, when form is \"multi\"",
              "default": "data",
              "example": "newData"
            },
            "idsPath": {
              "type": "string",
              "definition": "Json path for the ids to update, when form is \"multi\"",
              "default": "ids",
              "example": "productids"
            },
            "itemPath": {
              "type": "string",
              "definition": "Json path for the array field to update (for SetElement and RemoveElement)",
              "example": "parameters"
            },
            "allowManualId": {
              "type": "boolean",
              "definition": "When creating a new record, whether IDs can be given manually, if there is already an ID generator",
              "default": false,
              "example": true
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "id": "given-id",
        "data":{
            "name": "Test",
            "description": "Test Entry"
        }
    }
}
```

Event Metadata

![](/files/HDNyTTT8QPMg2pDS4Iwq)

</details>

### Create

Creates a new aggregate on a specific state manager.

### Update

Patches an existing aggregate on a specific state manager.

### Set

Completely updates an existing aggregate on a specific state manager.

### Upsert

Completely updates or creates an aggregate on a specific state manager.

### Delete

Marks an aggregate as deleted, hiding it on a specific state manager.

### Undelete

Unmarks an aggregate as deleted, making it accessible again on a specific state manager.

### Remove

Completely removes an aggregate from a specific state manager.

### SetElement

Adds to or sets element of an array field of an aggregate on a specific state manager.

### RemoveElement

Removes element of an array field of an aggregate on a specific state manager.

### CallSP

This is a special action, which makes calls to stored procedures in state managers which support the functionality (such as Jooq state manager for RDBMS). Special parameters used by this action are:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                 | Example                             | Default |
| -------------- | ---------------------------------------------------------- | ----------------------------------- | ------- |
| Command        | Procedure call command with parameters                     | CALL update\_status({0}, {1})       | -       |
| Input Pattern  | JMESPath for transforming input into call parameters array | \[parameters.id, parameters.status] | -       |
| Output Pattern | JMESPath for transforming procedure call results           | -                                   | -       |
| {% endtab %}   |                                                            |                                     |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Write Data CallSP action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "command": {
              "type": "string",
              "definition": "Procedure call command with parameters",
              "example": "CALL update_status({0}, {1})"
            },
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath for transforming input into call parameters array",
              "example": "[parameters.id, parameters.status]"
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath for transforming procedure call results"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

[^1]: Executes all impacts at once

[^2]: Executes each impact entry individually as a loop (typically used when id generator requires previous entries executed first)

[^3]: Executes same impact on multiple records at once


# Read Data

These actions provide ability to select one, multiple or all records from a state manager on demand, facilitating common REST API read calls.

## Read Data Actions

### Get

Reads and returns aggregate for a single ID from a specific state manager. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Domain         | Name of the state manager to read data from        | product    | -       |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | product    | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read Data Get action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the state manager to read data from",
          "example": "product"
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "product"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                           | Example                                               | Default |
| -------------- | -------------------------------------------------------------------- | ----------------------------------------------------- | ------- |
| Output Pattern | JMESPath pattern to apply on data output, before returning response  | {id:id, name:data.name, description:data.description} | -       |
| ID Path        | Json path for the id field in input element                          | product.id                                            | id      |
| ID Value       | Static ID to read instead of idPath value                            | 1234                                                  | -       |
| Fields         | Comma separated list of fields to keep in response                   | data.name,data.description                            | -       |
| Form           | Form of response to produce (i.e. full=including custom data fields) | full                                                  | -       |
| Customize By   | Comma separated list of customizations to apply to data              | luxury,tech\_savvy                                    | -       |
| Version Type   | Type of version data to return (history[^1], snapshot[^2], none[^3]) | history                                               | none    |
| {% endtab %}   |                                                                      |                                                       |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read Data Get action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": "{id:id, name:data.name, description:data.description}"
            },
            "idPath": {
              "type": "string",
              "definition": "Json path for the id field in input element",
              "default": "id",
              "example": "product.id"
            },
            "idValue": {
              "type": ["string", "integer"],
              "definition": "Static ID to read instead of idPath value",
              "example": 1234
            },
            "fields": {
              "type": "string",
              "definition": "Comma separated list of fields to keep in response",
              "example": "data.name,data.description"
            },
            "form": {
              "type": "string",
              "definition": "Form of response to produce (i.e. full=including custom data fields)",
              "example": "full"
            },
            "customizeBy": {
              "type": "string",
              "definition": "Comma separated list of customizations to apply to data",
              "example": "luxury,tech_savvy"
            },
            "versionType": {
              "type": "string",
              "definition": "Type of version data to return (history, snapshot, none)",
              "default": "none",
              "example": "history"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "id": "given-id"
    }
}
```

Event Metadata

![](/files/UvdDaVCOY70i2Xf7k14X)

</details>

### GetList

Reads and returns aggregates for a list of ID from a specific state manager. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example             | Default |
| -------------- | -------------------------------------------------- | ------------------- | ------- |
| Domain         | Name of the state manager to read data from        | product             | -       |
| Input Element  | Json path for the input in request event payload   | parameters.products | -       |
| Output Element | Json path for the output in response event payload | list                | -       |
| {% endtab %}   |                                                    |                     |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read Data GetList action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the state manager to read data from",
          "example": "product"
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters.products"
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "list"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If input element ends with .\*, it allows iteration of an array of {id:""} objects for injection of their details. Otherwise, this action expects a list of ids in \[""] form.
{% endhint %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                               | Example                                               | Default |
| -------------- | ------------------------------------------------------------------------ | ----------------------------------------------------- | ------- |
| Output Pattern | JMESPath pattern to apply on each data output, before returning response | {id:id, name:data.name, description:data.description} | -       |
| Fields         | Comma separated list of fields to keep in response                       | data.name,data.description                            | -       |
| Form           | Form of response to produce (i.e. full=including custom data fields)     | full                                                  | -       |
| Customize By   | Comma separated list of customizations to apply to data                  | luxury,tech\_savvy                                    | -       |
| Skip           | Number of rows to skip in results                                        | 20                                                    | -       |
| Limit          | Maximum number of rows to return                                         | 10                                                    | -       |
| Version Type   | Type of version data to return (history[^1], snapshot[^2], none[^3])     | history                                               | none    |
| {% endtab %}   |                                                                          |                                                       |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read Data GetList action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on each data output, before returning response",
              "example": "{id:id, name:data.name, description:data.description}"
            },
            "fields": {
              "type": "string",
              "definition": "Comma separated list of fields to keep in response",
              "example": "data.name,data.description"
            },
            "form": {
              "type": "string",
              "definition": "Form of response to produce (i.e. full=including custom data fields)",
              "example": "full"
            },
            "customizeBy": {
              "type": "string",
              "definition": "Comma separated list of customizations to apply to data",
              "example": "luxury,tech_savvy"
            },
            "skip": {
              "type": "integer",
              "definition": "Number of rows to skip in results",
              "example": 20
            },
            "limit": {
              "type": "integer",
              "definition": "Maximum number of rows to return",
              "example": 10
            },
            "versionType": {
              "type": "string",
              "definition": "Type of version data to return (history, snapshot, none)",
              "default": "none",
              "example": "history"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
For complex use cases with skip, limit, fields or outputPattern using QueryEventHandler could provide better performance, as it benefits from pass-thru query execution.
{% endhint %}

### GetAll

Reads and returns all aggregates from a specific state manager. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Domain         | Name of the state manager to read data from        | product | -       |
| Output Element | Json path for the output in response event payload | list    | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read Data GetAll action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the state manager to read data from",
          "example": "product"
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "list"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                               | Example                                               | Default |
| -------------- | ------------------------------------------------------------------------ | ----------------------------------------------------- | ------- |
| Output Pattern | JMESPath pattern to apply on each data output, before returning response | {id:id, name:data.name, description:data.description} | -       |
| Fields         | Comma separated list of fields to keep in response                       | data.name,data.description                            | -       |
| Form           | Form of response to produce (i.e. full=including custom data fields)     | full                                                  | -       |
| Customize By   | Comma separated list of customizations to apply to data                  | luxury,tech\_savvy                                    | -       |
| Skip           | Number of rows to skip in results                                        | 20                                                    | -       |
| Limit          | Maximum number of rows to return                                         | 10                                                    | -       |
| Order By       | Order by field for results with direction                                | name desc                                             | -       |
| Count As       | Json path to return total number of rows on event payload                | total                                                 | -       |
| {% endtab %}   |                                                                          |                                                       |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read Data GetAll action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on each data output, before returning response",
              "example": "{id:id, name:data.name, description:data.description}"
            },
            "fields": {
              "type": "string",
              "definition": "Comma separated list of fields to keep in response",
              "example": "data.name,data.description"
            },
            "form": {
              "type": "string",
              "definition": "Form of response to produce (i.e. full=including custom data fields)",
              "example": "full"
            },
            "customizeBy": {
              "type": "string",
              "definition": "Comma separated list of customizations to apply to data",
              "example": "luxury,tech_savvy"
            },
            "skip": {
              "type": "integer",
              "definition": "Number of rows to skip in results",
              "example": 20
            },
            "limit": {
              "type": "integer",
              "definition": "Maximum number of rows to return",
              "example": 10
            },
            "orderBy": {
              "type": "string",
              "definition": "Order by field for results with direction",
              "example": "name desc"
            },
            "countAs": {
              "type": "string",
              "definition": "Json path to return total number of rows on event payload",
              "example": "total"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

[^1]: Returning all "versions" in result

[^2]: Returning single snapshot requested in "version" or "versionBase64" input payload

[^3]: Standard aggregate without version history


# Query Data

These actions provide ability to generate and execute system specific queries on a query manager on demand, from simple select statements to complex requests.

## Query Data Actions

### GetQuery

Executes and returns results for a single query from a specific query manager. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                   | Example    | Default |
| -------------- | ------------------------------------------------------------ | ---------- | ------- |
| Domain         | Name of the query manager to read data from                  | product    | -       |
| Input Element  | Json path for the input in event payload for query variables | parameters | -       |
| Output Element | Json path for the output in response event payload           | $.list     | -       |

{% endtab %}

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Query Data GetQuery action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the query manager to read data from",
          "example": "product"
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload for query variables",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "$.list"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                          | Example                                               | Default |
| -------------- | ------------------------------------------------------------------- | ----------------------------------------------------- | ------- |
| Output Pattern | JMESPath pattern to apply on data output, before returning response | {id:id, name:data.name, description:data.description} | -       |
| Query ID       | Id of the query to execute                                          | product\_search\_0001                                 | -       |
| Query Name     | Name of the query to execute                                        | Product Search                                        | -       |
| Query Json     | Full Json representation of query to execute                        | -                                                     | -       |
| First          | Whether to return first record only from results                    | true                                                  | false   |
| Sort Path      | Json path in query results to be used for sorting                   | product.id                                            | -       |
| Sorter Path    | Json path in request event payload to be used for sorting           | productids                                            | -       |
| {% endtab %}   |                                                                     |                                                       |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Query Data GetQuery action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": "{id:id, name:data.name, description:data.description}"
            },
            "queryId": {
              "type": "string",
              "definition": "Id of the query to execute",
              "example": "product_search_0001"
            },
            "queryName": {
              "type": "string",
              "definition": "Name of the query to execute",
              "example": "Product Search"
            },
            "queryJson": {
              "type": "object",
              "definition": "Full Json representation of query to execute"
            },
            "first": {
              "type": "boolean",
              "definition": "Whether to return first record only from results",
              "default": false
            },
            "sortPath": {
              "type": "string",
              "definition": "Json path in query results to be used for sorting",
              "example": "product.id"
            },
            "sorterPath": {
              "type": "string",
              "definition": "Json path in request event payload to be used for sorting",
              "example": "productids"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "search": "test"
    }
}
```

Event Metadata

![](/files/7oSM1jVAtjrFd93mWBGO)

</details>

{% hint style="info" %}
sortPath and sorterPath parameters are used to allow sorting of results by an already prioritized list of ids (such as product ids sorted based on search releavence).
{% endhint %}

### ProduceQuery

Generates a query statement for a specific query manager, which is typically used by 3rd party systems in converting query objects into system specific requests. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                   | Example    | Default |
| -------------- | ------------------------------------------------------------ | ---------- | ------- |
| Domain         | Name of the query manager to produce statement for           | product    | -       |
| Input Element  | Json path for the input in event payload for query variables | parameters | -       |
| Output Element | Json path for the output in response event payload           | $.query    | -       |
| {% endtab %}   |                                                              |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Query Data ProduceQuery action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the query manager to produce statement for",
          "example": "product"
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload for query variables",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "$.query"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                   | Example               | Default |
| ------------ | -------------------------------------------- | --------------------- | ------- |
| Query ID     | Id of the query to execute                   | product\_search\_0001 | -       |
| Query Name   | Name of the query to execute                 | Product Search        | -       |
| Query Json   | Full Json representation of query to execute | -                     | -       |
| {% endtab %} |                                              |                       |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Query Data ProduceQuery action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "queryId": {
              "type": "string",
              "definition": "Id of the query to execute",
              "example": "product_search_0001"
            },
            "queryJson": {
              "type": "object",
              "definition": "Full Json representation of query to execute"
            },
            "queryName": {
              "type": "string",
              "definition": "Name of the query to execute",
              "example": "Product Search"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Produced statement is returned as a "query" field of the outputElement.
{% endhint %}


# Apply Rules

These actions provide ability to evaluate a list of rules and returns results based on matches.

## Apply Rules Actions

### Process / ProcessSimpleRules

Evaluates list of rules for a domain and returns the result of matching rule. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                                                           | Example       | Default |
| -------------- | ---------------------------------------------------------------------------------------------------- | ------------- | ------- |
| Domain         | Set of rules to apply                                                                                | risk\_scoring | -       |
| Input Element  | Json path for the input in event payload for query variables                                         | parameters    | -       |
| Output Element | Json path for the output in response event payload where "result" or "results" element will be added | $.decision    | -       |
| {% endtab %}   |                                                                                                      |               |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "Set of rules to apply",
          "example": "risk_scoring"
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in event payload for query variables",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload where \"result\" or \"results\" element will be added",
          "example": "$.decision"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                                                                                          | Example                   | Default |
| ------------- | --------------------------------------------------------------------------------------------------- | ------------------------- | ------- |
| Input Pattern | JMESPath pattern to apply on data input                                                             | {id:id, group:data.group} | -       |
| Structure     | Whether the "result" of highest salience rule or "results" list of all matching rules should return | list                      | single  |
| {% endtab %}  |                                                                                                     |                           |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data input",
              "example": "{id:id, group:data.group}"
            },
            "structure": {
              "type": "string",
              "description": "Whether the \"result\" of highest salience rule or \"results\" list of all matching rules should return",
              "enum": ["single", "list"],
              "default": "single",
              "example": "list"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Call Rest API

These actions provide ability to make REST based calls to other internal or external services and return their results for API-based integrations.

## Call Rest API Actions

### CallRest

Makes a REST call and returns the result. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                                                | Example    | Default |
| -------------- | ----------------------------------------------------------------------------------------- | ---------- | ------- |
| Domain         | Name of the system to make REST call to (url and auth parameters of this system are used) | erp        | -       |
| Input Element  | Json path for the input in request event payload                                          | parameters | -       |
| Output Element | Json path for the output in response event payload                                        | $.product  | -       |
| {% endtab %}   |                                                                                           |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "Name of the system to make REST call to (url and auth parameters of this system are used)",
          "example": "erp"
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "$.product"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter       | Definition                                                                                                                                                 | Example                   | Default          |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- | ---------------- |
| Input Pattern   | JMESPath pattern to apply on data input                                                                                                                    | {id:parameters.productid} | -                |
| Output Pattern  | JMESPath pattern to apply on data output, before returning response                                                                                        | {id:id, stock:totalUnits} | -                |
| Url             | Url path on the target system for REST call                                                                                                                | GetInventory              | -                |
| Append Url Path | Payload element to add to the end of REST call url path                                                                                                    | parameters.language       | -                |
| Auth Path       | Payload element to use for auth.\* parameters of REST system                                                                                               | parameters.auth           | -                |
| Method          | Call method to use                                                                                                                                         | POST                      | GET              |
| Content Type    | Content type for REST calls (none, query, application/json, application/xml, text/xml, text/plain, multipart/form-data, application/x-www-form-urlencoded) | application/xml           | application/json |
| Headers         | Json string defining list of headers to add to the request                                                                                                 | {"content-encoding":"br"} | -                |
| Query.\*        | Query parameters to pass on the request URL                                                                                                                | language=en-US            | -                |
| {% endtab %}    |                                                                                                                                                            |                           |                  |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data input",
              "example": "{id:parameters.productid}"
            },
            "outputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data output, before returning response",
              "example": "{id:id, stock:totalUnits}"
            },
            "url": {
              "type": "string",
              "description": "Url path on the target system for REST call",
              "example": "GetInventory"
            },
            "urlPath": {
              "type": "string",
              "description": "Payload element to add to the end of REST call url path",
              "example": "parameters.language"
            },
            "authPath": {
              "type": "string",
              "description": "Payload element to use for auth.* parameters of REST system",
              "example": "parameters.auth"
            },
            "method": {
              "type": "string",
              "description": "Call method to use",
              "default": "GET",
              "example": "POST"
            },
            "contentType": {
              "type": "string",
              "description": "Content type for REST calls",
              "enum": [
                "none",
                "query",
                "application/json",
                "application/xml",
                "text/xml",
                "text/plain",
                "multipart/form-data",
                "application/x-www-form-urlencoded"
              ],
              "default": "application/json",
              "example": "application/xml"
            },
            "headers": {
              "type": "string",
              "description": "Json string defining list of headers to add to the request",
              "example": "{\"content-encoding\":\"br\"}"
            }
          },
          "patternProperties": {
            "^query\\..+$": {
              "type": "string",
              "description": "Query parameters to pass on the request URL (use keys like \"query.language\")",
              "example": "en-US"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "measures": "Population"
    }
}
```

Event Metadata

## ![](/files/ifjO0XtxzKTpcqmePAEL)

</details>

For contentType = "multipart/form-data", files can be added as fields using the following fields (all other fields are sent as text fields):

* **$type:** Should be set as "FILE"
* **body:** Text or JSON body to be sent as file contents
* **fileName:** File name to use for sending contents
* **mimeType:** Mime-type for the file contents

**Example:** {"$type": "FILE", "body": {test: true}, "fileName": "test.json"}

Depending on the response format, this handler returns the following data:

<table><thead><tr><th width="169">Format</th><th>Process</th></tr></thead><tbody><tr><td>json</td><td>Response is returned as is</td></tr><tr><td>xml</td><td>Response is converted to json format</td></tr><tr><td><a data-footnote-ref href="#user-content-fn-1">plain</a></td><td>Response is returned as {"text": [text]}</td></tr><tr><td><a data-footnote-ref href="#user-content-fn-1">html</a></td><td>Response is returned as {"html": [html]}</td></tr></tbody></table>

### ProduceRest

Produces rest call details without executing them for debugging purposes. Uses the same parameters as CallRest action.

## Commands

### RECONFIGURE

Reloads all REST target system properties, injecting connection and credential parameters with latest values. Typically used if the base URLs or API credentials change for the target system.

[^1]: since 0.5.2


# Generate Text/Html

These actions provide ability to produce text outputs using templates and input payload.

## Generate Text/Html Actions

### ApplyTemplate

Produces text (e.g. plain, html) from given input data and template id. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example  | Default |
| -------------- | -------------------------------------------------- | -------- | ------- |
| Input Element  | Json path for the input in request event payload   | customer | -       |
| Output Element | Json path for the output in response event payload | html     | -       |
| {% endtab %}   |                                                    |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "customer"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "html"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter        | Definition                                       | Example             | Default |
| ---------------- | ------------------------------------------------ | ------------------- | ------- |
| Template ID      | Id of the template to use from code.state        | landing\_page       | -       |
| Template ID Path | Json path of the template in event payload       | parameters.template | -       |
| Result Path      | Json path to add produced text on output element | output              | result  |
| {% endtab %}     |                                                  |                     |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "templateId": {
              "type": "string",
              "description": "Id of the template to use from code.state",
              "example": "landing_page"
            },
            "templateIdPath": {
              "type": "string",
              "description": "Json path of the template in event payload",
              "example": "parameters.template"
            },
            "resultPath": {
              "type": "string",
              "description": "Json path to add produced text on output element",
              "default": "result",
              "example": "output"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "course": "Rierino 101",
        "chapters": [
            {"name": "Introduction"}
        ] 
    }
}
```

Event Metadata

### ![](/files/zkMQRL71yiY2RX7zBLgq)

</details>

### ApplyTemplateList

Produces text from a given array of input data and template ids. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the input in request event payload   | list    | -       |
| Output Element | Json path for the output in response event payload | html    | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "list"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "html"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter        | Definition                                                    | Example | Default |
| ---------------- | ------------------------------------------------------------- | ------- | ------- |
| Output Structure | Structure of output to produce (map[^1], array[^2], text[^3]) | map     | -       |
| Output Delimiter | Delimiter for concatenating results if structure is "text"    | \n      | -       |
| Input Path       | Json path to get list of requests from                        | list    | input   |
| Result Path      | Json path to add produced text on output element              | output  | result  |
| {% endtab %}     |                                                               |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "structure": {
              "type": "string",
              "description": "Structure of output to produce (map, array, text)",
              "enum": ["map", "array", "text"],
              "example": "map"
            },
            "delimiter": {
              "type": "string",
              "description": "Delimiter for concatenating results if structure is \"text\"",
              "example": "\\n"
            },
            "inputPath": {
              "type": "string",
              "description": "Json path to get list of requests from",
              "default": "input",
              "example": "list"
            },
            "resultPath": {
              "type": "string",
              "description": "Json path to add produced text on output element",
              "default": "result",
              "example": "output"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

[^1]: {section:\[{templateId, result}]}

[^2]: \[{section, templateId, result}]

[^3]: Concatenated result text


# Parse Html

These actions provide ability to parse HTML documents and return their contents as structured JSON.

## Parse Html Actions

### ParseHtml

Produces JSON from given input html text or page url. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                                                       | Example | Default |
| -------------- | ------------------------------------------------------------------------------------------------ | ------- | ------- |
| Input Element  | Json path for the input in request event payload (should include "html" or "url" field)          | content | -       |
| Output Element | Json path for the output in response event payload (includes "elements" as the list of children) | parsed  | -       |
| {% endtab %}   |                                                                                                  |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload (should include \"html\" or \"url\" field)",
          "example": "content"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload (includes \"elements\" as the list of children)",
          "example": "parsed"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                            | Example   | Default |
| ------------ | ----------------------------------------------------- | --------- | ------- |
| XPath        | XPath expression to select elements from document     | -         | -       |
| CSS Query    | CSS query expression to select elements from document | #products | -       |
| {% endtab %} |                                                       |           |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "xpath": {
              "type": "string",
              "description": "XPath expression to select elements from document"
            },
            "cssQuery": {
              "type": "string",
              "description": "CSS query expression to select elements from document",
              "example": "#products"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Generate Secrets

These actions provide ability to encrypt, decrypt and hash data, as well as validate and generate tokens and certificates.

## Generate Secrets Actions

All actions of this handler share the following event metadata parameters for getting key inputs:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                | Example        | Default |
| ------------ | ----------------------------------------- | -------------- | ------- |
| Key          | Constant key to use for operations        | 1234567890ABC  | -       |
| Key Path     | Json path of key in event payload         | parameters.key | -       |
| Key Id       | ID of the key to use from key state       | 123            | -       |
| Key Id Path  | Json path of key id to use from key state | parameters.id  | -       |
| {% endtab %} |                                           |                |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "key": {
              "type": "string",
              "description": "Constant key to use for operations",
              "example": "1234567890ABC"
            },
            "keyPath": {
              "type": "string",
              "description": "Json path of key in event payload",
              "example": "parameters.key"
            },
            "keyId": {
              "type": ["string", "integer"],
              "description": "ID of the key to use from key state",
              "example": 123
            },
            "keyIdPath": {
              "type": "string",
              "description": "Json path of key id to use from key state",
              "example": "parameters.id"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Encrypt

Encrypts a given json node or string value using preferred algorithms. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the input in request event payload   | data    | -       |
| Output Element | Json path for the output in response event payload | secret  | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "data"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "secret"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                        | Example | Default         |
| ------------- | --------------------------------- | ------- | --------------- |
| Algorithm     | Custom cipher algorithm to use    | -       | Handler default |
| Key Algorithm | Custom SecretKey algorithm to use | -       | Handler default |
| Provider      | Custom security provider to use   | -       | Handler default |
| {% endtab %}  |                                   |         |                 |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "algorithm": {
              "type": "string",
              "description": "Custom cipher algorithm to use",
              "default": "Handler default"
            },
            "keyAlgorithm": {
              "type": "string",
              "description": "Custom SecretKey algorithm to use",
              "default": "Handler default"
            },
            "provider": {
              "type": "string",
              "description": "Custom security provider to use",
              "default": "Handler default"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Decrypt

Decryptes a previously encrypted value and returns as a json node or string value. This action uses the same fields as Encrypt action, with the addition of following event metadata parameter:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                                          | Example | Default |
| ------------ | ------------------------------------------------------------------- | ------- | ------- |
| Is Json      | Whether encrypted value is json and should be parsed into an object | true    | false   |
| {% endtab %} |                                                                     |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "isJson": {
              "type": "boolean",
              "description": "Whether encrypted value is json and should be parsed into an object",
              "default": false,
              "example": true
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Hash

Hashes a given json node or string value using preferred algorithms. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the input in request event payload   | data    | -       |
| Output Element | Json path for the output in response event payload | secret  | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "data"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "secret"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                      | Example | Default         |
| ------------ | ------------------------------- | ------- | --------------- |
| Algorithm    | Custom hash algorithm to use    | -       | Handler default |
| Provider     | Custom security provider to use | -       | Handler default |
| Iterations   | Iterations to update the hash   | 100     | 1               |
| {% endtab %} |                                 |         |                 |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "algorithm": {
              "type": "string",
              "description": "Custom hash algorithm to use",
              "default": "Handler default"
            },
            "provider": {
              "type": "string",
              "description": "Custom security provider to use",
              "default": "Handler default"
            },
            "iterations": {
              "type": "integer",
              "description": "Iterations to update the hash",
              "default": 1,
              "example": 100
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Hash actions can be used to generate secure API keys, when used together with JmesPath salt\_key action that creates secure random key. These keys can be stored with access.roles details for key based authentication.
{% endhint %}

### ValidateHash

Validates the hash of a given json node or string value using preferred algorithms. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                                        | Example    | Default |
| -------------- | --------------------------------------------------------------------------------- | ---------- | ------- |
| Input Element  | Json path for the input in request event payload, with "hash" and "data" elements | parameters | -       |
| Output Element | Json path for the output in response event payload                                | secret     | -       |
| {% endtab %}   |                                                                                   |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload, with \"hash\" and \"data\" elements",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "secret"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                      | Example | Default         |
| ------------ | ------------------------------- | ------- | --------------- |
| Algorithm    | Custom hash algorithm to use    | -       | Handler default |
| Provider     | Custom security provider to use | -       | Handler default |
| Iterations   | Iterations to update the hash   | 100     | 1               |
| {% endtab %} |                                 |         |                 |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "algorithm": {
              "type": "string",
              "description": "Custom hash algorithm to use",
              "default": "Handler default"
            },
            "provider": {
              "type": "string",
              "description": "Custom security provider to use",
              "default": "Handler default"
            },
            "iterations": {
              "type": "integer",
              "description": "Iterations to update the hash",
              "default": 1,
              "example": 100
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### GenerateToken

Generates a JWT token for given claims (including special claims such as audience). Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                             | Example    | Default |
| -------------- | ------------------------------------------------------ | ---------- | ------- |
| Input Element  | Json path for the fields to include as claims in token | parameters | -       |
| Output Element | Json path to add token at                              | secret     | -       |
| {% endtab %}   |                                                        |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the fields to include as claims in token",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path to add token at",
          "example": "secret"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter       | Definition                          | Example | Default         |
| --------------- | ----------------------------------- | ------- | --------------- |
| Provider        | Custom security provider to use     | -       | Handler default |
| Expiration Time | Milliseconds to expiration of token | 60000   | 0               |
| {% endtab %}    |                                     |         |                 |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "provider": {
              "type": "string",
              "description": "Custom security provider to use",
              "default": "Handler default"
            },
            "expirationTime": {
              "type": "integer",
              "description": "Milliseconds to expiration of token",
              "default": 0,
              "example": 60000
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### ValidateToken

Validates a JWT token. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                            | Example          | Default |
| -------------- | ------------------------------------- | ---------------- | ------- |
| Input Element  | Json path for the token               | parameters.token | -       |
| Output Element | Json path to add validation result to | isValid          | -       |
| {% endtab %}   |                                       |                  |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the token",
          "example": "parameters.token"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path to add validation result to",
          "example": "isValid"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                                    | Example | Default         |
| ------------- | --------------------------------------------- | ------- | --------------- |
| Provider      | Custom security provider to use               | -       | Handler default |
| Input Pattern | Jmespath expression to apply on input element | -       | -               |
| {% endtab %}  |                                               |         |                 |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "provider": {
              "type": "string",
              "description": "Custom security provider to use",
              "default": "Handler default"
            },
            "inputPattern": {
              "type": "string",
              "description": "Jmespath expression to apply on input element"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### DecodeToken

Decodes a JWT token and returns its claims. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                         | Example          | Default |
| -------------- | ---------------------------------- | ---------------- | ------- |
| Input Element  | Json path for the token            | parameters.token | -       |
| Output Element | Json path to add decoded claims to | claims           | -       |
| {% endtab %}   |                                    |                  |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the token",
          "example": "parameters.token"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path to add decoded claims to",
          "example": "claims"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                                    | Example | Default         |
| ------------- | --------------------------------------------- | ------- | --------------- |
| Provider      | Custom security provider to use               | -       | Handler default |
| Input Pattern | Jmespath expression to apply on input element | -       | -               |
| Validate      | Whether the token must be valid to decode     | false   | true            |
| {% endtab %}  |                                               |         |                 |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "provider": {
              "type": "string",
              "description": "Custom security provider to use",
              "default": "Handler default"
            },
            "inputPattern": {
              "type": "string",
              "description": "Jmespath expression to apply on input element"
            },
            "validate": {
              "type": "boolean",
              "description": "Whether the token must be valid to decode",
              "default": true,
              "example": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### GenerateCertificate

Generates a certificate, returning private key and public certificate values. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                          | Example         | Default |
| -------------- | --------------------------------------------------- | --------------- | ------- |
| Input Element  | Json path for custom certificate DN and lifetime    | parameters.cert | -       |
| Output Element | Json path to add "key" and "certificate" outputs to | produced        | -       |
| {% endtab %}   |                                                     |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for custom certificate DN and lifetime",
          "example": "parameters.cert"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path to add \"key\" and \"certificate\" outputs to",
          "example": "produced"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter                      | Definition                          | Example | Default         |
| ------------------------------ | ----------------------------------- | ------- | --------------- |
| Provider                       | Custom security provider to use     | -       | Handler default |
| Certificate Algorithm          | Custom certificate algorithm        | -       | Handler default |
| Certificate SignatureAlgorithm | Custom signature algorithm          | -       | Handler default |
| Certificate Key Size           | Custom key size                     | -       | Handler default |
| Certificate DN                 | Custom certificate DN               | -       | Handler default |
| Certificate Life Time          | Custom certificate lifetime in days | -       | Handler default |
| {% endtab %}                   |                                     |         |                 |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "provider": {
              "type": "string",
              "description": "Custom security provider to use",
              "default": "Handler default"
            },
            "certificateAlgorithm": {
              "type": "string",
              "description": "Custom certificate algorithm",
              "default": "Handler default"
            },
            "certificateSignatureAlgorithm": {
              "type": "string",
              "description": "Custom signature algorithm",
              "default": "Handler default"
            },
            "certificateKeySize": {
              "type": ["integer", "string"],
              "description": "Custom key size",
              "default": "Handler default"
            },
            "certificateDN": {
              "type": "string",
              "description": "Custom certificate DN",
              "default": "Handler default"
            },
            "certificateLifeTime": {
              "type": ["integer", "string"],
              "description": "Custom certificate lifetime in days",
              "default": "Handler default"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Orchestrate User Task

These actions provide ability to include human actions and time delays in API calls.

## Orchestrate User Task Actions

### StartTask

Records current event as a process entry assigned to a user or group, to proceed after a trigger or timeout after given time. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                                                 | Example      | Default |
| ------------- | ---------------------------------------------------------- | ------------ | ------- |
| Domain        | Name of the state manager to store process data in         | workflow     | -       |
| Input Element | Json path for storing data to return on proceeding process | process.data | -       |
| {% endtab %}  |                                                            |              |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "Name of the state manager to store process data in",
          "example": "workflow"
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for storing data to return on proceeding process",
          "example": "process.data"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                                                                   | Example              | Default |
| ------------- | ---------------------------------------------------------------------------- | -------------------- | ------- |
| Input Pattern | JMESPath pattern to apply on data input                                      | {data: process.data} | -       |
| Task Id Path  | [Json path which defines id for storing the process](#user-content-fn-1)[^1] | process.id           | taskId  |
| Task Name     | Descriptive name for the task                                                | Job Post Approval    | -       |
| Task Spec     | Task specification (i.e. reference name for the process flow)                | job\_post\_approval  | -       |
| Task Action   | Referential name of the action                                               | Approve              | -       |
| Task Roles    | Comma separated list of user roles allowed to process task                   | admin,manager        | -       |
| Task User     | ID of user allowed to process task                                           | user123              | -       |
| Timeout       | Milliseconds to timeout started process after                                | 60000                | -       |
| Timeout On    | Epoch time in ms to timeout started process on                               | 1666765654           | -       |
| {% endtab %}  |                                                                              |                      |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data input",
              "example": "{data: process.data}"
            },
            "taskIdPath": {
              "type": "string",
              "description": "Json path which defines id for storing the process",
              "default": "taskId",
              "example": "process.id"
            },
            "taskName": {
              "type": "string",
              "description": "Descriptive name for the task",
              "example": "Job Post Approval"
            },
            "taskSpec": {
              "type": "string",
              "description": "Task specification (i.e. reference name for the process flow)",
              "example": "job_post_approval"
            },
            "taskAction": {
              "type": "string",
              "description": "Referential name of the action",
              "example": "Approve"
            },
            "taskRoles": {
              "type": "string",
              "description": "Comma separated list of user roles allowed to process task",
              "example": "admin,manager"
            },
            "taskUser": {
              "type": "string",
              "description": "ID of user allowed to process task",
              "example": "user123"
            },
            "timeout": {
              "type": "integer",
              "description": "Milliseconds to timeout started process after",
              "example": 60000
            },
            "timeoutOn": {
              "type": "integer",
              "description": "Epoch time in ms to timeout started process on",
              "example": 1666765654
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "productId": "product-1",
        "brief": "Image and video creation with summer vibes" 
    }
}
```

Event Metadata

### ![](/files/bCDCTU50W4dUxdRW2d5M)

</details>

{% hint style="info" %}
StartTask action can be followed with an event status condition step in sagas, for escalation of tasks not completed in timeout duration. The "TIMEOUT" condition value can be used for such flows.
{% endhint %}

### ProceedTask

Triggers proceeding of an existing process entry, enriching with stored event data. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Domain         | Name of the state manager keeping process data     | workflow   | -       |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | process    | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "Name of the state manager keeping process data",
          "example": "workflow"
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "process"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                                 | Example           | Default                                      |
| -------------- | -------------------------------------------------------------------------- | ----------------- | -------------------------------------------- |
| Input Pattern  | JMESPath pattern to apply on data input                                    | {data: newData}   | -                                            |
| Output Pattern | JMESPath pattern to apply on enrich data output, before returning response | {stored: oldData} | -                                            |
| Task Id Path   | Json path which defines id for proceeding the process                      | id                | \[requestId]:\[sagaStepId]\[runnerPartition] |
| Enrich Path    | Json path to use for enriching proceeded process event data                | newData           | -                                            |
| {% endtab %}   |                                                                            |                   |                                              |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data input",
              "example": "{data: newData}"
            },
            "outputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on enrich data output, before returning response",
              "example": "{stored: oldData}"
            },
            "taskIdPath": {
              "type": "string",
              "description": "Json path which defines id for proceeding the process",
              "default": "[requestId]:[sagaStepId][runnerPartition]",
              "example": "id"
            },
            "enrichPath": {
              "type": "string",
              "description": "Json path to use for enriching proceeded process event data",
              "example": "newData"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Typically a global, generic /ProceedTask endpoint is used for triggering progression of tasks assigned to users across all sagas.

However, it is typically preferred to have the ProceedTask action running on the same runner performing StartTask sagas, as they typically need to have access to the same state managers (e.g. approval states).
{% endhint %}

### TimeoutTask

Triggers timeout of an already started process, enriching with input event data. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Domain         | Name of the state manager keeping process data     | workflow   | -       |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | process    | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "Name of the state manager keeping process data",
          "example": "workflow"
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "example": "process"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                                 | Example           | Default                                      |
| -------------- | -------------------------------------------------------------------------- | ----------------- | -------------------------------------------- |
| Input Pattern  | JMESPath pattern to apply on data input                                    | {data: newData}   | -                                            |
| Output Pattern | JMESPath pattern to apply on enrich data output, before returning response | {stored: oldData} | -                                            |
| Task Id Path   | Json path which defines id for timed out process                           | id                | \[requestId]:\[sagaStepId]\[runnerPartition] |
| Enrich Path    | Json path to use for enriching timed out process event data                | newData           | -                                            |
| {% endtab %}   |                                                                            |                   |                                              |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data input",
              "example": "{data: newData}"
            },
            "outputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on enrich data output, before returning response",
              "example": "{stored: oldData}"
            },
            "taskIdPath": {
              "type": "string",
              "description": "Json path which defines id for timed out process",
              "default": "[requestId]:[sagaStepId][runnerPartition]",
              "example": "id"
            },
            "enrichPath": {
              "type": "string",
              "description": "Json path to use for enriching timed out process event data",
              "example": "newData"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Tasks that are created with StartTask automatically timeout based on their parameter values. This task provides an extra facility to timeout records manually.
{% endhint %}

### TimeoutBetween

Triggers timeout of all processes with timeout time within the given range. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                                       | Example    | Default |
| ------------- | ------------------------------------------------ | ---------- | ------- |
| Input Element | Json path for the input in request event payload | parameters | -       |
| {% endtab %}  |                                                  |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "example": "parameters"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                 | Example | Default      |
| -------------- | ---------------------------------------------------------- | ------- | ------------ |
| From Time Path | Json path for "from time" of timeouts                      | start   | Last timeout |
| To Time Path   | Json path for "to time" of timeouts (updates last timeout) | end     | -            |
| {% endtab %}   |                                                            |         |              |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "fromTimePath": {
              "type": "string",
              "description": "Json path for \"from time\" of timeouts",
              "default": "Last timeout",
              "example": "start"
            },
            "toTimePath": {
              "type": "string",
              "description": "Json path for \"to time\" of timeouts (updates last timeout)",
              "example": "end"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

[^1]: If given path is null, \[requestId]:\[sagaStepId]\[runnerPartition] is used


# Perform File Operation

These actions provide ability to interact with local and remote file systems for directory and file operations.

## Perform File Operation Actions

### MakeDir

Creates a new directory in given file system. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                     | Example | Default |
| ------------ | ------------------------------ | ------- | ------- |
| Domain       | Name of the file system to use | imageFs | -       |
| {% endtab %} |                                |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "MakeDir action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the file system to use",
          "example": "imageFs"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                        | Example  | Default |
| ------------ | ------------------------------------------------- | -------- | ------- |
| Path Path    | Json path in payload for directory path to create | filePath | path    |
| {% endtab %} |                                                   |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "MakeDir action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "pathPath": {
              "type": "string",
              "definition": "Json path in payload for directory path to create",
              "default": "path",
              "example": "filePath"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### List / ListPath

Lists files and directories for given path. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                     | Example | Default |
| ------------ | ------------------------------ | ------- | ------- |
| Domain       | Name of the file system to use | imageFs | -       |
| {% endtab %} |                                |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "List action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the file system to use",
          "example": "imageFs"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                      | Example  | Default |
| ------------ | ----------------------------------------------- | -------- | ------- |
| Path Path    | Json path in payload for directory path to list | filePath | path    |
| {% endtab %} |                                                 |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "List action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "pathPath": {
              "type": "string",
              "definition": "Json path in payload for directory path to list",
              "default": "path",
              "example": "filePath"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Delete / DeletePath

Deletes a file or directory in given file system. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                     | Example | Default |
| ------------ | ------------------------------ | ------- | ------- |
| Domain       | Name of the file system to use | imageFs | -       |
| {% endtab %} |                                |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Delete action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the file system to use",
          "example": "imageFs"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                             | Example  | Default |
| ------------ | ------------------------------------------------------ | -------- | ------- |
| Path Path    | Json path in payload for file/directory path to delete | filePath | path    |
| Recursive    | Whether deletion should include sub-directories        | true     | false   |
| {% endtab %} |                                                        |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Delete action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "pathPath": {
              "type": "string",
              "definition": "Json path in payload for file/directory path to delete",
              "default": "path",
              "example": "filePath"
            },
            "recursive": {
              "type": "boolean",
              "definition": "Whether deletion should include sub-directories",
              "default": false,
              "example": true
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Rename / RenamePath

Renames a file or directory in given file system. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                     | Example | Default |
| ------------ | ------------------------------ | ------- | ------- |
| Domain       | Name of the file system to use | imageFs | -       |
| {% endtab %} |                                |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Rename action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the file system to use",
          "example": "imageFs"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                        | Example  | Default |
| ------------ | ------------------------------------------------- | -------- | ------- |
| Path Path    | Json path in payload for file/directory to rename | filePath | path    |
| To Path      | Json path in payload for new file/directory name  | newPath  | to      |
| {% endtab %} |                                                   |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Rename action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "pathPath": {
              "type": "string",
              "definition": "Json path in payload for file/directory to rename",
              "default": "path",
              "example": "filePath"
            },
            "toPath": {
              "type": "string",
              "definition": "Json path in payload for new file/directory name",
              "default": "to",
              "example": "newPath"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### CopyFile

Copies or moves a file from one file system to another. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                            | Example | Default |
| ------------ | ------------------------------------- | ------- | ------- |
| Domain       | Name of the source file system to use | imageFs | -       |
| {% endtab %} |                                       |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "CopyFile action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the source file system to use",
          "example": "imageFs"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                      | Example  | Default |
| ------------ | ----------------------------------------------- | -------- | ------- |
| target       | Name of the target file system                  | cdnFs    | -       |
| Path Path    | Json path in payload for file/directory to copy | filePath | path    |
| To Path      | Json path in payload for target file/directory  | newPath  | to      |
| Move         | Whether file should be deleted from the source  | true     | false   |
| {% endtab %} |                                                 |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "CopyFile action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "target": {
              "type": "string",
              "definition": "Name of the target file system",
              "example": "cdnFs"
            },
            "pathPath": {
              "type": "string",
              "definition": "Json path in payload for file/directory to copy",
              "default": "path",
              "example": "filePath"
            },
            "toPath": {
              "type": "string",
              "definition": "Json path in payload for target file/directory",
              "default": "to",
              "example": "newPath"
            },
            "move": {
              "type": "boolean",
              "definition": "Whether file should be deleted from the source",
              "default": false,
              "example": true
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Write / WriteFile

Writes contents to a single file or a set of files for a given file system:

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                          | Example    | Default |
| ------------ | ----------------------------------- | ---------- | ------- |
| Domain       | Name of the file system to write to | dataLakeFs | -       |
| {% endtab %} |                                     |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Write action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the file system to write to",
          "example": "dataLakeFs"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                                                                               | Example        | Default |
| ------------ | -------------------------------------------------------------------------------------------------------- | -------------- | ------- |
| Path Path    | Json path in payload for directory path to list (from payload root)                                      | parameters.id  | path    |
| Mode         | Type of file(s) to output (sequence[^1], single[^2])                                                     | sequence       | single  |
| Prefix       | Prefix to add to each file's name (for sequence mode output)                                             | tracking/views | -       |
| Suffix       | Suffix to add to each file's name (for sequence mode output)                                             | \_out.json     | -       |
| Content      | Event contents to write to file (for sequence mode, event[^3], request[^4] or payload[^5])               | request        | payload |
| Overwrite    | Whether to overwrite or append contents to output (for single mode output)                               | true           | false   |
| Base64       | Whether the input should be treated as base64 text and decoded for generating the file (e.g. image, PDF) | true           | false   |
| {% endtab %} |                                                                                                          |                |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Write action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "pathPath": {
              "type": "string",
              "definition": "Json path in payload for directory path to list (from payload root)",
              "default": "path",
              "example": "parameters.id"
            },
            "mode": {
              "type": "string",
              "definition": "Type of file(s) to output (sequence, single)",
              "enum": [
                "sequence",
                "single"
              ],
              "default": "single",
              "example": "sequence"
            },
            "prefix": {
              "type": "string",
              "definition": "Prefix to add to each file's name (for sequence mode output)",
              "example": "tracking/views"
            },
            "suffix": {
              "type": "string",
              "definition": "Suffix to add to each file's name (for sequence mode output)",
              "example": "_out.json"
            },
            "content": {
              "type": "string",
              "definition": "Event contents to write to file (for sequence mode, event, request or payload)",
              "enum": [
                "event",
                "request",
                "payload"
              ],
              "default": "payload",
              "example": "request"
            },
            "overwrite": {
              "type": "boolean",
              "definition": "Whether to overwrite or append contents to output (for single mode output)",
              "default": false,
              "example": true
            },
            "base64": {
              "type": "boolean",
              "definition": "Whether the input should be treated as base64 text and decoded for generating the file (e.g. image, PDF)",
              "default": false,
              "example": true
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "customerId": "customer-1",
    "productId": "product-1",
    "pageId": "product-detail"
}
```

Event Metadata

![](/files/QzVcuz9FSi8Qyb8CD5hM)

</details>

For sequence output mode, this handler uses a path writer, which is responsible for generating unique sequence file paths/names for wrting contents to. The writer can be configured by adding path.\* parameters to file system definition.

{% hint style="info" %}
Using "\[uuid]" in prefix or suffix allows generation of globally unique paths and file names, as this entry is replaced with a UUID value generated.
{% endhint %}

### Read / ReadFile

Reads and returns contents of a file (in a cachable manner):

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                           | Example    | Default |
| ------------ | ------------------------------------ | ---------- | ------- |
| Domain       | Name of the file system to read from | contentsFs | -       |
| {% endtab %} |                                      |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the file system to read from",
          "example": "contentsFs"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                          | Example | Default |
| ------------ | --------------------------------------------------- | ------- | ------- |
| Path Path    | Json path in payload for directory path to list     | id      | path    |
| Format       | Format of the file contents to retrieve (json,text) | json    | text    |
| {% endtab %} |                                                     |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Read action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "pathPath": {
              "type": "string",
              "definition": "Json path in payload for directory path to list",
              "default": "path",
              "example": "id"
            },
            "format": {
              "type": "string",
              "definition": "Format of the file contents to retrieve (json, text)",
              "enum": [
                "json",
                "text"
              ],
              "default": "text",
              "example": "json"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

[^1]: Series of files (mostly used for data lakes)

[^2]: Single file

[^3]: Full event contents including metadata

[^4]: Event payload and request metadata

[^5]: Input payload with input pattern applied


# Run Shell Command

These actions provide ability to execute shell commands.

## Run Shell Command Actions

### CallShell

Executes given shell command. Event metadata parameters applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                                        | Example | Default |
| ------------ | ----------------------------------------------------------------- | ------- | ------- |
| Command      | Main command to execute                                           | ls      | -       |
| Track        | Whether status updates should be recorded in process state or not | true    | false   |
| Parameters   | Arguments to add                                                  | -       | -       |
| {% endtab %} |                                                                   |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "CallShell action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "command": {
              "type": "string",
              "definition": "Main command to execute",
              "example": "ls"
            },
            "track": {
              "type": "boolean",
              "definition": "Whether status updates should be recorded in process state or not",
              "default": false,
              "example": true
            }
          },
          "patternProperties": {
            "^param_\\\\[\\\\d+\\\\]_arg$": {
              "type": "string",
              "definition": "Name of the ith argument to add",
              "example": "--dir"
            },
            "^param_\\\\[\\\\d+\\\\]_value$": {
              "type": "string",
              "definition": "Value of the ith argument to add",
              "example": "/tmp"
            },
            "^param_\\\\[\\\\d+\\\\]_path$": {
              "type": "string",
              "definition": "Path from input payload for ith argument",
              "example": "parameters.dir"
            },
            "^param_\\\\[\\\\d+\\\\]_asText$": {
              "type": "boolean",
              "definition": "Whether payload value should be added as text",
              "default": false,
              "example": true
            },
            "^param_\\\\[\\\\d+\\\\]_repeat$": {
              "type": "boolean",
              "definition": "Whether array or object payload values should repeat argument",
              "default": false,
              "example": true
            },
            "^param_\\\\[\\\\d+\\\\]_delimiter$": {
              "type": "string",
              "definition": "Delimiter to put between array or object payload values if argument won't be repeated",
              "example": ","
            },
            "^param_\\\\[\\\\d+\\\\]_separator$": {
              "type": "string",
              "definition": "Separator to put between argument and object values if argument will be repeated",
              "example": "="
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Send/Receive Emails

These actions provide ability to send and receive emails using existing email servers.

## Send/Receive Emails Actions

### SendEmail

Sends an email using the configured email server. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                                       | Example    | Default |
| ------------- | ------------------------------------------------ | ---------- | ------- |
| Input Element | Json path for the input in request event payload | parameters | -       |
| {% endtab %}  |                                                  |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "SendEmail action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                              | Example                                                                                                                    | Default |
| ------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------- |
| Input Pattern | JMESPath pattern to apply on data input | {"from": from, "replyTo": replyTo, "to": to, "cc": cc, "subject": subject, "charset": charset, "text": text, "html": html} | -       |
| {% endtab %}  |                                         |                                                                                                                            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "SendEmail action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data input",
              "example": "{\"from\": from, \"replyTo\": replyTo, \"to\": to, \"cc\": cc, \"subject\": subject, \"charset\": charset, \"text\": text, \"html\": html}"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### ReceiveEmail

Receives details of a specific email with given UID using the configured email server. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | result     | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "ReceiveEmail action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters"
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "result"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                          | Example | Default |
| -------------- | ------------------------------------------------------------------- | ------- | ------- |
| ID Path        | Json path for the id field in input element                         | mail.id | id      |
| No Content     | Whether to discard email content details                            | true    | false   |
| Output Pattern | JMESPath pattern to apply on data output, before returning response | -       | -       |
| {% endtab %}   |                                                                     |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "ReceiveEmail action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "idPath": {
              "type": "string",
              "definition": "Json path for the id field in input element",
              "default": "id",
              "example": "mail.id"
            },
            "noContent": {
              "type": "boolean",
              "definition": "Whether to discard email content details",
              "default": false,
              "example": true
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Flow Actions

Flow actions provide ability to combine and orchestrate various actions.


# Orchestrate Saga

These actions provide ability to coordinate end-to-end API calls, locally executing or distributing microservice steps across the platform.

## Orchestrate Saga Actions

### StartSaga

Initiates execution of a new saga, using `sagaPath` or `sagaId` parameter of the requesting event, or the request metadata path if not defined. The request is accepted only if there is an active saga matching this path.

When called from within another saga, following event metadata fields are applicable for this action:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | result     | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "result",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With the following event metadata parameters:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                                                      | Example         | Default |
| -------------- | ----------------------------------------------------------------------------------------------- | --------------- | ------- |
| Saga           | ID of the saga to call                                                                          | list\_customers | -       |
| Saga Path      | Path of the saga to call                                                                        | /ListCustomers  |         |
| Fire Forget    | Whether specific call to saga should work async (in case saga itself is not configured as such) | true            | false   |
| Input Pattern  | JMESPath pattern to apply on data input                                                         | -               | -       |
| Output Pattern | JMESPath pattern to apply on data output, before returning response                             | -               | -       |
| {% endtab %}   |                                                                                                 |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "sagaId": {
              "type": "string",
              "definition": "ID of the saga to call",
              "example": "list_customers",
              "default": null
            },
            "sagaPath": {
              "type": "string",
              "definition": "Path of the saga to call",
              "example": "/ListCustomers",
              "default": null
            },
            "fireForget": {
              "type": "string",
              "definition": "Whether specific call to saga should work async (in case saga itself is not configured as such)",
              "default": "false"
            },
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data input",
              "example": null,
              "default": null
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": null,
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Nested sagas should only be used within the same runner as they do not replicate original event payload and metadata during execution for stateless distribution.
{% endhint %}

### StepSaga

Executes the next action after a saga step is completed by an event runner, using the saga id and step id in event saga metadata.

{% hint style="info" %}
Unlike the other event handlers, SagaEventHandler is rarely called from within saga flows, as it acts as a coordinator rather than a simple task executor.
{% endhint %}


# Execute Predefined Actions

These actions provide ability to execute predefined reusable actions as saga steps.

## Execute Predefined Actions

### TakeAction

Calls a predefined action using given parameters and event payload. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | result     | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "result",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With the following event metadata parameters:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                                          | Example         | Default |
| -------------- | ----------------------------------------------------------------------------------- | --------------- | ------- |
| Action         | ID of the action to call                                                            | list\_customers | -       |
| Input Pattern  | JMESPath pattern to apply on data input                                             | -               | -       |
| Output Pattern | JMESPath pattern to apply on data output, before returning response                 | -               | -       |
| \*             | Any parameter to replace in action configuration mapping to %%param\_\*%% variables | domain=test     | -       |
| {% endtab %}   |                                                                                     |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "action": {
              "type": "string",
              "definition": "ID of the action to call",
              "example": "list_customers",
              "default": null
            },
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data input",
              "example": null,
              "default": null
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": null,
              "default": null
            },
            "*": {
              "type": "string",
              "definition": "Any parameter to replace in action configuration mapping to %%param_*%% variables",
              "example": "domain=test",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Loop Each Entry

These actions provide ability to repeat an action for each entry in a specific payload element.

## Loop Each Entry Actions

### RunEach

Repeats an action multiple times, each with an assigned part of the payload. Event metadata parameters applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                                                         | Example                                              | Default |
| ------------ | ---------------------------------------------------------------------------------- | ---------------------------------------------------- | ------- |
| For Each     | Json path in payload to array entries for repetition                               | parameters.productids                                | list    |
| Parallel     | Whether actions should run in parallel or not                                      | true                                                 | false   |
| As           | Field name to set results from each action                                         | output                                               | \_      |
| Inner Fields | Event metadata fields for each action execution (e.g. action, handler, parameters) | <p>action=CallRest</p><p>parameters.url=/product</p> | -       |
| {% endtab %} |                                                                                    |                                                      |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "forEach": {
              "type": "string",
              "definition": "Json path in payload to array entries for repetition",
              "example": "parameters.productids",
              "default": "list"
            },
            "parallel": {
              "type": "boolean",
              "definition": "Whether actions should run in parallel or not",
              "example": true,
              "default": false
            },
            "as": {
              "type": "string",
              "definition": "Field name to set results from each action",
              "example": "output",
              "default": "_"
            },
            "inner_[field]": {
              "type": "string",
              "definition": "Event metadata fields for each action execution (e.g. action, handler, parameters)",
              "example": "action=CallRest\\nparameters.url=/product",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "translations": ['enUS', 'deDE', 'frFR'],
    "text": "Hello World"
}
```

Event Metadata

![](/files/2UrZ0O3izzWXSoRdT4q2)

</details>


# Run Multiple Steps

These actions provide ability to execute sequential actions using different event handlers at once.

## Run Multiple Steps Actions

### RunSteps

Runs multiple steps sequentially and passes each one's result to the next. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                                                | Example    | Default |
| -------------- | ----------------------------------------------------------------------------------------- | ---------- | ------- |
| Domain         | Name of the system to make REST call to (url and auth parameters of this system are used) | erp        | -       |
| Input Element  | Json path for the input in request event payload                                          | parameters | -       |
| Output Element | Json path for the output in response event payload                                        | product    | -       |
| {% endtab %}   |                                                                                           |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the system to make REST call to (url and auth parameters of this system are used)",
          "example": "erp",
          "default": null
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "product",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                                       | Example                   | Default |
| ------------- | ------------------------------------------------ | ------------------------- | ------- |
| Common Fields | Event metadata fields applicable for all steps   | inputElement=parameters   | -       |
| Step Action   | Name of the action to run for step \[step]       | GetQuery                  | -       |
| Step Fields   | Event metadata field applicable for step \[step] | {id:parameters.productid} | -       |
| {% endtab %}  |                                                  |                           |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "common.[field]": {
              "type": "string",
              "definition": "Event metadata fields applicable for all steps",
              "example": "inputElement=parameters",
              "default": null
            },
            "step_[step]_action": {
              "type": "string",
              "definition": "Name of the action to run for step [step]",
              "example": "GetQuery",
              "default": null
            },
            "step_[step].[field]": {
              "type": "string",
              "definition": "Event metadata field applicable for step [step]",
              "example": "{id:parameters.productid}",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "language": "enUS"
    },
    "facets":{
        "brands": ["brand-1"],
        "categories": ["cat-1"]
    }

}
```

Event Metadata

![](/files/seejAgFJICIuMjae8fr3)

</details>

{% hint style="info" %}
Common event metadata fields are used as default and merged with step specific metadata fields such as inputElement, handler or parameters.
{% endhint %}


# Buffer Payloads

These actions provide ability to buffer multiple event payloads into a single batch event.

## Buffer Payloads Actions

### Buffer

Buffers payload of the events received and releases them as a single combined event with array of input payloads in either of the following cases:

* When the runner performs a commit operation, based on its settings or a commit command received.
* When the number of buffered events reaches the buffer size provided in event parameters.

Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                            | Example    | Default |
| -------------- | ----------------------------------------------------- | ---------- | ------- |
| Input Element  | Json path for payload element to buffer               | parameters | -       |
| Output Element | Json path for payload element to output buffered data | batch      | -       |
| {% endtab %}   |                                                       |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for payload element to buffer",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for payload element to output buffered data",
          "example": "batch",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                  | Example           | Default |
| -------------- | ----------------------------------------------------------- | ----------------- | ------- |
| Input Pattern  | JMES path for transforming input element                    | {"id": productid} | -       |
| Output Pattern | JMES path for transforming buffered data, which is an array | @\[?id>0]         | -       |
| Buffer ID      | Unique id for buffering similar payloads together           | product\_ids      | -       |
| Buffer Size    | Max number of records to buffer                             | 10                | -       |
| {% endtab %}   |                                                             |                   |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "definition": "JMES path for transforming input element",
              "example": "{\"id\": productid}",
              "default": null
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMES path for transforming buffered data (which is an array)",
              "example": "@[?id>0]",
              "default": null
            },
            "bufferId": {
              "type": "string",
              "definition": "Unique id for buffering similar payloads together",
              "example": "product_ids",
              "default": null
            },
            "bufferSize": {
              "type": "integer",
              "definition": "Max number of records to buffer",
              "example": 10,
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
`bufferSize` is defined at action level instead of handler level. This allows real-time changes for different buffer types without rebuilding the handler.
{% endhint %}

This action can improve performance for handlers that support batched requests, such as bulk writes or batched rule calculations.


# Merge Parallel Steps

These actions provide ability to merge parallel saga steps in distributed flow executions.

## Merge Parallel Steps Actions

### Merge

Merges multiple parallel running branches in a saga flow, storing merge status in a state manager. Each merge instance is identified by a unique `taskId`, and contributing branches are identified by their `mergeIds`. When all required merge ids are received, the merge step continues.

{% tabs %}
{% tab title="Table" %}

| Field        | Definition                                         | Example       | Default |
| ------------ | -------------------------------------------------- | ------------- | ------- |
| Domain       | Name of state manager for coordinating merge state | search\_merge | -       |
| {% endtab %} |                                                    |               |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of state manager for coordinating merge state",
          "example": "search_merge",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter          | Definition                                                                                         | Example | Default |
| ------------------ | -------------------------------------------------------------------------------------------------- | ------- | ------- |
| Merge Path         | [Json path of the payload that should be merged with other merge branches](#user-content-fn-1)[^1] | results | -       |
| Required Merge Ids | Comma separated list of merge ids that are required to complete the merge                          | 1,2,3   | -       |
| Merge Id Path      | Json path which defines id for merge branch                                                        | id      | mergeId |
| Task Id Path       | [Json path which defines id for merge instance](#user-content-fn-2)[^2]                            | mainId  | taskId  |
| {% endtab %}       |                                                                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "mergePath": {
              "type": "string",
              "definition": "Json path of the payload that should be merged with other merge branches",
              "example": "results",
              "default": null
            },
            "requiredMergeIds": {
              "type": "string",
              "definition": "Comma separated list of merge ids that are required to complete the merge",
              "example": "1,2,3",
              "default": null
            },
            "mergeIdPath": {
              "type": "string",
              "definition": "Json path which defines id for merge branch",
              "example": "id",
              "default": "mergeId"
            },
            "taskIdPath": {
              "type": "string",
              "definition": "Json path which defines id for merge instance",
              "example": "mainId",
              "default": "taskId"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
In local saga flows, steps run in sequence. Use `ForEachEventHandler` to create parallelism there instead of `MergeEventHandler`.
{% endhint %}

[^1]: Also used for returning merge results in output event

[^2]: If given path is null, `[requestId]:[sagaStepId][runnerPartition]` is used


# Log Event

These actions provide ability to review contents of events received by a runner from logs.

## Log Event Actions

### Log

Logs contents of the event received with the following event metadata parameters:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                     | Example | Default           |
| ------------ | ---------------------------------------------- | ------- | ----------------- |
| Level        | Logging level to use                           | ERROR   | DEBUG             |
| Type         | Whether full event or payload should be logged | payload | event             |
| Message      | Message format to use for logging              | Success | Event details: {} |
| {% endtab %} |                                                |         |                   |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "level": {
              "type": "string",
              "definition": "Logging level to use",
              "example": "ERROR",
              "default": "DEBUG"
            },
            "type": {
              "type": "string",
              "definition": "Whether full event or payload should be logged",
              "example": "payload",
              "default": "event"
            },
            "message": {
              "type": "string",
              "definition": "Message format to use for logging",
              "example": "Success",
              "default": "Event details: {}"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
If the runner log level is above the selected level, event details will not be displayed.
{% endhint %}


# Send Event

These actions provide ability to send events to an output stream.

## Send Event Actions

### SendEvent

Sends the event received to another stream with the following event metadata parameters:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition              | Example        | Default                |
| ------------ | ----------------------- | -------------- | ---------------------- |
| System       | System to send event to | kafka\_default | -                      |
| Stream       | Stream to send event to | tracking       | -                      |
| Key          | Key value to use        | 123            | -                      |
| Partition    | Partition to use        | 1              | \[Calculated from key] |
| {% endtab %} |                         |                |                        |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "system": {
              "type": "string",
              "definition": "System to send event to",
              "example": "kafka_default",
              "default": null
            },
            "stream": {
              "type": "string",
              "definition": "Stream to send event to",
              "example": "tracking",
              "default": null
            },
            "key": {
              "type": ["string", "integer"],
              "definition": "Key value to use",
              "example": 123,
              "default": null
            },
            "partition": {
              "type": ["integer", "string"],
              "definition": "Partition to use",
              "example": 1,
              "default": "[Calculated from key]"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Validate Event

These actions provide ability to check validity of event contents using different validator types.

## Validate Event Actions

### Validate

Checks validity of the event input payload using the configured validator instance and returns results.

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                             | Example    | Default |
| -------------- | -------------------------------------- | ---------- | ------- |
| Input Element  | Json path in payload to use            | parameters | -       |
| Output Element | Json path in payload to return results | result     | -       |
| {% endtab %}   |                                        |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path in payload to use",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path in payload to return results",
          "example": "result",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                        | Example             | Default |
| -------------- | ------------------------------------------------- | ------------------- | ------- |
| Output Pattern | JMESPath expression to convert results            | -                   | -       |
| \*             | Additional parameters used by the validator class | pattern=(value='a') | -       |
| {% endtab %}   |                                                   |                     |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath expression to convert results",
              "example": null,
              "default": null
            },
            "*": {
              "type": "string",
              "definition": "Additional parameters used by the validator class",
              "example": "pattern=(value='a')",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Transform Event

These actions provide ability to transform incoming event payload using various transformation classes.

## Transform Event Actions

### Transform

Applies the requested transformation on an event. Event metadata parameters applicable for this action are as follows:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter    | Definition                                    | Example                                              | Default |
| ------------ | --------------------------------------------- | ---------------------------------------------------- | ------- |
| Class        | Fully qualified name of the transformer class | com.rierino.handler.transform.ReducePayloadTransform | -       |
| {% endtab %} |                                               |                                                      |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "class": {
              "type": "string",
              "description": "Fully qualified name of the transformer class",
              "examples": [
                "com.rierino.handler.transform.ReducePayloadTransform"
              ],
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
All transformer classes available in saga flows can be used with this handler, making it possible to distribute resource-consuming transformations to different runners.
{% endhint %}


# Do Nothing

These actions provide ability to pass event data through without changes.

## Do Nothing Actions

### noop

Passes event data as is to the output.


# Lock & Unlock

These actions provide ability to create locks and unlock them for a given id and a domain.

## Lock & Unlock Actions

### TryLock

Tries creating a lock and returns whether it was successful:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                      | Example    | Default |
| -------------- | ----------------------------------------------- | ---------- | ------- |
| Input Element  | Json path in payload that has id parameter      | parameters | -       |
| Output Element | Json path in payload to return "locked" results | result     | -       |
| {% endtab %}   |                                                 |            |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path in payload that has id parameter",
          "examples": ["parameters"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path in payload to return \"locked\" results",
          "examples": ["result"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With the following event metadata parameters:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter     | Definition                                                                                          | Example | Default |
| ------------- | --------------------------------------------------------------------------------------------------- | ------- | ------- |
| Master        | Whether master lock should be used instead of a specific id                                         | true    | false   |
| Timeout       | Milliseconds to wait for acquiring a lock, overrides default                                        | 2000    | -       |
| Expiry        | TTL in milliseconds for lock expiry, overrides default                                              | 10000   | -       |
| Allow No Lock | Whether failure to hold a lock should return a successful result, returns `locked` instead of error | true    | false   |
| {% endtab %}  |                                                                                                     |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "master": {
              "type": "boolean",
              "description": "Whether master lock should be used instead of a specific id",
              "examples": [true],
              "default": false
            },
            "timeout": {
              "type": "integer",
              "description": "Milliseconds to wait for acquiring a lock (overrides default)",
              "examples": [2000],
              "default": null
            },
            "expiry": {
              "type": "integer",
              "description": "TTL in milliseconds for lock expiry (overrides default)",
              "examples": [10000],
              "default": null
            },
            "allowNoLock": {
              "type": "boolean",
              "description": "Whether failure to hold a lock should return a successful result (returns \"locked\" value instead of error)",
              "examples": [true],
              "default": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Unlock

Unlocks an existing lock:

{% tabs %}
{% tab title="Fields (table)" %}

| Field         | Definition                                 | Example    | Default |
| ------------- | ------------------------------------------ | ---------- | ------- |
| Input Element | Json path in payload that has id parameter | parameters | -       |
| {% endtab %}  |                                            |            |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path in payload that has id parameter",
          "examples": ["parameters"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With the following event metadata parameters:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter    | Definition                                                  | Example | Default |
| ------------ | ----------------------------------------------------------- | ------- | ------- |
| Master       | Whether master lock should be used instead of a specific id | true    | false   |
| {% endtab %} |                                                             |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "master": {
              "type": "boolean",
              "description": "Whether master lock should be used instead of a specific id",
              "examples": [true],
              "default": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### CheckLock

Returns the current status for a lock:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                      | Example    | Default |
| -------------- | ----------------------------------------------- | ---------- | ------- |
| Input Element  | Json path in payload that has id parameter      | parameters | -       |
| Output Element | Json path in payload to return "locked" results | result     | -       |
| {% endtab %}   |                                                 |            |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path in payload that has id parameter",
          "examples": ["parameters"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path in payload to return \"locked\" results",
          "examples": ["result"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With the following event metadata parameters:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter    | Definition                                                  | Example | Default |
| ------------ | ----------------------------------------------------------- | ------- | ------- |
| Master       | Whether master lock should be used instead of a specific id | true    | false   |
| {% endtab %} |                                                             |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "master": {
              "type": "boolean",
              "description": "Whether master lock should be used instead of a specific id",
              "examples": [true],
              "default": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Perform DB Transaction

These actions provide ability to execute multiple state manipulation journals as a single database transaction.

## Perform DB Transaction Actions

### ExecuteTransaction

Executes database statements on target JDBC state managers as a single transaction, using an array of journals provided in the `journals` path of the event payload.

### StartTransaction

Starts a database transaction on the current local thread, which can be used as part of a local saga flow for multiple database operations.

### CommitTransaction

Commits the current database transaction started on the local thread. Call this after `StartTransaction`.

### RollbackTransaction

Cancels and rolls back the current database transaction started on the local thread. Call this after `StartTransaction`.

{% hint style="info" %}
This handler can only be used on JDBC state managers.
{% endhint %}


# Trigger Runner Command

These actions provide ability to trigger commands through event streams.

## Trigger Runner Command Actions

{% hint style="info" %}
Unlike commands, events are not broadcast to all runners. Triggering a command with this handler causes only a single runner to execute the command.

This handler is mainly useful for development and testing when a single-partition runner is used and commands are not sent through Kafka topics.
{% endhint %}

### Command

Treats input payload as a command and executes it on the runner:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                             | Example | Default |
| -------------- | -------------------------------------- | ------- | ------- |
| Input Element  | Json path in payload to use            | command | -       |
| Output Element | Json path in payload to return results | result  | -       |
| {% endtab %}   |                                        |         |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path in payload to use",
          "examples": ["command"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path in payload to return results",
          "examples": ["result"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter     | Definition                            | Example | Default |
| ------------- | ------------------------------------- | ------- | ------- |
| Input Pattern | JMESPath expression to create command | -       | -       |
| {% endtab %}  |                                       |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESPath expression to create command",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# ML & AI Actions

ML and AI actions provide ability to run machine learning inference, GenAI calls, embeddings and agent protocols.


# Use ML Models

These actions provide ability to run real-time inference using various machine learning libraries.

## Use ML Models Actions

### Score / ScoreML

Scores input data using a pretrained model managed by this handler. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | $.score    | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "examples": ["parameters"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "examples": ["$.score"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter      | Definition                                                          | Example                        | Default |
| -------------- | ------------------------------------------------------------------- | ------------------------------ | ------- |
| Input Pattern  | JMESPath pattern to apply on data input                             | \[ \[text] ]                   | -       |
| Output Pattern | JMESPath pattern to apply on data output, before returning response | {totalPrice:basket.totalPrice} | -       |
| {% endtab %}   |                                                                     |                                |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data input",
              "examples": ["[ [text] ]"],
              "default": null
            },
            "outputPattern": {
              "type": "string",
              "description": "JMESPath pattern to apply on data output, before returning response",
              "examples": ["{totalPrice:basket.totalPrice}"],
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Use GenAI Models

These actions provide ability to use GenAI models from various providers.

## Use GenAI Models Actions

### LLMChat

Performs a chat interaction with a target LLM model provider. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                         | Example       | Default |
| -------------- | -------------------------------------------------- | ------------- | ------- |
| Domain         | ID of the model to use                             | chatgpt\_chat | -       |
| Input Element  | Json path for the input in request event payload   | message       | -       |
| Output Element | Json path for the output in response event payload | output        | -       |
| {% endtab %}   |                                                    |               |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "ID of the model to use",
          "examples": ["chatgpt_chat"],
          "default": null
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "examples": ["message"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "examples": ["output"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

Input element can include the following fields:

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "chat": {
      "type": "string",
      "description": "ID of an ongoing chat for an assistant type use case with memory",
      "examples": ["test-chat"],
      "default": null
    },
    "message": {
      "description": "A text message or an object representing complex chat contents",
      "default": null,
      "oneOf": [
        {
          "type": "string",
          "examples": ["Hello"]
        },
        {
          "type": "object",
          "examples": [
            {
              "text": "Can you describe this image",
              "imageBase64": "base64"
            }
          ],
          "properties": {
            "text": {
              "type": "string",
              "description": "Text part of the user message",
              "examples": ["Hello"],
              "default": null
            },
            "textFile": {
              "type": "string",
              "description": "URI of a user message stored as a file",
              "examples": ["https://example.com/message.txt"],
              "default": null
            },
            "image": {
              "type": "string",
              "description": "URI of an image attachment, can be URL or data URI",
              "examples": ["data:image/png;base64,iVBORw0KGgoAAAANSUhE..."],
              "default": null
            },
            "imageBase64": {
              "type": "string",
              "description": "Base64 data of an image attachment",
              "examples": ["iVBORw0KGgoAAAANSUhE..."],
              "default": null
            },
            "imageBase64Mime": {
              "type": "string",
              "description": "Mime type of base64 image",
              "examples": ["image/jpg"],
              "default": null
            },
            "pdf": {
              "type": "string",
              "description": "URI of a PDF attachment",
              "examples": ["https://example.com/file.pdf"],
              "default": null
            },
            "pdfBase64": {
              "type": "string",
              "description": "Base64 data of a PDF attachment",
              "examples": ["iVBORw0KGgoAAAANSUhE..."],
              "default": null
            },
            "audio": {
              "type": "string",
              "description": "URI of an audio attachment",
              "examples": ["https://example.com/audio.mp3"],
              "default": null
            },
            "audioBase64": {
              "type": "string",
              "description": "Base64 data of an audio attachment",
              "examples": ["iVBORw0KGgoAAAANSUhE..."],
              "default": null
            },
            "video": {
              "type": "string",
              "description": "URI of a video attachment",
              "examples": ["https://example.com/video.mp4"],
              "default": null
            },
            "videoBase64": {
              "type": "string",
              "description": "Base64 data of a video attachment",
              "examples": ["iVBORw0KGgoAAAANSUhE..."],
              "default": null
            }
          }
        }
      ]
    },
    "messages": {
      "type": "array",
      "description": "Array of message entries",
      "default": null,
      "items": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "Text part of the user message",
            "default": null
          }
        }
      }
    },
    "prompt": {
      "type": "string",
      "description": "ID of the prompt to generate an additional text based user message",
      "examples": ["search-prompt"],
      "default": null
    },
    "input": {
      "type": "object",
      "description": "Data input elements to be used for populating prompt",
      "examples": [{"search": "keyword"}],
      "default": null
    }
  }
}
```

{% hint style="info" %}
Base64 contents can also be passed as data URI values with the correct prefix.
{% endhint %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter       | Definition                                                                                                                                       | Example                                | Default |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------- | ------- |
| Message Pattern | Used for tool sagas, allowing merging data from original event to saga call, with `arguments` as agent-generated input and `payload` as original | merge(arguments, {user: payload.user}) | -       |
| Full Result     | Whether response should include full AI call details, such as token counts and tool executions                                                   | true                                   | false   |
| Json Response   | Whether model response should be automatically parsed as a JSON object                                                                           | true                                   | false   |
| {% endtab %}    |                                                                                                                                                  |                                        |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "messagePattern": {
              "type": "string",
              "description": "Used for tool sagas, allowing merging data from original event to saga call",
              "examples": ["merge(arguments, {user: payload.user})"],
              "default": null
            },
            "fullResult": {
              "type": "boolean",
              "description": "Whether response should include full AI call details",
              "examples": [true],
              "default": false
            },
            "jsonResponse": {
              "type": "boolean",
              "description": "Whether model response should be automatically parsed as a json object",
              "examples": [true],
              "default": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### LLMGenerateImage

Performs an image generation with a target LLM model provider. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                         | Example                      | Default |
| -------------- | -------------------------------------------------- | ---------------------------- | ------- |
| Domain         | ID of the model to use                             | dalle\_gen                   | -       |
| Input Element  | Json path for the input in request event payload   | {prompt: "", imageCount: ""} | -       |
| Output Element | Json path for the output in response event payload | imageBase64                  | -       |
| {% endtab %}   |                                                    |                              |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "ID of the model to use",
          "examples": ["dalle_gen"],
          "default": null
        },
        "inputElement": {
          "description": "Json path for the input in request event payload",
          "default": null,
          "oneOf": [
            {
              "type": "string",
              "examples": ["parameters"]
            },
            {
              "type": "object",
              "examples": [{"prompt": "", "imageCount": ""}]
            }
          ]
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "examples": ["imageBase64"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter    | Definition                                           | Example | Default |
| ------------ | ---------------------------------------------------- | ------- | ------- |
| Full Result  | Whether response should include full AI call details | true    | false   |
| {% endtab %} |                                                      |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "fullResult": {
              "type": "boolean",
              "description": "Whether response should include full AI call details",
              "examples": [true],
              "default": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### LLMEditImage

Performs an image edit with a target LLM model provider. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                         | Example                                                                                   | Default |
| -------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------- |
| Domain         | ID of the model to use                             | dalle\_gen                                                                                | -       |
| Input Element  | Json path for the input in request event payload   | {prompt: "", image: {revisedPrompt: "", base64Data: "", mimeType: "", url: ""}, mask: ""} | -       |
| Output Element | Json path for the output in response event payload | output                                                                                    | -       |
| {% endtab %}   |                                                    |                                                                                           |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "ID of the model to use",
          "examples": ["dalle_gen"],
          "default": null
        },
        "inputElement": {
          "description": "Json path for the input in request event payload",
          "default": null,
          "oneOf": [
            {
              "type": "string",
              "examples": ["parameters"]
            },
            {
              "type": "object",
              "examples": [
                {
                  "prompt": "",
                  "image": {
                    "revisedPrompt": "",
                    "base64Data": "",
                    "mimeType": "",
                    "url": ""
                  },
                  "mask": ""
                }
              ]
            }
          ]
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "examples": ["output"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter    | Definition                                           | Example | Default |
| ------------ | ---------------------------------------------------- | ------- | ------- |
| Full Result  | Whether response should include full AI call details | true    | false   |
| {% endtab %} |                                                      |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "fullResult": {
              "type": "boolean",
              "description": "Whether response should include full AI call details",
              "examples": [true],
              "default": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Perform Text Embedding

These actions provide ability to convert text into embeddings for advanced search functionality.

## Perform Text Embedding Actions

### EmbedText

Transforms text into an embedding. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the input in request event payload   | input   | -       |
| Output Element | Json path for the output in response event payload | output  | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "examples": ["input"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "examples": ["output"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter     | Definition                                                                                        | Example                  | Default |
| ------------- | ------------------------------------------------------------------------------------------------- | ------------------------ | ------- |
| Input Pattern | JMESpath pattern to apply on input element for getting text and metadata fields                   | {text: "", metadata: ""} | -       |
| Extra Action  | Optional extra action after generating embedding, `add` to local index or `search` in local index | add                      | -       |
| Max Results   | Maximum results to return if `search` extra action is used                                        | 5                        | -       |
| Min Score     | Minimum similarity score required if `search` extra action is used                                | 0.5                      | -       |
| {% endtab %}  |                                                                                                   |                          |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "JMESpath pattern to apply on input element for getting text and metadata fields",
              "examples": ["{text: \"\", metadata: \"\"}"],
              "default": null
            },
            "extraAction": {
              "type": "string",
              "description": "Optional extra action to perform after generating embedding",
              "examples": ["add"],
              "default": null
            },
            "maxResults": {
              "type": "integer",
              "description": "Maximum results to return if search extra action is used",
              "examples": [5],
              "default": null
            },
            "minScore": {
              "type": "number",
              "description": "Minimum similarity score required if search extra action is used",
              "examples": [0.5],
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

Input element can be a text value, or an object in `{chat, message}` format where `chat` includes the ID of an ongoing chat for assistant-style use cases with memory.


# Service MCP Requests

These actions provide ability to expose existing microservice capabilities over MCP.

## Service MCP Requests Actions

### CallRPC

Responds to a request using MCP protocol. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                         | Example                 | Default |
| -------------- | -------------------------------------------------- | ----------------------- | ------- |
| Domain         | ID of the MCP server to interact with              | procurement\_specialist | -       |
| Input Element  | Json path for the input in request event payload   | message                 | -       |
| Output Element | Json path for the output in response event payload | output                  | -       |
| {% endtab %}   |                                                    |                         |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "ID of the MCP server to interact with",
          "examples": ["procurement_specialist"],
          "default": null
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload",
          "examples": ["message"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "examples": ["output"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter     | Definition                                                   | Example | Default |
| ------------- | ------------------------------------------------------------ | ------- | ------- |
| Input Pattern | Jmespath expression for converting input payload to MCP call | -       | -       |
| {% endtab %}  |                                                              |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "Jmespath expression for converting input payload to MCP call",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

Input contents should match MCP server calls such as:

#### Initialize Request

```json
{
    "jsonrpc": "2.0",
    "method": "initialize"
}
```

#### Tool Listing Request

```json
{
    "jsonrpc": "2.0",
    "method": "tools/list"
}
```

#### Tool Call Request

```json
{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
        "name": "Hello",
        "arguments": {}
    }
}
```


# Service A2A Requests

These actions provide ability to expose existing microservice capabilities over A2A.

## Service A2A Requests Actions

### GetA2A

Responds with the agent card configuration for `.well-known/agent.json` calls.

### CallA2A

Responds to a request using A2A protocol. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Fields (table)" %}

| Field          | Definition                                                              | Example                 | Default |
| -------------- | ----------------------------------------------------------------------- | ----------------------- | ------- |
| Domain         | ID of the A2A server to interact with                                   | procurement\_specialist | -       |
| Input Element  | Json path for the input in request event payload in A2A JSON-RPC format | message                 | -       |
| Output Element | Json path for the output in response event payload                      | output                  | -       |
| {% endtab %}   |                                                                         |                         |         |

{% tab title="Fields (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "description": "ID of the A2A server to interact with",
          "examples": ["procurement_specialist"],
          "default": null
        },
        "inputElement": {
          "type": "string",
          "description": "Json path for the input in request event payload in A2A JSON-RPC format",
          "examples": ["message"],
          "default": null
        },
        "outputElement": {
          "type": "string",
          "description": "Json path for the output in response event payload",
          "examples": ["output"],
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Parameters (table)" %}

| Parameter     | Definition                                                   | Example | Default |
| ------------- | ------------------------------------------------------------ | ------- | ------- |
| Input Pattern | Jmespath expression for converting input payload to A2A call | -       | -       |
| {% endtab %}  |                                                              |         |         |

{% tab title="Parameters (JSON Schema)" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "description": "Jmespath expression for converting input payload to A2A call",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Specialized Actions

Specialized actions facilitate advanced operations and are available in Rierino Core+ edition.


# Apply Advanced Rules

These actions provide ability to execute business rules using Drools BRMS.

## Apply Advanced Rules Actions

### Process / ProcessRules

Passes structured request data to Drools and returns rule evaluation results in the output. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the input in request event payload   | basket  | -       |
| Output Element | Json path for the output in response event payload | basket  | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Apply Advanced Rules action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "basket",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "basket",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                                                 | Example                        | Default |
| -------------- | ------------------------------------------------------------------------------------------ | ------------------------------ | ------- |
| Input Pattern  | JMESPath pattern to apply on data input                                                    | {items:items.productid}        | -       |
| Output Pattern | JMESPath pattern to apply on data output, before returning response                        | {totalPrice:basket.totalPrice} | -       |
| For Each       | Field for which a separate record should be passed on to Drools                            | items                          | -       |
| For Each Map   | Json pattern for mapping each record passed to Drools, allowing replication of common data | -                              | -       |
| {% endtab %}   |                                                                                            |                                |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Apply Advanced Rules action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data input",
              "example": "{items:items.productid}",
              "default": null
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": "{totalPrice:basket.totalPrice}",
              "default": null
            },
            "forEach": {
              "type": "string",
              "definition": "Field for each a separate record should be passed on to Drools",
              "example": "items",
              "default": null
            },
            "forEachMap": {
              "type": "string",
              "definition": "Json pattern for mapping each record that should be passed on to Drools, allowing replication of common data",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Calculate Real-time Metrics

These actions provide ability to build real-time intelligence and CEP capabilities using Siddhi.

## Calculate Real-time Metrics Actions

### Get / GetRT

Returns stored real-time data for a given id from Siddhi tables. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example         | Default |
| -------------- | -------------------------------------------------- | --------------- | ------- |
| Domain         | Name of the Siddhi table to query on               | session\_latest | -       |
| Input Element  | Json path for the input in request event payload   | basket          | -       |
| Output Element | Json path for the output in response event payload | basket          | -       |
| {% endtab %}   |                                                    |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Calculate Real-time Metrics Get/GetRT action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "Name of the Siddhi table to query on",
          "example": "session_latest",
          "default": null
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "basket",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "basket",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                          | Example                        | Default |
| -------------- | ------------------------------------------------------------------- | ------------------------------ | ------- |
| Output Pattern | JMESPath pattern to apply on data output, before returning response | {totalPrice:basket.totalPrice} | -       |
| Dataflow       | Id of the dataflow from which data will be received                 | session\_dna                   | -       |
| Id Field       | Name of the id field to query on Siddhi table                       | sessionid                      | id      |
| Id Path        | Json path for the id field in input element                         | session.id                     | id      |
| {% endtab %}   |                                                                     |                                |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Calculate Real-time Metrics Get/GetRT action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": "{totalPrice:basket.totalPrice}",
              "default": null
            },
            "dataflow": {
              "type": "string",
              "definition": "Id of the dataflow from which data will be received",
              "example": "session_dna",
              "default": null
            },
            "idField": {
              "type": "string",
              "definition": "Name of the id field to query on Siddhi table",
              "example": "sessionid",
              "default": "id"
            },
            "idPath": {
              "type": "string",
              "definition": "Json path for the id field in input element",
              "example": "session.id",
              "default": "id"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "id": "path-1"
    }
}
```

Event Metadata

### ![](/files/wbQ8YykfEkVsl7tEp0NH)

</details>

### GetQuery / GetQueryRT

Returns stored real-time data for a given id from Siddhi tables. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the input in request event payload   | basket  | -       |
| Output Element | Json path for the output in response event payload | product | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Calculate Real-time Metrics GetQuery/GetQueryRT action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "basket",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "product",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                                          | Example                                               | Default |
| -------------- | ------------------------------------------------------------------- | ----------------------------------------------------- | ------- |
| Output Pattern | JMESPath pattern to apply on data output, before returning response | {id:id, name:data.name, description:data.description} | -       |
| Dataflow       | Id of the dataflow from which data will be received                 | session\_dna                                          | -       |
| Query Id       | Id of the query to execute                                          | product\_search\_0001                                 | -       |
| Query Name     | Name of the query to execute                                        | Product Search                                        | -       |
| Query Json     | Full Json representation of query to execute                        | -                                                     | -       |
| {% endtab %}   |                                                                     |                                                       |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Calculate Real-time Metrics GetQuery/GetQueryRT action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output, before returning response",
              "example": "{id:id, name:data.name, description:data.description}",
              "default": null
            },
            "dataflow": {
              "type": "string",
              "definition": "Id of the dataflow from which data will be received",
              "example": "session_dna",
              "default": null
            },
            "queryId": {
              "type": "string",
              "definition": "Id of the query to execute",
              "example": "product_search_0001",
              "default": null
            },
            "queryJson": {
              "type": "object",
              "definition": "Full Json representation of query to execute",
              "default": null
            },
            "queryName": {
              "type": "string",
              "definition": "Name of the query to execute",
              "example": "Product Search",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "parameters": {
        "category": "cat-1"
    }
}
```

Event Metadata

## ![](/files/LkgnBX1MNoUUq0xGQp3V)

</details>


# Consume Web of Things

These actions provide ability to consume WoT data and invoke actions on IoT and similar endpoints.

## Consume Web of Things Actions

### GetWOTEntry

Returns details of a Thing using its discovery endpoint. Uses `domain` event metadata to refer to the Thing ID.

### GetWOTProperty

Reads a specific property from a Thing. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example         | Default |
| -------------- | -------------------------------------------------- | --------------- | ------- |
| Domain         | ID of the Thing to read from                       | coffee\_machine | -       |
| Output Element | Json path for the output in response event payload | output          | -       |
| {% endtab %}   |                                                    |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Consume Web of Things GetWOTProperty action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "ID of the \"Thing\" to read from",
          "example": "coffee_machine",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "output",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                   | Example | Default |
| ------------ | ---------------------------- | ------- | ------- |
| Property     | Name of the property to read | level   | -       |
| {% endtab %} |                              |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Consume Web of Things GetWOTProperty action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "property": {
              "type": "string",
              "definition": "Name of the property to read",
              "example": "level",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### WriteWOTProperty

Writes a specific property to a Thing. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                             | Example         | Default |
| -------------- | ------------------------------------------------------ | --------------- | ------- |
| Domain         | ID of the Thing to write to                            | coffee\_machine | -       |
| Input Element  | Json path for the input in event payload to write from | input           | -       |
| Output Element | Json path for the output in response event payload     | output          | -       |
| {% endtab %}   |                                                        |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Consume Web of Things WriteWOTProperty action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "ID of the \"Thing\" to write to",
          "example": "coffee_machine",
          "default": null
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload to write from",
          "example": "input",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "output",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                    | Example | Default |
| ------------ | ----------------------------- | ------- | ------- |
| Property     | Name of the property to write | level   | -       |
| {% endtab %} |                               |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Consume Web of Things WriteWOTProperty action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "property": {
              "type": "string",
              "definition": "Name of the property to write",
              "example": "level",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### InvokeWOTAction

Invokes a specific action on a Thing. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                                           | Example         | Default |
| -------------- | -------------------------------------------------------------------- | --------------- | ------- |
| Domain         | ID of the Thing to invoke action on                                  | coffee\_machine | -       |
| Input Element  | Json path for the input in event payload to use as action parameters | input           | -       |
| Output Element | Json path for the output in response event payload                   | output          | -       |
| {% endtab %}   |                                                                      |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Consume Web of Things InvokeWOTAction action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "ID of the \"Thing\" to invoke action on",
          "example": "coffee_machine",
          "default": null
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload to use as action parameters",
          "example": "input",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "output",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                 | Example | Default |
| ------------ | -------------------------- | ------- | ------- |
| Action       | Name of the action to call | cleanup | -       |
| {% endtab %} |                            |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Consume Web of Things InvokeWOTAction action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "action": {
              "type": "string",
              "definition": "Name of the action to call",
              "example": "cleanup",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Produce Web of Things

These actions provide ability to produce WoT descriptions and endpoints from allowed sagas.

## Produce Web of Things Actions

### ReadThing

Creates and returns a Thing description with a list of actions to invoke and properties to read from allowed sagas. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example       | Default |
| -------------- | -------------------------------------------------- | ------------- | ------- |
| Domain         | State to read Thing from                           | custom\_thing | thing   |
| Input Element  | Json path for the id field in event payload        | input         | -       |
| Output Element | Json path for the output in response event payload | output        | -       |
| {% endtab %}   |                                                    |               |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Produce Web of Things ReadThing action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "State to read \"Thing\" from",
          "example": "custom_thing",
          "default": "thing"
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the id field in event payload",
          "example": "input",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "output",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

Thing definitions are stored in state managers with the following data elements:

* `title`
* `description`
* `baseURL`
* `securityScheme`
* `contentType`
* `actionsSagas` - list of saga ids used to invoke actions
* `propertiesSagas` - list of saga ids used to read properties


# Generate Excel

These actions provide ability to produce formatted Excel files using templates and input payload.

## Generate Excel Actions

### ExportXLSX

Produces an Excel file from given input data and template id. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                                       | Example  | Default |
| ------------- | ------------------------------------------------ | -------- | ------- |
| Input Element | Json path for the input in request event payload | customer | -       |
| {% endtab %}  |                                                  |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Generate Excel ExportXLSX action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "customer",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                                                                                       | Example        | Default |
| ------------- | ------------------------------------------------------------------------------------------------ | -------------- | ------- |
| Template      | Id of the template to use from code.state                                                        | landing\_page  | -       |
| Input Pattern | JMESPath pattern to apply on input element                                                       | {sheets: list} | -       |
| Sheets Path   | Json path in payload including data for sheets, in `{[sheet_name]: [{[field]: [value]}]}` format | list           | sheets  |
| Output Path   | Json path in payload defining the output file path on target file system                         | file\_path     | path    |
| {% endtab %}  |                                                                                                  |                |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Generate Excel ExportXLSX action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "templateId": {
              "type": "string",
              "definition": "Id of the template to use from code.state",
              "example": "landing_page",
              "default": null
            },
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on input element",
              "example": "{sheets: list}",
              "default": null
            },
            "sheetsPath": {
              "type": "string",
              "definition": "Json path in payload including data for sheets (in {[sheet_name]: [ {[field]: [value]} ]} format)",
              "example": "list",
              "default": "sheets"
            },
            "outputPath": {
              "type": "string",
              "definition": "Json path in payload defining the output file path on target file system",
              "example": "file_path",
              "default": "path"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

## Content Format

Templates used by this action have the following data format:

```json
{
    "name": "NAME",
    "header": {},
    "columns": [
        {"title": "TITLE", "field": "FIELD", "titleStyle": {}, "rowStyle": {}}
    ],
    "footer": {}
}
```

`titleStyle` and `rowStyle` use [Apache POI cell style](https://poi.apache.org/apidocs/dev/org/apache/poi/ss/util/CellUtil.html) keys.


# Generate PDF

These actions provide ability to produce formatted PDF files from HTML content.

## Generate PDF Actions

### ExportPDF

Produces a PDF file from given input data and template id. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                                       | Example  | Default |
| ------------- | ------------------------------------------------ | -------- | ------- |
| Input Element | Json path for the input in request event payload | customer | -       |
| {% endtab %}  |                                                  |          |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Generate PDF ExportPDF action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "customer",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter     | Definition                                                               | Example                     | Default |
| ------------- | ------------------------------------------------------------------------ | --------------------------- | ------- |
| Input Pattern | JMESPath pattern to apply on input element                               | {html: text}                | -       |
| Html Path     | Json path in payload including html text to convert to PDF               | input                       | html    |
| Output Path   | Json path in payload defining the output file path on target file system | file\_path                  | path    |
| Font Paths    | Comma separated list of font file paths to use in rendering              | /app/fonts/custom\_font.ttf | -       |
| Html Base     | Base URL root to use for converting html contents into PDF               | <https://example.com>       | -       |
| {% endtab %}  |                                                                          |                             |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Generate PDF ExportPDF action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on input element",
              "example": "{html: text}",
              "default": null
            },
            "htmlPath": {
              "type": "string",
              "definition": "Json path in payload including html text to convert to PDF",
              "example": "input",
              "default": "html"
            },
            "outputPath": {
              "type": "string",
              "definition": "Json path in payload defining the output file path on target file system",
              "example": "file_path",
              "default": "path"
            },
            "fontPaths": {
              "type": "string",
              "definition": "Comma separated list of font file paths to use in rendering",
              "example": "/app/fonts/custom_font.ttf",
              "default": null
            },
            "htmlBase": {
              "type": "string",
              "definition": "Base URL root to use for converting html contents into PDF",
              "example": "https://example.com",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
This action is typically used together with [Generate Text/Html](/devops/api-event-and-process-flows/configuring-saga-steps/event-step/core-actions/generate-text-html) to produce formatted PDF files.
{% endhint %}


# Call SOAP API

These actions provide ability to use SOAP services for third-party integrations.

## Call SOAP API Actions

### GetAvailableOperations

Gets the list of available operations for a SOAP service. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Output Element | Json path for the output in response event payload | ops     | list    |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Call SOAP API GetAvailableOperations action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "ops",
          "default": "list"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                | Example           | Default |
| ------------ | ----------------------------------------- | ----------------- | ------- |
| Service Name | Name of the service to get operations for | price\_calculator | -       |
| {% endtab %} |                                           |                   |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Call SOAP API GetAvailableOperations action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "serviceName": {
              "type": "string",
              "definition": "Name of the service to get operations for",
              "example": "price_calculator",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Invoke

Invokes a specific operation on a SOAP service. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | ops        | list    |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Call SOAP API Invoke action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "ops",
          "default": "list"
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                               | Example                   | Default |
| -------------- | ---------------------------------------- | ------------------------- | ------- |
| Input Pattern  | JMESPath pattern to apply on data input  | {"item": product}         | -       |
| Output Pattern | JMESPath pattern to apply on data output | {"product\_price": price} | -       |
| Service Name   | Name of the service to use               | price\_calculator         | -       |
| Operation      | Name of the operation to call            | calculate                 | -       |
| {% endtab %}   |                                          |                           |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Call SOAP API Invoke action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data input",
              "example": "{\"item\": product}",
              "default": null
            },
            "outputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on data output",
              "example": "{\"product_price\": price}",
              "default": null
            },
            "serviceName": {
              "type": "string",
              "definition": "Name of the service to use",
              "example": "price_calculator",
              "default": null
            },
            "operation": {
              "type": "string",
              "definition": "Name of the operation to call",
              "example": "calculate",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Input element should match the parameter names required by the SOAP operation.
{% endhint %}


# Integrate with Camel

These actions provide ability to use Apache Camel producers for third-party integrations.

## Integrate with Camel Actions

### SendMessage

Sends a message to a Camel producer and returns a response if the target system has output. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example    | Default |
| -------------- | -------------------------------------------------- | ---------- | ------- |
| Domain         | System name to use as target                       | mq         | -       |
| Input Element  | Json path for the input in request event payload   | parameters | -       |
| Output Element | Json path for the output in response event payload | result     | -       |
| {% endtab %}   |                                                    |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Integrate with Camel SendMessage action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "domain": {
          "type": "string",
          "definition": "System name to use as target",
          "example": "mq",
          "default": null
        },
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in request event payload",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "result",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                          | Example | Default |
| ------------ | ----------------------------------- | ------- | ------- |
| Exchange     | Camel message exchange pattern      | InOut   | -       |
| Camel Header | Header parameters to send to target | ...     | -       |
| {% endtab %} |                                     |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Integrate with Camel SendMessage action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "exchange": {
              "type": "string",
              "definition": "Camel message exchange pattern",
              "example": "InOut",
              "default": null
            },
            "camelHeader": {
              "type": "object",
              "definition": "Header parameters to send to target, represents camelHeader.*",
              "example": {
                "myHeader": "value"
              },
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Custom Code Actions

Custom code actions provide ability to execute scripts, dynamic Java code, packages and Python procedures.


# Run Scripts

These actions provide ability to execute stored scripts using Javax engines.

## Run Scripts Actions

### Process / ProcessScript

Passes the requested event to a dynamic event handler for processing. Event metadata parameters applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Parameter       | Definition                                  | Example         | Default |
| --------------- | ------------------------------------------- | --------------- | ------- |
| Dynamic Handler | Name of the code handler to execute request | custom\_handler | -       |
| Dynamic Action  | Name of the action to call on code handler  | CustomCalculate | -       |
| {% endtab %}    |                                             |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Run Scripts Process/ProcessScript action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "dynamicHandler": {
              "type": "string",
              "definition": "Name of the code handler to execute request",
              "example": "custom_handler",
              "default": null
            },
            "dynamicAction": {
              "type": "string",
              "definition": "Name of the action to call on code handler",
              "example": "CustomCalculate",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

<details>

<summary>Example</summary>

Input

```json
{
    "product": {
        "id": "product-1",
        "data": {
            "name": "Test Product"
        }
    }
}
```

Event Metadata

![](/files/LTazOTaFWGsZlfMV68vi)

</details>

{% hint style="info" %}
All parameters applicable for the selected code handler are also passed on by `ScriptLoadedEventHandler`.
{% endhint %}


# Run Java Package

These actions provide ability to load and execute dynamic Java packages during runtime.

## Run Java Package Actions

### Process / ProcessPackage

Passes the requested event to a dynamic event handler for processing. Event metadata parameters applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Parameter       | Definition                             | Example            | Default |
| --------------- | -------------------------------------- | ------------------ | ------- |
| Dynamic Handler | Name of the handler to execute request | basket\_operations | -       |
| Dynamic Action  | Name of the action to call on handler  | PriceBasket        | -       |
| {% endtab %}    |                                        |                    |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Run Java Package Process/ProcessPackage action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "dynamicHandler": {
              "type": "string",
              "definition": "Name of the handler to execute request",
              "example": "basket_operations",
              "default": null
            },
            "dynamicAction": {
              "type": "string",
              "definition": "Name of the action to call on handler",
              "example": "PriceBasket",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
All parameters applicable for the selected handler are also passed on by `JarLoadedEventHandler`.
{% endhint %}


# Run Python Procedure

These actions provide ability to handle events using Python libraries.

## Run Python Procedure Actions

### Process / ProcessPython

Passes the requested event to a Python interface for processing. Event metadata fields applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                             | Example    | Default |
| -------------- | -------------------------------------- | ---------- | ------- |
| Input Element  | Json path of payload input to pass     | parameters | -       |
| Output Element | Json path for output to add on payload | $          | -       |
| {% endtab %}   |                                        |            |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Run Python Procedure Process/ProcessPython action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path of payload input to pass",
          "example": "parameters",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for output to add on payload",
          "example": "$",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter      | Definition                                 | Example         | Default |
| -------------- | ------------------------------------------ | --------------- | ------- |
| Input Pattern  | JMESPath pattern to apply on input element | {data:contents} | -       |
| Python Package | Name of the Python package to use          | rierino\_runner | -       |
| Python Module  | Name of the Python module to use           | CustomHandler   | -       |
| Python Action  | Name of the Python function to call        | Calculate       | -       |
| {% endtab %}   |                                            |                 |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Run Python Procedure Process/ProcessPython action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "inputPattern": {
              "type": "string",
              "definition": "JMESPath pattern to apply on input element",
              "example": "{data:contents}",
              "default": null
            },
            "pyPackage": {
              "type": "string",
              "definition": "Name of the Python package to use",
              "example": "rierino_runner",
              "default": null
            },
            "pyModule": {
              "type": "string",
              "definition": "Name of the Python module to use",
              "example": "CustomHandler",
              "default": null
            },
            "pyAction": {
              "type": "string",
              "definition": "Name of the Python function to call",
              "example": "Calculate",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The Python function receives the Java handler, the processed input as a dict, and the event metadata parameters.
{% endhint %}


# Run Java Code

These actions provide ability to load and execute dynamic Java event handler code during runtime.

## Run Java Code Actions

### Process / ProcessCode

Passes the requested event to a dynamic event handler for processing. Event metadata parameters applicable for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Parameter       | Definition                                  | Example            | Default |
| --------------- | ------------------------------------------- | ------------------ | ------- |
| Dynamic Handler | Name of the code handler to execute request | basket\_operations | -       |
| Dynamic Action  | Name of the action to call on code handler  | PriceBasket        | -       |
| {% endtab %}    |                                             |                    |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Run Java Code Process/ProcessCode action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "dynamicHandler": {
              "type": "string",
              "definition": "Name of the code handler to execute request",
              "example": "basket_operations",
              "default": null
            },
            "dynamicAction": {
              "type": "string",
              "definition": "Name of the action to call on code handler",
              "example": "PriceBasket",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
All parameters applicable for the selected code handler are also passed on by `OpenHFTEventHandler`.
{% endhint %}


# Gateway Actions

Gateway actions facilitate authentication and session management and are mostly used on dedicated runners called by the API gateway.


# Authenticate

These actions provide ability to authenticate users and manage user access as part of gateway functionality.

## Authenticate Actions

### Register

Registers a user with provided credentials and returns the new user's id, if the handler allows user registration.

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the input in event payload           | auth    | -       |
| Output Element | Json path for the output in response event payload | $.user  | -       |

Registration details can be provided in the payload input element or in request metadata auth.

<details>

<summary>Example</summary>

Input

```json
{
    "auth": {
        "username": "user",
        "password": "pass"
    }
}
```

Event Metadata

![](/files/qUF53V522HI7JBg5Ih4r)

</details>

### Login

Logs in a user with credentials and returns tokens, and optionally user details.

| Field                     | Definition                                                          | Example            | Default                                              |
| ------------------------- | ------------------------------------------------------------------- | ------------------ | ---------------------------------------------------- |
| Input Element             | Json path for the input in event payload                            | auth               | -                                                    |
| Output Element            | Json path for the output in response event payload                  | $.token            | -                                                    |
| parameters.resolve        | Whether access token should be resolved to also return user details | true               | false                                                |
| parameters.resolvePattern | JMESPath expression for resolving token contents if resolve is true | {"access": access} | {"user": {"id": access.sub, "roles": access.roles} } |

<details>

<summary>Example</summary>

Input

```json
{
    "auth": {
        "username": "user",
        "password": "pass"
    }
}
```

Event Metadata

![](/files/EExeyf2WZiihl0qzsvqw)

</details>

### Validate

Validates and resolves a user with provided tokens and returns user details.

| Field                     | Definition                                                  | Example            | Default                                              |
| ------------------------- | ----------------------------------------------------------- | ------------------ | ---------------------------------------------------- |
| Input Element             | Json path for the input in event payload                    | auth               | -                                                    |
| Output Element            | Json path for the output in response event payload          | $.user             | -                                                    |
| parameters.resolvePattern | JMESPath expression for resolving token contents for output | {"access": access} | {"user": {"id": access.sub, "roles": access.roles} } |

### Resolve

Provides the same functionality and uses the same parameters as `Validate`.

### Refresh

Refreshes tokens with a provided refresh token and returns new tokens, and optionally user details.

| Field                     | Definition                                                               | Example            | Default                                              |
| ------------------------- | ------------------------------------------------------------------------ | ------------------ | ---------------------------------------------------- |
| Input Element             | Json path for the input in event payload                                 | auth               | -                                                    |
| Output Element            | Json path for the output in response event payload                       | $.user             | -                                                    |
| parameters.resolve        | Whether access token should be resolved to also return user id and roles | true               | false                                                |
| parameters.resolvePattern | JMESPath expression for resolving token contents if resolve is true      | {"access": access} | {"user": {"id": access.sub, "roles": access.roles} } |

### Logout

Logs out a user with the provided access token.

| Field         | Definition                               | Example | Default |
| ------------- | ---------------------------------------- | ------- | ------- |
| Input Element | Json path for the input in event payload | auth    | -       |

### ResolveKey

Resolves a given API key and returns resolved contents in output.

| Field                     | Definition                                                                            | Example                                        | Default                                                                      |
| ------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------- |
| Input Element             | Json path for the `api_key` input in event payload, or can be passed in auth metadata | auth                                           | -                                                                            |
| Output                    | Json path for the output in response event payload                                    | $.user                                         | -                                                                            |
| parameters.resolvePattern | JMESPath pattern for converting `{user,key}` data in output                           | {"user": {"id": key.id, "roles": key.roles } } | {"user": {"id": key.id, "roles": intersect(user.access.roles, key.roles) } } |

### UserRegister

Registers a new user with given profile and credential details and returns the created user's id as `user_id`.

| Field         | Definition                               | Example | Default |
| ------------- | ---------------------------------------- | ------- | ------- |
| Input Element | Json path for the input in event payload | auth    | -       |

### UserList

Lists current users with profile and access details.

| Field            | Definition                                | Example         | Default |
| ---------------- | ----------------------------------------- | --------------- | ------- |
| Input Element    | Json path for the input in event payload  | parameters      | -       |
| Output Element   | Json path for the output in event payload | $.users         | -       |
| Output Pattern   | JMESPath pattern for list of users        | {userList:list} | -       |
| parameters.skip  | Number of records to skip                 | 10              | -       |
| parameters.limit | Max number of records to return           | 10              | -       |

### UserGet

Returns profile and access details of a user with the given id.

| Field          | Definition                                | Example  | Default |
| -------------- | ----------------------------------------- | -------- | ------- |
| Input Element  | Json path for the input in event payload  | user     | -       |
| Output Element | Json path for the output in event payload | $.result | -       |
| Output Pattern | JMESPath pattern for returned user        | {user:@} | -       |

### UserDelete

Deletes the user with the given id from records.

| Field         | Definition                                       | Example  | Default |
| ------------- | ------------------------------------------------ | -------- | ------- |
| Input Element | Json path for the input in event payload with id | user     | -       |
| idPath        | Json path for the id field in input element      | username | id      |

### UserLogout

Logs out the user with the given id.

| Field         | Definition                                       | Example  | Default |
| ------------- | ------------------------------------------------ | -------- | ------- |
| Input Element | Json path for the input in event payload with id | user     | -       |
| idPath        | Json path for the id field in input element      | username | id      |

### UserSetProfile

Sets profile details of a given user id.

| Field         | Definition                                               | Example                           | Default |
| ------------- | -------------------------------------------------------- | --------------------------------- | ------- |
| Input Element | Json path for the input in event payload                 | user                              | -       |
| Input Pattern | JMESPath pattern for converting input into a user record | {id:id, data: {profile: profile}} | -       |

### UserSetCredential

Sets credential details of a given user id.

| Field         | Definition                                               | Example                                 | Default |
| ------------- | -------------------------------------------------------- | --------------------------------------- | ------- |
| Input Element | Json path for the input in event payload                 | user                                    | -       |
| Input Pattern | JMESPath pattern for converting input into a user record | {id:id, data: {credential: credential}} | -       |

### UserSetAccess

Sets access details of a given user id.

| Field         | Definition                                               | Example                         | Default |
| ------------- | -------------------------------------------------------- | ------------------------------- | ------- |
| Input Element | Json path for the input in event payload                 | user                            | -       |
| Input Pattern | JMESPath pattern for converting input into a user record | {id:id, data: {access: access}} | -       |

### UserCreateKey

Creates an API key for the given user id with the given access details.

| Field         | Definition                                               | Example                         | Default |
| ------------- | -------------------------------------------------------- | ------------------------------- | ------- |
| Input Element | Json path for the input in event payload                 | user                            | -       |
| Input Pattern | JMESPath pattern for converting input into a user record | {id:id, data: {access: access}} | -       |


# State Based

These actions provide a state-based authentication implementation using existing states as a credential store.

## State Based Actions

### Login

Extra event metadata parameters for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                                                         | Example | Default                 |
| ------------ | ------------------------------------------------------------------ | ------- | ----------------------- |
| Expiration   | Seconds for expiration of access token for a specific login action | 1200    | Handler's configuration |
| {% endtab %} |                                                                    |         |                         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "State Based Login action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "expiration": {
              "type": "number",
              "definition": "Seconds for expiration of access token for a specific login action",
              "example": 1200,
              "default": "Handler's configuration"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Refresh

Extra event metadata parameters for this action are as follows:

{% tabs %}
{% tab title="Table" %}

| Parameter          | Definition                                                                         | Example | Default |
| ------------------ | ---------------------------------------------------------------------------------- | ------- | ------- |
| Allow Unregistered | Whether refresh tokens should be valid if they don't belong to users in auth.state | true    | false   |
| {% endtab %}       |                                                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "State Based Refresh action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "allowUnregistered": {
              "type": "boolean",
              "definition": "Whether refresh tokens should be valid if they don't belong to users in auth.state",
              "example": true,
              "default": false
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Allowing unregistered user refresh can be useful where user registration is optional and stateless authentication is used.
{% endhint %}


# Keycloak Based

These actions provide a Keycloak-based authentication implementation.

## Keycloak Based Actions

### Register

Supports additional credential types provided as `credential_type` in the request, in addition to `password`.

### Login

Supports additional credential types provided as `grant_type` in the request, in addition to `password`.

### UpdatePassword

Allows updating password for a user represented by `access_token`, using `password` field.

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                               | Example | Default |
| ------------- | ---------------------------------------- | ------- | ------- |
| Input Element | Json path for the input in event payload | auth    | -       |
| {% endtab %}  |                                          |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Keycloak Based UpdatePassword action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload",
          "example": "auth",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### ExecuteActionEmail

Triggers an action email through Keycloak for a specific action type such as `VALIDATE_EMAIL` or `FORGOT_EMAIL` for a given `username`.

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                               | Example | Default |
| ------------- | ---------------------------------------- | ------- | ------- |
| Input Element | Json path for the input in event payload | auth    | -       |
| {% endtab %}  |                                          |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Keycloak Based ExecuteActionEmail action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload",
          "example": "auth",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition        | Example       | Default |
| ------------ | ----------------- | ------------- | ------- |
| Action       | Action to execute | FORGOT\_EMAIL | -       |
| {% endtab %} |                   |               |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Keycloak Based ExecuteActionEmail action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "action": {
              "type": "string",
              "definition": "Action to execute",
              "example": "FORGOT_EMAIL",
              "default": null
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### ForgotPasswordAction

Resets the password for a user to a given `password`, using `action_token` for user verification.

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                               | Example | Default |
| ------------- | ---------------------------------------- | ------- | ------- |
| Input Element | Json path for the input in event payload | auth    | -       |
| {% endtab %}  |                                          |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Keycloak Based ForgotPasswordAction action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload",
          "example": "auth",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### VerifyEmailAction

Verifies a user email using `action_token` for user verification.

{% tabs %}
{% tab title="Table" %}

| Field         | Definition                               | Example | Default |
| ------------- | ---------------------------------------- | ------- | ------- |
| Input Element | Json path for the input in event payload | auth    | -       |
| {% endtab %}  |                                          |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Keycloak Based VerifyEmailAction action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the input in event payload",
          "example": "auth",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Sessionize

These actions provide ability to create and track sessions for system users as part of gateway functionality.

## Sessionize Actions

### Touch

Initializes or extends an existing session for the given origin and returns that session's id and expiration time.

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Output Element | Json path for the output in response event payload | session | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize Touch action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "session",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition               | Example | Default       |
| ------------ | ------------------------ | ------- | ------------- |
| TTL          | TTL to apply for session | 900000  | Handler's ttl |
| {% endtab %} |                          |         |               |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize Touch action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "ttl": {
              "type": "string",
              "definition": "TTL to apply for the session",
              "example": "900000",
              "default": "Handler's ttl"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Extend

Extends an existing session for the given origin and returns that session's new expiration time.

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Output Element | Json path for the output in response event payload | session | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize Extend action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "session",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition               | Example | Default       |
| ------------ | ------------------------ | ------- | ------------- |
| TTL          | TTL to apply for session | 900000  | Handler's ttl |
| {% endtab %} |                          |         |               |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize Extend action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "ttl": {
              "type": "string",
              "definition": "TTL to apply for the session",
              "example": "900000",
              "default": "Handler's ttl"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### ExtendList

Extends a list of existing sessions for the given origin keys and returns their new expiration time.

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                              | Example | Default |
| -------------- | ------------------------------------------------------- | ------- | ------- |
| Input Element  | Json path for the list of session keys in event payload | list    | -       |
| Output Element | Json path for the output in response event payload      | session | -       |
| {% endtab %}   |                                                         |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize ExtendList action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "inputElement": {
          "type": "string",
          "definition": "Json path for the list of session keys in event payload",
          "example": "list",
          "default": null
        },
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "session",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition                | Example | Default       |
| ------------ | ------------------------- | ------- | ------------- |
| TTL          | TTL to apply for sessions | 900000  | Handler's ttl |
| {% endtab %} |                           |         |               |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize ExtendList action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "ttl": {
              "type": "string",
              "definition": "TTL to apply for the sessions",
              "example": "900000",
              "default": "Handler's ttl"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

### Expire

Expires an existing session for the given origin.

### Stitch

Stitches an existing session, identified by `oldId` and `oldType` in origin parameters, with a new origin and returns the final session's id and expiration time.

{% tabs %}
{% tab title="Table" %}

| Field          | Definition                                         | Example | Default |
| -------------- | -------------------------------------------------- | ------- | ------- |
| Output Element | Json path for the output in response event payload | session | -       |
| {% endtab %}   |                                                    |         |         |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize Stitch action eventMeta fields",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "outputElement": {
          "type": "string",
          "definition": "Json path for the output in response event payload",
          "example": "session",
          "default": null
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}

With event metadata parameters as:

{% tabs %}
{% tab title="Table" %}

| Parameter    | Definition               | Example | Default       |
| ------------ | ------------------------ | ------- | ------------- |
| TTL          | TTL to apply for session | 900000  | Handler's ttl |
| {% endtab %} |                          |         |               |

{% tab title="JSON Schema" %}

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Sessionize Stitch action eventMeta.parameters",
  "type": "object",
  "properties": {
    "eventMeta": {
      "type": "object",
      "properties": {
        "parameters": {
          "type": "object",
          "properties": {
            "ttl": {
              "type": "string",
              "definition": "TTL to apply for the session",
              "example": "900000",
              "default": "Handler's ttl"
            }
          }
        }
      }
    }
  }
}
```

{% endtab %}
{% endtabs %}


# Transform Step

This step performs a transformation on an event and continues with its output to the next step.

<figure><img src="/files/SYXezJIl4K85CbanUlbF" alt=""><figcaption><p>Transform Definition</p></figcaption></figure>

{% hint style="info" %}
A transform step is always executed locally by the saga orchestrator runner.
{% endhint %}

Transform steps allow modifying structure of an event payload, which may be required when integrating with 3rd party services or returning data in a format preferred by the front-end applications.

Dragging and dropping a transform step from the icon bar of a saga adds a new transformation, which can be configured by clicking on the edit icon displayed when hovering its node. The following fields are used for overall settings of the transformation:

* **Name:** Descriptive name of the step, which will be displayed on the saga flow.
* **Auto Fail:** Whether failure of this step should automatically fail the whole saga flow. If not set to true (or the saga itself has auto fail setting), error status should be handled separately.
* **Description:** Verbal description of the step, for reference and documentation.
* **Stroke:** Color to use for drawing borders of the step, for visual purposes.
* **Fill:** Color to use for filling the step node, for visual purposes.

The actual functionality of a transform step is defined using settings listed on the parameters tab:

* **Transform Class:** Type of the transform handler to use (such as JMESPath Transformation, Add Value to Payload).
* **Transform Parameters:** Transform class specific list of parameters to use.&#x20;

## Transform Step Data Schema

```json
	{
		"transformClass": {
			"type": "string",
			"description": "The Java class for transformation (e.g., `com.rierino.handler.transform.JMESPayloadTransform`)"
		},
		"transformParameters": {
			"type": "object",
			"description": "Key-value pair parameters used by the specific transform class (such as pattern for JMESPath transform class)"
		}
	}
```


# Transform Classes

It is possible to define any number and type of new transformation classes with specialized configurations. Rierino is shipped with the following default classes:

## Payload Manipulation

### Add Value To Payload

This class(*com.rierino.handler.transform.AddToPayloadTransform*) extends a selected payload element with a constant Json node provided as string.

| Parameter | Definition                                      | Example        |
| --------- | ----------------------------------------------- | -------------- |
| element   | Json path of payload element to create / extend | parameters     |
| value     | Json string to extend element with              | {"test":false} |

### Transform Payload with JMESPath

This class(*com.rierino.handler.transform.JMESPayloadTransform*) transforms event payload using a JMESPath pattern.

| Parameter      | Definition                                                                            | Example                                                      |
| -------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| pattern        | JMESPath pattern to calculate value                                                   | {language:parameters.language, currency:parameters.currency} |
| patternElement | Json path to payload element which defines JMESPath pattern to calculate value        | parameters.pattern                                           |
| extend         | Whether calculated value should replace payload or extend it                          | true                                                         |
| store          | Whether JMESPath expression should be cached for future executions (defaults to true) | false                                                        |
| inputElement   | Json path for the input element to transform                                          | parameters                                                   |
| outputElement  | Json path to output calculated results                                                | result                                                       |
| errorAs        | Element to include error message on, if the pattern fails                             | error                                                        |

{% embed url="<https://jmespath.org>" %}
JMESPath Page
{% endembed %}

### Transform Payload Array with JMESPath

This class(*com.rierino.handler.transform.JMESArrayPayloadTransform*) transforms array elements of an event payload using a JMESPath pattern with access to a parent data element as well (which is not supported by JMESPath out of box).

| Parameter      | Definition                                                                                                        | Example                                            |
| -------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| pattern        | JMESPath pattern to calculate value                                                                               | {parentValue: data.value, entryValue: entry.value} |
| patternElement | Json path to payload element which defines JMESPath pattern to calculate value                                    | parameters.pattern                                 |
| dataElement    | Json path to payload element which will populate "data" field in JMES input                                       | parameters.parent                                  |
| arrayElement   | Json path to payload element which is an array will populate "entry" field in JMES input with each of its entries | parameters.results                                 |
| entryPath      | Json path to extract specific element from array "entry" to simplify JMESPath patterns                            | data.main                                          |
| filter         | Whether JMESPath returns a boolean value for filtering arrayElement only (defaults to true)                       | false                                              |
| excludeNulls   | Whether null results should be excluded from JMESPath results (defaults to true)                                  | false                                              |
| outputElement  | Json path to output results on event payload (null replaces arrayElement itself)                                  | output                                             |
| store          | Whether JMESPath expression should be cached for future executions (defaults to true)                             | false                                              |
| errorAs        | Element to include error message on, if the pattern fails                                                         | error                                              |

### Add Expression To Payload

This class(*com.rierino.handler.transform.AddExpToPayloadTransform*) adds the result of an expression to event payload.

| Parameter  | Definition                                                  | Example |
| ---------- | ----------------------------------------------------------- | ------- |
| element    | Json path of payload element to use / extend                | date    |
| as         | Json path to return results in (null for replacing element) | result  |
| expression | Expression to execute                                       | now     |

This transformation allows additional parameters based on the expression value:

#### replace

Replaces given char sequence in element with a new char sequence.

| Parameter   | Definition           | Example |
| ----------- | -------------------- | ------- |
| target      | Text to find         | old     |
| replacement | Text to replace with | new     |

#### replaceAll

Replaces all matchings of a regex in element with a new char sequence.

| Parameter   | Definition           | Example |
| ----------- | -------------------- | ------- |
| target      | Regex to find        | \[0-9]  |
| replacement | Text to replace with | 0       |

#### regex

Replaces named parameters found from a regex in element with given pattern.

| Parameter   | Definition              | Example                                   |
| ----------- | ----------------------- | ----------------------------------------- |
| target      | Regex to find           | /source/(?\<folder>\\\w+)/(?\<file>\\\w+) |
| replacement | Pattern to replace with | /target/${folder}/${file}                 |

#### substring

Returns substring from element.

| Parameter  | Definition                                       | Example |
| ---------- | ------------------------------------------------ | ------- |
| beginIndex | Char index to start from                         | 0       |
| endIndex   | Char index to end with (null means till the end) | 5       |

#### split

Splits element into an array with a given delimiter.

| Parameter | Definition             | Example |
| --------- | ---------------------- | ------- |
| delimiter | Regex delimiter to use | ,       |

#### join

Joins an element array with a given delimiter.

| Parameter | Definition                 | Example |
| --------- | -------------------------- | ------- |
| delimiter | Delimiter to join elements | ,       |

#### concat

Concatenates element with a prefix and/or suffix.

| Parameter | Definition       | Example |
| --------- | ---------------- | ------- |
| prefix    | Prefix to append | pre\_   |
| suffix    | Suffix to append | \_post  |

#### kv

Performs a lookup for configuration parameter value - such as secrets or connection parameters.

| Parameter | Definition                                    | Example                |
| --------- | --------------------------------------------- | ---------------------- |
| parameter | Parameter reference                           | rierino.mongo.main.uri |
| type      | Lookup/injection type (static, dynamic, both) | static                 |

### Lookup & Map within Payload

This class(*com.rierino.handler.transform.LookupPayloadTransform*) traverses a list of ids in event payload and enriches them with another list matching on ids.

| Parameter  | Definition                                                                        | Example |
| ---------- | --------------------------------------------------------------------------------- | ------- |
| lookup     | Json path of payload element to lookup from                                       | lookup  |
| lookupId   | Name of id fields in lookup array                                                 | id      |
| traverse   | Json traverse expression of payload element to enrich                             | list.\* |
| traverseId | Name of id fields in traverse entries                                             | id      |
| as         | Name of field to inject lookup values in traversed path (null for merged results) | -       |

### Use Script on Payload

This class(*com.rierino.handler.transform.ScriptingPayloadTransform*) allows using scripting languages to transform event payload.

| Parameter   | Definition                                                               | Example                                          |
| ----------- | ------------------------------------------------------------------------ | ------------------------------------------------ |
| script      | Full scripting code returning output (or editing event payload directly) | value \* 2                                       |
| language    | Scripting engine to use (if helperClass is not defined)                  | groovy                                           |
| helperClass | Java class name for the scripting engine helper                          | com.rierino.handler.util.helper.JavaScriptHelper |
| nodePath    | Json path to the input node in event payload                             | parameters                                       |
| paramsPath  | Key-value pairs for passing multiple variables from different Json paths | foo=data.in,bar=data.val                         |
| outputPath  | Json path to output on event payload                                     | data.output                                      |

### Generate ID in Payload

This class(*com.rierino.handler.transform.GenerateIDTransform*) uses an [ID generator](/devops/microservices/building-blocks/data-sources/id-generators) to create a unique ID inside the payload.

| Parameter   | Definition                                                               | Example                                                                 |
| ----------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| element     | Json path to add generated id on                                         | id                                                                      |
| generator   | ID generator class                                                       | com.rierino.handler.util.generator.NumberIDGenerator                    |
| generatorId | [Unique ID](#user-content-fn-1)[^1] assigned to generator                | product\_gen                                                            |
| version     | ID generator version to use                                              | 1                                                                       |
| \*          | All additional parameters that are applicable for the ID generator class | numberGenerator=com.rierino.handler.util.generator.EpochNumberGenerator |

{% hint style="warning" %}
ID generators are cached inside GenerateIDTransform by generatorId value, so, parameter changes are not applied unless the service is restarted or version parameter value is updated. Both actions create a new instance of the generator.
{% endhint %}

### Copy In Payload

This class(*com.rierino.handler.transform.CopyInPayloadTransform*) copies data from one section of payload to another.

| Parameter | Definition                                        | Example            |
| --------- | ------------------------------------------------- | ------------------ |
| from      | Json path to copy from                            | parameters.filters |
| to        | Json path to copy to                              | filters            |
| move      | Whether element should be moved instead of a copy | true               |

### Remove From Payload

This class(*com.rierino.handler.transform.ReducePayloadTransform*) removes list of elements from event payload.

| Parameter | Definition                                   | Example                           |
| --------- | -------------------------------------------- | --------------------------------- |
| list      | Comma separated list of Json paths to remove | product.metadata,product.internal |

### Do Nothing

Thıs class(com.rierino.handler.transform.NoopTransform) performs no action on the event, and is typically used as a placeholder.

## Metadata Access

### Add Error To Payload

This class(*com.rierino.handler.transform.AddErrorToPayloadTransform*) copies event error details to event payload.

| Parameter | Definition                                      | Example |
| --------- | ----------------------------------------------- | ------- |
| element   | Json path of payload element to create / extend | error   |

### Add Metadata To Payload

This class(*com.rierino.handler.transform.AddMetaToPayloadTransform*) copies request metadata to event payload as "meta" element.

### Append Partition To Payload

This class(*com.rierino.handler.transform.AppendPartitionToPayloadTransform*) appends partition digits from a payload element to another payload element. Typically used for creating a linked entity with the same partition as a master entity.

| Parameter | Definition                                    | Example   |
| --------- | --------------------------------------------- | --------- |
| from      | Json path for id to get partition digits from | guest.id  |
| to        | Json path to add partition digits to          | basket.id |
| char      | Delimiter before the partition digits         | -         |

### Add Event Parameter To Payload

This class(*com.rierino.handler.transform.EventParameterToPayloadTransform*) copies list of elements from full event contents to payload. Parameters defined for this transform step act as key value pairs, where keys are the target payload paths and values are the event source content paths (e.g. sessionId=requestMeta.sessionId).

### Add Request Id To Payload

This class(*com.rierino.handler.transform.RequestIdToPayloadTransform*) adds requestId to event payload.

| Parameter | Definition                                      | Example   |
| --------- | ----------------------------------------------- | --------- |
| element   | Json path of payload element to create / extend | requestId |

### Set Event Result

This class(*com.rierino.handler.transform.SetResultTransform*) resets the result data of an event, typically used for returning specific contents in case of an error.

| Parameter        | Definition                                                                                  | Example                     |
| ---------------- | ------------------------------------------------------------------------------------------- | --------------------------- |
| status           | Result status to set for the event                                                          | FAIL                        |
| errorPattern     | JMES pattern to apply on event payload to return sensitive error payload (i.e. logged only) | {"failQuery": query}        |
| errorSafePattern | JMES pattern to apply on event payload to return safe error details (i.e. passed to client) | {"failId": id}              |
| errorCode        | Error code to return for the event                                                          | 123                         |
| errorMessage     | Error message to return for the event                                                       | Could not find requested id |
| errorHttp        | Http error code to return for the event                                                     | 404                         |

### Add Claims To Payload

This class(*com.rierino.handler.transform.AddClaimsToPayloadTransform*) adds claims from request metadata (if configured in gateway token) to event payload.

| Parameter | Definition                                                          | Example |
| --------- | ------------------------------------------------------------------- | ------- |
| element   | Json path of payload element to create / extend (claims as default) | user    |

[^1]: Should not overlap with existing states or other ID generators


# Condition Step

This step performs a condition check and directs flow of saga based on its outcome.

<figure><img src="/files/e6DSYDoDYAfjr0rons7P" alt=""><figcaption><p>Condition Definition</p></figcaption></figure>

Condition steps allow branching out alternative flows based on input parameters, data received or calculated between saga steps. Output of a condition step is a condition value calculated by this step, which is then used by the links to define which step should be followed after this condition step.

Dragging and dropping a condition step from the icon bar of a saga adds a new condition, which can be configured by clicking on the edit icon displayed when hovering its node. The following fields are used for overall settings of the condition:

* **Name:** Descriptive name of the step, which will be displayed on the saga flow.
* **Auto Fail:** Whether failure of this step should automatically fail the whole saga flow. If not set to true (or the saga itself has auto fail setting), error status should be handled separately.
* **Description:** Verbal description of the step, for reference and documentation.
* **Stroke:** Color to use for drawing borders of the step, for visual purposes.
* **Fill:** Color to use for filling the step node, for visual purposes.

The actual functionality of a condition step is defined using settings listed on the parameters tab:

* **Condition Class:** Type of the condition handler to use (such as Element Value or Error Code).
* **Condition Parameters:** Condition class specific list of parameters to use as listed below.&#x20;

{% hint style="info" %}
A condition is always executed locally by the saga orchestrator runner.
{% endhint %}

## Condition Step Data Schema

```json
	{
		"conditionClass": {
			"type": "string",
			"description": "The Java class condition logic (e.g., `com.rierino.handler.saga.condition.ElementValueCondition`)"
		},
		"conditionParameters": {
			"type": "object",
			"description": "Key-value pair parameters used by the specific condition class (such as pattern for JMESPath condition class)"
		}
	}
```


# Condition Classes

It is possible to define any number and type of new condition classes with specialized configurations. Rierino is shipped with a number of default classes.

## ElementValueCondition

This class(*com.rierino.handler.saga.condition.ElementValueCondition*) returns the value of a specific payload element to be used as a condition value.

| Parameter | Definition                      | Example             |
| --------- | ------------------------------- | ------------------- |
| element   | Json path of the element to use | parameters.language |

## ErrorCodeCondition

This class(*com.rierino.handler.saga.condition.ErrorCodeCondition*) returns the value of event error code (or '-' if null) to be used as a condition value.

## ErrorHttpCondition

This class(*com.rierino.handler.saga.condition.ErrorHttpCondition*) returns the http status code of event error (or '-' if null) to be used as a condition value.

## EventStatusCondition

This class(*com.rierino.handler.saga.condition.EventStatusCondition*) returns the status name of event result (or '-' if null) to be used as a condition value.

## HasElementCondition

This class(*com.rierino.handler.saga.condition.HasElementCondition*) returns "true" or "false" based on whether a specific payload element exists or not.

| Parameter | Definition                      | Example     |
| --------- | ------------------------------- | ----------- |
| element   | Json path of the element to use | customer.id |

## JMESCondition

This class(*com.rierino.handler.saga.condition.JMESCondition*) returns a text value based on evaluation of a JMESPath pattern.

| Parameter      | Definition                                                                            | Example              |
| -------------- | ------------------------------------------------------------------------------------- | -------------------- |
| pattern        | JMESPath pattern to apply                                                             | language=='enUS'     |
| patternElement | Json path to payload element which defines JMESPath pattern to apply                  | parameters.condition |
| store          | Whether JMESPath expression should be cached for future executions (defaults to true) | false                |
| inputElement   | Json path of the payload to run pattern on                                            | parameters           |

{% embed url="<https://jmespath.org>" %}
JMESPath Page
{% endembed %}

## JsonSchemaCondition

This class(*com.rierino.handler.saga.condition.JsonSchemaCondition*) evaluates event payload against a Json schema constraints and returns "success" or "fail".

| Parameter | Definition                           | Example           |
| --------- | ------------------------------------ | ----------------- |
| schema    | String representation of Json schema | {"type":"string"} |

{% embed url="<https://json-schema.org>" %}
Json Schema Page
{% endembed %}

## RegexCondition

This class(*com.rierino.handler.saga.condition.RegexCondition*) evaluates event payload against a regex expression and returns "true" or "false".

| Parameter | Definition                           | Example            |
| --------- | ------------------------------------ | ------------------ |
| element   | Json path of the element to evaluate | customer.data.name |
| regex     | Regex expression to evaluate         | \[a-zA-Z]+         |

## SuccessCondition

This class(*com.rierino.handler.saga.condition.SuccessCondition*) returns "success" or "fail" based on whether the previous saga step had an error or not.


# Step Link

Links between saga steps define the flow of execution from start to end.

<figure><img src="/files/Xm9FT6QaMoOyPxfBdaru" alt=""><figcaption><p>Link Definition</p></figcaption></figure>

Links define the order and physical flow of data between different saga steps. It is possible to link two saga steps with each other, by clicking on the link icon on the source step first and then clicking on the target step.

## Link Configuration

Once link is created, it should be edited using the edit icon displayed when it is selected, using the following settings:

* **Name:** Descriptive name of the link, which is displayed on saga flow.
* **Condition Values\*:** List of values for which this link will be followed. This setting is only applicable if the source of the link is a condition which produces different values for different event inputs. If condition values is left empty, this link is always followed. If it is set to "\*", this link is followed if no other link qualifies for the current condition. Apart from flows which have special merge steps, or asynchronous activities, it is advisable to have only 1 link qualifying for each possible condition value.
* **System:** Alias of the streaming system which will be used for sending an event to its target event runner. It is only used when the target is an event step and defaults to the default system when left blank.
* **Stream\*:** Alias of the stream which will be used for sending the event. Similar to system setting, it is only used when the target is an event step. A special value "local" is used for executing the next step on the same runner which is orchestrating current saga flow. Once you enter a stream name, you can click on the icon over this field to see which runners are configured to receive requests on this stream, to make sure that you are using the right stream name for coordination.
* **Description:** Verbal description of the link, used for reference and documentation.
* **Priority:** Numerical priority of the link, used for selecting execution order of links in case more than one link condition is met. Links with higher value are followed first.
* **Stroke:** Color of the link, used for visualization of the saga flow.
* **Key Strategy:** For links executing on partitioned streams (e.g. Kafka topics), key strategy defines data element to use as the partition key. This setting is not used for local or REST based communications, but is important when microservices consuming the stream have states specific to their assigned partitions (e.g. using local caches of their respective partitions only or using a partitioned write event handler avoiding write conflicts between instances). The following alternative strategies are available:
  * **Request ID:** Uses ID field in request metadata, which is a globally unique value assigned by the API gateway. Since this value stays the same throughout a request's flow, it is useful when the partition needs to be the same between different event steps.
  * **Input ID:** Uses ID field in event payload's input element, which is defined by the event metadata settings. This strategy is typically used for directing events to database microservices, ensuring selecting of the partition relevant to target record's id.
  * **Output ID:** Similar to input ID, but uses the ID field in event payload's output element instead.
  * **Event Path:** Uses an element from event's full contents, specified by the "key path" parameter. This strategy is useful for selecting a partition based on non-payload fields, such as request origin.
  * **Payload Path:** Uses an element from event payload, specified by the "key path" parameter. This strategy is useful for selecting a partition based on a non-input id field.
  * **Fixed (Zero):** Sends all events to partition 0. Typically used for development, testing or single partition deployments only.
  * **Random:** Sends all events to a random partition with an option to define the list of possible values to select from (e.g. when a specific partition is overloaded or down). Typically used for balancing event load across instances.
  * **Round Robin:** Sends sequential events to different partitions in a round robin version, with an option to define the list of possible values to select from. Similar to random strategy, typically used for balancing event load across instances.

{% hint style="info" %}
Key strategy is a critical decision, as it allows sending requests to the right runners in case of a partitioned deployment (such as basket data cahinched by partition on different runners). In non-partitioned use cases, typically request ID or random keys are used.
{% endhint %}

{% hint style="info" %}
When link system is a "rest" connection, it uses \[base url]/\[stream]/\[action] call to the target event runner.
{% endhint %}

{% hint style="info" %}
Starting from version 0.8.2, if Stream is left empty, "local" is used as the default value and the next step is executed locally, to simplify saga creation process.
{% endhint %}

## Automated Condition Values

Event steps automatically produce their result status (e.g. "SUCCESS", "FAIL") as the condition value, which can be used to split flows based on success/fail of an event step without adding an explicit condition step to check its result.


# Injecting Variables

Reference for injecting variables into saga steps and queries using payload fields, defaults, and built-in values.

[API flows](/devops/api-event-and-process-flows) as well as [queries](/configuration/queries) allow use of variables for creating more dynamic actions without the need to create complex conditional flows or query logic.

Variables can be referenced within metadata fields of [event steps](/devops/api-event-and-process-flows/configuring-saga-steps/event-step) as well as query fields and conditions using %%VARIABLE%% notation, with the following extra features:&#x20;

* Using multiple variables within a single field: %%VARIABLE1%%\_%%VARIABLE2%%.
* Using default value when missing: %%VARIABLE|DEFAULT%%

Opening the **Variable** screen from **Devops** app menu or navigation bar, you will come across the list of defined variables, allowing adding new entries as required. It is recommended to define variables on this screen before using them in flows or queries, as this approach ensures type safety while providing ability to add validation constraints on variable values. It is also possible to use variables not listed on this screen, which automatically leads to retrieving variable value from input payload with the assumption that the variable is of string type.

Variable values are extracted from payload of the event which is currently being processed by a runner, with the following flow:

* If a path\_\[VARIABLE] parameter is defined in event metadata, it is used as the variable path
* Else, if the variable is defined in Variables screen, path provided in that screen is used
* Else, variable name is used as its path

If the variable path starts with $., then it is searched in the root of event payload, otherwise it is searched in the input element payload.

In addition to event payload values, following built-in variables can be used to access special values:

| Variable                             | Meaning                                                                        |
| ------------------------------------ | ------------------------------------------------------------------------------ |
| .id                                  | Runner id                                                                      |
| .name                                | Runner name                                                                    |
| .deploymentVersion                   | Runner deployment version                                                      |
| .parameters.\[parameter]             | Runner parameter \[parameter]                                                  |
| .system.parameters.\[parameter]      | Runner parameter \[parameter] for system matching event metadata domain        |
| .state.partition                     | Runner partition for state matching event metadata domain                      |
| .state.partitionMod                  | Runner partition modulo for state matching event metadata domain               |
| .query.parameters.\[parameter]       | Runner parameter \[parameter] for query manager matching event metadata domain |
| @.\[element]                         | Event element \[element] (e.g. @.requestMeta.id)                               |
| $!{{\[setting]}} or #!{{\[setting]}} | Ephemeral key-value / secret setting in runner configuration                   |
| ${{\[setting]}} or #{{\[setting]}}   | Key-value / secret setting in runner configuration                             |

{% hint style="info" %}
In queries, if the value is not available for a variable, the related field or condition is omitted (e.g. condition is considered as true, field is not returned in response). Making it possible to use a single query configuration for different combination of input variables.&#x20;
{% endhint %}


# Microservices

Microservices sit at the heart of Rierino platform, for building flexible and scalable backend applications.

Typical microservice development with Rierino follows 3 main steps, building and using reusable components in each step:

1. Configuration of micro-composable [elements](/devops/microservices/building-blocks), which define data stores and streams to use, key functions to execute and systems to access. These elements are configured once and utilized by multiple runners, minimizing workload and user errors, while making it possible to create infinite number of runners with plug and play capabilities.
2. Assembly of [runners](/devops/microservices/service-runners), which is basically defining list of micro-composable elements to include inside a runner, and defining relations between them (such as which handler to respond to which type of requests coming from a stream). A runner itself does not mandate how it is deployed (e.g. which cloud provider, which containerization), isolating deployment from design.
3. Structuring of [deployments](/devops/microservices/deployment-packages), which describes how and where to deploy each runner, including required CD settings. Typically, a deployment is executed by triggering a specific Jenkins or similar automation task with specific parameters. A deployment can include one or more runners, which allows for shrinkage or expansion of scale.

{% embed url="<https://www.youtube.com/watch?v=qIJNBnN6v8U>" %}


# Service Runners

Runners are the main components for creating and running microservices across the platform.

![Runner UI](/files/tModgmWYfXmskqtBdsXl)

A typical runner listens from various streams, uses action and handlers to respond to received data and sends its response to other streams.

A runner is built with a no-code approach, by adding elements through the Devops app.&#x20;

To simplify reuse of elements shared across multiple runners, it is possible to define a set of base runners, which others can extend from. If a runner extends another runner, all of its elements, input/output streams and settings are copied into the new runner during execution. If the new runner includes an element with the same alias, it extends & overrides base runner's element parameters.


# Using the Runner Screen

How to use the Runner screen to browse runners, edit runner details, add elements, and manage graph layout.

Opening the **Runner** screen from **Devops** app menu or navigation bar, you will come across a visual graph editor, allowing design of runners by adding new elements.

Runners are listed on the left side of this screen, grouped by their domain information.

The runner screen has similar functionalities as any other UI screen, such as save, delete, duplicate, item import and export actions and menus. Runners designed on this screen are stored in JSON format, the same as any other data source.

On top of this screen, you will notice that the runner ID is editable, this allows you to assign a meaningful unique ID to each runner for your reference. Since these IDs will be recorded within event logs, this approach makes them more manageable than assigning random or sequential IDs.

<figure><img src="/files/yw1qNbsqv1zLuMpYYaJD" alt=""><figcaption><p>Runner Icon Bar</p></figcaption></figure>

Below the ID field, you can find the icon bar, which allows construction of a runner as well as changing its layout.

If you click on the edit icon on the left of this bar, you will see the pop-up editor for defining runner details.

At the center of the icon bar, you can see different types of runner elements, which you can and drop on to the grid to add new systems, states and other element types.

At the right side, you can see the icons for changing the layout of runner after you've added its elements, such as automatically aligning steps, hiding / displaying the grid as well as changing its size.

{% hint style="warning" %}
When a runner configuration changes, it is important to execute a "Rebuild" command, as existing deployments of a runner are not updated automatically unless rebuildMs setting is configured explicitly. This is a design decision made to avoid unintended updates to runners due to user errors. &#x20;
{% endhint %}


# Defining a Runner

Reference for a runner’s core definition fields, including status, domain, base runners, and description.

<figure><img src="/files/drmkO1wm5ydBVvd1zb3R" alt=""><figcaption><p>Runner Definition</p></figcaption></figure>

Clicking on the edit icon displays runner definition form, which has the first tab with the following data fields:

* **Name:** Descriptive name for the runner, which will be used as the label on runner screen and listings.
* **Status\*:** Whether the runner is currently active or not.
* **Domain:** Used for grouping runners within logical business domains (e.g. admin, cms).
* **Base Runners:** List of runners this runner should inherit elements and settings from. This configuration allows reuse of predefined lists of runner elements for functionalities shared among different runners (such as receiving commands, running queries), instead of copying same list of elements to each individually. Typically used base runners include:
  * Samza Base: Includes global configurations for all Samza runners
  * Spring Base: Includes global configurations for all Spring runners
  * Query Base: Includes state configurations for all runners with query handlers
  * Variable Base: Includes state configurations for all runners using variables (e.g. query and saga handlers)
  * Saga Base: Includes state configurations for all runners with saga handlers
  * Command Base: Includes stream configurations for all runners which should be listening to commands (i.e. effectively all runners)
* **Description:** Verbal description of the runner, used for referential purposes and documentation.

{% file src="/files/YmDM1DD5wC5D8TLq4soo" %}
Example Runner Definition (Can be Imported on Runner Screen)
{% endfile %}


# Managing Runner Settings

Reference for configuring runner I/O, partition selection, and runner-level settings such as rebuild, commit, logging, and handler access.

<figure><img src="/files/GvZrLNUAcpOX9Cw9aVrd" alt=""><figcaption><p>Runner I/O</p></figcaption></figure>

Each runner specifies the list of streams it consumes and produces to via its I/O settings:

* **Input Streams:** List of streams the runner should consume from.
* **Output Streams:** List of streams the runner should produce to.
* **Partition Stream:** Name of the stream which should be used for selecting runner partition, unless the runner is assigned a static partition.

These settings are mainly required for event streams (e.g. Kafka), and are not critical for REST or websocket based I/O operations. When a runner starts, it connects to the event streams listed in these configurations, which can not be modified while the runner is running (as it would affect partition assignments of runners using the same streams).

Partition stream is important when a runner is listening to multiple event streams, some of which may be used in broadcasting mode. Selecting a specific stream to assign partition to the runner aligns state partition selection strategies with stream feeds, so, when required you should be picking the main data stream for this entry.

<figure><img src="/files/7L3AixuhNsgvv8nQ2T4Y" alt=""><figcaption><p>Runner Settings</p></figcaption></figure>

The final tab of runner definition screen is the settings tab, which allows entry of runner-level settings when required (such as rebuildMs).&#x20;

A typical use case for this tab is for assigning default stream to RPC runners (e.g. defaultStream = saga), which allows making requests directly to saga paths, without specifying the stream name.

All runners share the following settings that can be also configured from this screen:

| Parameter                              | Definition                                                                                                        | Example   |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | --------- |
| rierino.runner.\[runner].rebuildMs     | Milliseconds period to check whether runner is updated and automatically rebuild                                  | 30000     |
| rierino.runner.\[runner].commitMs[^1]  | Milliseconds period to commit current records / resume tokens                                                     | 10000     |
| rierino.runner.\[runner].logDetail     | When to perform detailed logging for the runner (overrides log\_level setting, with options as "never", "always") | always    |
| rierino.runner.\[runner].allowHandlers | Whether the runner should allow use of handlers not mapped on to individual streams for event calls               | crud-0001 |

[^1]: Should not be used with Samza runners since Samza has its custom implementation of checkpoints


# Adding Runner Elements

Guide to adding runner elements, setting aliases and member types, overriding settings, and wiring element dependencies.

Elements are the building blocks for all runners, hence the microservices. They also provide the mechanism for extending Rierino capabilities by integrating new systems, databases and functions. While Rierino is shipped with a rich set of runner elements, it is possible to create new elements to address any new business use case.

Elements can be added to runners simply by dragging and dropping from the runner toolbar, based on the type of element you would like to add.

<figure><img src="/files/8Wro8dHy74xdXCqk0mWN" alt=""><figcaption><p>Runner Element Configuration</p></figcaption></figure>

Once added, you can click on the edit icon for your new element to configure its common settings:

* **Element\*:** Selection of the element to add to the runner.
* **Alias\*:** Unique name to assign to the runner element, which will be used for referencing to it in event metadata and by other runner elements. It is possible to use the same element with different aliases within the same or across different runners. An alias is similar to assigning an object instance a variable name for reference.
* **Member Type\*:** Whether the element requires runner to restart upon its change (structure), can be reinstantiated with a rebuild command (operation) or even simply reassigned using a remap command (mapping). Within out-of-box elements, only event streams need to be configured as structure members, as their partition assignments are done during system start. The remaining elements are typically configured as operation members, aside from action elements, which can be configured as mapping members.
* **Status:** Whether the element is active or not. If the status is set to Draft or Passive, the runner does not load element configuration during runtime.
* **Description:** Verbal definition of the element for referential purposes.

Once you select the element from the dropdown, you can find its predefined settings from the element tab and decide whether you would like to override any of these settings.

Most runner element types allow overriding of their predefined settings via the override tab:

* **Setting Name\*:** Specific setting to replace (e.g. parameter.query.state)
* **Setting Description:** Verbal definition of reason for replacement for referential purposes.
* **Setting Value\*:** New value to apply for this setting.
* **Runner Type:** Type of runner to apply setting for (in case it is only applicable for a certain runner implementation such as samza).

Actions and streams allow assignment of default or mandatory event metadata settings as well, which can be useful for enforcing use of specific states for requests received on a specific input stream, or avoiding repetition of same metadata for each request. These are set on metadata tab for these types of elements:

* **Name:** Metadata to override (e.g. domain, handler).
* **Value:** Value to set metadata field to (e.g. product, read).
* **Override:** Whether the value should be used as default (hence, can be replaced by the requesting party) or override (hence, is mandatory).
* **Stream:** For actions, indicates which input stream should trigger metadata override.

Handlers and roles can also relate themselves to specific input / output streams, so that each event received from a specific input stream is handled by a specific handler or role, and roles can forward their results to a specific output stream. These are set on the I/O tab for these types of elements:

* **For Handlers:**
  * **Role:** Alias of the role to use for data received ("event" for typical events, "journal", "pulse", "command" or custom roles for other types).
  * **Inputs:** List of input streams that should be treated as a call to the handler with the given role (e.g. productq).
* **For Roles:**
  * **Inputs:** List of input streams that should be treated as data for this role (e.g. command).
  * **Outputs:** Input to "system-stream-key path" mapping for directing received role data to output streams on the right partition (e.g. kafka\_command-command\_result-request.id).

You can add as many elements as you like to your runner, which will provide it with access to other systems, load it with new functionalities or allow it to use predefined list of actions. The number and mix of elements you add to a runner depends on your preferred deployment strategy (e.g. building very specialized microservices with few elements that have low resource consumption or building more monolithic services with many elements serving variety of requests).

As you add new elements to a runner, you will notice that they are automatically linked to each other, based on their dependencies (such as a state manager linking to the database system it is defined for). Typically, if you have streams, state or query managers without links to any system elements, you most likely forgot to add their dependencies to your runner.&#x20;

Essential links between elements are as follows:

* **System - Stream:** Streams typically rely on systems for getting shared connection properties such as server ips.
* **System - State / Query:** State and query managers typically rely on systems for getting shared connection properties such as connection strings.
* **Handler - Action:** Actions require a handler for execution, as they are mainly logical mappings of function names to handler implementations.
* **State - State:** Some states use others as cache or loaders.


# Deploying Runners

Overview of how runner configurations are deployed, the core deployment parameters, and the runtime commands available after rollout.

Runner configurations do not mandate deployment of these capabilities on a specific platform. It is possible to define any number and type of new runners using different programming languages or frameworks. Runners shipped with Rierino for different use cases are listed in this section.

Typical deployment requires only 3 parameters in a properties file or via [Deployments](/devops/microservices/deployment-packages) screen:

| Parameter                                  | Definition                                                                           | Example                                   |
| ------------------------------------------ | ------------------------------------------------------------------------------------ | ----------------------------------------- |
| rierino.runner.\[runner].class             | Fully qualified class name for the runner                                            | com.rierino.runner.spring.CRUDEventRunner |
| rierino.runner.\[runner].element           | Id of the runner configuration                                                       | crud-0001                                 |
| rierino.runner.\[runner].deploymentVersion | Version of the runner deployment (allows multiple versions running at the same time) | 1                                         |

Once designed and deployed, it is possible to send certain commands to a runner's instances through the user interface menu (for more commands, [Command Center](/devops/administration/sending-commands) can be used):

* **Ping:** Sends a ping command to all deployments and partitions of a runner and waits for 5 seconds to check if all the runners are healthy.
* **Rebuild:** Sends are build command to update all runner deployments in real-time, which can be used after operational elements of a runner are edited.
* **Deployments:** Lists deployments including the runner.
* **Dependents:** Lists other runners which use a specific runner as a base.


# Spring Runners

These runners are based on Java Spring library.

All relevant Spring configurations are applicable, and can be passed on to these runners using properties files.

All Spring runners accept following configurations, in addition to the common security configurations mentioned in [Gateway & Security](/devops/api-gateway-and-security):

| Parameter                                     | Definition                                                     | Example                                                    | Default |
| --------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------- | ------- |
| rierino.runner.\[name].offset.class           | Fully qualified class name for assigning offsets               | com.rierino.handler.util.generator.ConstantNumberGenerator | -       |
| rierino.runner.\[name].offset.\[parameter]    | Offset generator specific parameters                           | value=5                                                    | -       |
| rierino.runner.\[name].partition              | Partition assigned to runner (used for non-broadcasted topics) | 1                                                          | -       |
| rierino.runner.\[name].authentication.enabled | Whether runner requires authentication for API calls           | true                                                       | false   |
| rierino.runner.\[name].authentication.role    | Role required (on service account) for making API calls        | internal                                                   | -       |

## Authentication

If authentication is enabled on a runner (which is different than authentication on API gateways), the following parameters are also applicable, based on preferred authentication method:

### Simple Authentication

Simplest form of authentication, using a predefined API key without hashing and roles:

| Parameter                                   | Definition                               | Example | Default |
| ------------------------------------------- | ---------------------------------------- | ------- | ------- |
| rierino.runner.\[name].authentication.token | API key used for authenticating requests | DEMO    | -       |

### Hashed Authentication

| Parameter                                         | Definition                                                                                            | Example       | Default |
| ------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------- | ------- |
| rierino.runner.\[name].authentication.secret      | Secret to use for hashing API keys                                                                    | -             | -       |
| rierino.runner.\[name].authentication.algorithm   | Algorithm for hashing API keys                                                                        | MD5           | SHA-256 |
| rierino.runner.\[name].authentication.iterations  | Number of iterations for hashing API keys                                                             | 100           | 1       |
| rierino.runner.\[name].authentication.cache.state | State manager which keeps acceptable hashed keys with their role mappings (should manage its own TTL) | key\_store    | -       |
| rierino.runner.\[name].authentication.system      | System to run a saga on, for validating a hashed API key and returning its roles                      | admin\_core   | -       |
| rierino.runner.\[name].authentication.stream      | Stream to run a saga on, for validating a hashed API key and returning its roles                      | rpc           | -       |
| rierino.runner.\[name].authentication.action      | Action (i.e. saga path) to run, for validating a hashed API key and returning its roles               | ProcessAPIKey | -       |

{% hint style="info" %}
Authentication cache state can be a shared state manager, allowing use of predefined and hashed list of API keys and roles without using Sagas to produce them.
{% endhint %}

## CRUD Event Runner

CRUDEventRunner (*com.rierino.runner.spring.CRUDEventRunner*) is a Spring WebFlux based runner, which accepts typical REST calls through http or https protocols for common CRUD operations.

Each request method and path is mapped on to a specific action and processed based on the elements configured on the runner. Path mappings are as follows:

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}" method="get" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}/{id}" method="get" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}" method="post" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}/{id}" method="post" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}/{id}" method="put" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}/{id}" method="patch" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}/{id}" method="delete" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% openapi src="/files/FCeopQM2neKYgDFnMHzL" path="/{runner}/{state}/@" method="post" %}
[CRUD Runner OpenAPI.yaml](https://1659095931-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FcnDk3J1AzTgg2NFrGPlh%2Fuploads%2Fl8489SLWmfU3WmoWGgpz%2FCRUD%20Runner%20OpenAPI.yaml?alt=media\&token=df4a4bd6-7ba0-4991-a119-bd865495b09e)
{% endopenapi %}

{% hint style="info" %}
CRUD event runner also supports using /\[action]\_\[state] Saga flows for these requests if the input stream is mapped to a Saga event handler.
{% endhint %}

This event runner accepts request metadata in "request\_metadata" header, as a base64 encoded Json string.

## RPC Event Runner

RPCEventRunner (*com.rierino.runner.spring.RPCEventRunner*) is a Spring WebFlux based runner, which accepts remote procedure call type requests through http or https protocols for more customized use cases.

The request path defines the stream and action in /api/\[runner]/\[stream]/\[action] form, and the request body is used as the full event contents, including request metadata and payload itself.

Using /api\_direct instead of /api in calls to these runners allows sending requests in payload form, without requiring full event data format. This option is usable only when making calls directly to the runners from inside the cluster, without passing them through the API gateways.&#x20;

## RSocket Event Runner

RSocketEventRunner(*com.rierino.runner.spring.RSocketEventRunner*) is a RSocket based runner, which accepts continuous requests through socket connections for low latency and frequent use cases.

Message path defines the stream and action in /api/\[runner]/\[stream]/\[action] form, and the message payload is used as the full event contents.

{% embed url="<https://spring.io>" %}
Spring Page
{% endembed %}

{% hint style="info" %}
Spring runners can listen to Kafka streams, but only for command, journal and pulses (and not events or other role data).
{% endhint %}


# Samza Runners

These runners are based on Samza library, receiving requests from Samza consumers (e.g. Kafka) and returning results on Samza producers (e.g. Kinesis).

All Samza configurations are applicable, and can be passed on to these runners using global runner elements.

## Sync Samza Event Runner

SyncSamzaEventRunner(*com.rierino.runner.samza.SyncSamzaEventRunner*) guarantees message order, with blocking properties for each message received.

Name of the input topic is used as the stream and the messages are used as the full event contents.

## Async Samza Event Runner

AsyncSamzaEventRunner(*com.rierino.runner.samza.AsyncSamzaEventRunner*) does not guarantee message order, as it provides certain level of parallelization.

Name of the input topic is used as the stream and the messages are used as the full event contents.

{% embed url="<https://samza.apache.org>" %}
Samza Page
{% endembed %}

{% hint style="info" %}
Samza runners can also communicate with Restful event runners (e.g. as a step inside a Saga flow), which results in synchronous event exchange with the remote runner.
{% endhint %}


# Camel Runners

These runners are based on Apache Camel library, receiving requests from Camel consumers (e.g. Timer) and returning results on Camel producers (e.g. ActiveMQ).

All Camel configurations are applicable, and can be passed on to these runners using global runner elements.

## Camel Event Runner

CamelEventRunner(*com.rierino.runner.camel.CamelEventRunner*) provides a variety of integration options, all of which can be used as input and output streams for use cases that require channels beyond what Spring and Samza runners support.

This event runner can consume message from all input streams mapped to it, with a camelRoute property and produce to any output system with a camelRoute setting. All input messages are converted to Json first and then to the message class defined for the input stream before processing as an event/journal/command, etc. All outputs are converted to an instance of the class required by the output endpoint.

{% embed url="<https://camel.apache.org/>" %}
Apache Camel
{% endembed %}


# Building Blocks

Overview of the runner element types used to define systems, streams, data access, handlers, actions, and runtime behavior.

![Element UI](/files/JRisrXH1Xc0uclU7ZAn1)

Elements describe the functionality, system and database configurations required to build services responding to different types of requests across the platform.

Through combinations of these elements, it is possible to create any microservice without writing single line of code.

There are 10 types of elements, which can be defined using the Rierino admin user interface:

**1.** [**Global Setting**](/devops/microservices/building-blocks/additional-elements/global-settings)**:** Used for describing global settings, which are typically specific to a runner, such as Samza serialization settings (typical settings are already available in standard installations)

**2.** [**Generic Setting**](/devops/microservices/building-blocks/additional-elements/generic-settings)**:** Used for describing settings for a specific prefix, such as "master" system configurations (optional way of configuring systems)

**3.** [**System**](/devops/microservices/building-blocks/systems-integrations)**:** Used for settings which are applicable to all components of a system, such as the URI for a database connection or URL & authentication details for a 3rd party REST system

**4.** [**Stream**](/devops/microservices/building-blocks/data-and-event-streams)**:** Used for describing settings for a data stream, such as a Kafka topic or REST path&#x20;

**5.** [**State Manager**](/devops/microservices/building-blocks/data-sources)**:** Used for describing settings for a data store, such as a MongoDB collection or SQL table&#x20;

**6.** [**Listener**](/devops/microservices/building-blocks/additional-elements/listeners)**:** Used for describing settings of a state listener, which responds to updates on a data store (optional, as CDC mechanism provides more flexible capabilities)

**7.** [**Query Manager**](/devops/microservices/building-blocks/query-and-search-sources)**:** Used for describing settings for a querying a system, such as Elasticsearch or MongoDB&#x20;

**8.** [**Handler**](/devops/microservices/building-blocks/execution-handlers)**:** Used for describing a code or package, which is capable of performing procedures and returning results for requests received&#x20;

**9.** [**Action**](/devops/microservices/building-blocks/additional-elements/actions)**:** Used for describing preconfigured function calls on specific handlers with predefined parameter values&#x20;

**10.** [**Role**](/devops/microservices/building-blocks/additional-elements/roles)**:** Used for describing types of roles some data received from a stream can assume

## Element UI

Opening the **Element** screen from **Devops** app menu or navigation bar, you will come across an editor, allowing definition of elements.

### **Definition**

Definition tab is used for defining basic properties of elements, such as name, description and id.

### **Settings**

Settings page is used to populate element type specific properties of each element. Applicable settings for each element type are listed on related element page.




---

[Next Page](/llms-full.txt/1)

