Docs
/
Components
/

Component Canvas

Component Canvas

The canvas is the visual editor where you build processing logic by placing component instances, connecting their inputs and outputs, and monitoring live execution. Open it from the Canvas tab on any environment detail page.

Adding Instances

The Library Tray on the left side of the canvas lists all component types from the active library. To add a component:

  1. Open the library tray (left sidebar)
  2. Find the component type you want (components are organized by category)
  3. Drag it onto the canvas

A new instance node appears with the component's default configuration. Each node shows:

  • Header — component name and icon
  • Input pins (left side) — fields that receive data
  • Output pins (right side) — fields that produce data

You can drag nodes to reposition them on the canvas. Nodes snap to a grid for clean alignment.

Configuring an Instance

Double-click a component instance (or right-click and select Configure) to open the configuration drawer. It has tabs for:

Overview

  • Instance Name — a custom name to identify this instance (e.g., "Room 3 Temp Avg")
  • Node Width — adjust the visual width of the node on the canvas

Configuration

Static settings defined by the component. These values don't change at runtime and control how the component behaves. Depending on the component, you may see:

  • Number fields — with optional min/max bounds and step size
  • Text fields — with optional validation patterns
  • Toggle switches — for boolean settings
  • Dropdowns — for predefined choices

Wiring

Shows all input and output fields with their current wire connections and live values. Use this tab to see at a glance what data is flowing into and out of the instance.

Pin Layout

Reorder pins, insert gaps, and hide pins you don't need on this instance. See Per-Instance Pin Layouts below.

Documentation

If the component type includes documentation, it is rendered here.

Connectors

Connectors are the bridge between the canvas and the rest of Koios. They appear as square nodes on the canvas and come in seven types. Input connectors feed live data into a component; output connectors receive a component's result and write it somewhere.

ConnectorDirectionSource / Sink
TagInput or OutputA tag (live value, quality, timestamp, status, error code)
HistoryInput onlyA tag's historical time-series data, queried on demand
DeviceInput onlyA device's live status (running, stopped, failed, error code, last seen)
AI ModelInput onlyA model's live status and current prediction
BindingInput onlyThe live value flowing through a specific model binding
Scan GroupInput onlyA scan group's live status and timing metrics
ComponentInput onlyAn output from a component instance in a different environment

Each connector type only exposes the fields that make sense for it. For example, a Device connector lets you wire status or error_code into a component — but not value, because devices don't have one. The connector picker filters the available fields based on the entity you choose.

Tag Connector

Reads from or writes to a tag.

  • Tag — which tag to read from or write to
  • Field — which tag field to use: value, quality, timestamp, status, or error_code

For output tag connectors, only writable tags (output usage) are listed.

History Connector

Provides on-demand access to a tag's historical data. The connected component receives a history provider that can query the time-series database for trends, rolling statistics, or pattern detection.

  • Tag — which tag's history to access

Device, AI Model, Binding, Scan Group Connectors

Each of these reads a curated set of live fields from the named entity. Use them to build components that react to system state — for example, gate control logic on a device's status, or feed a model's current prediction into another component.

  • Entity — pick the device, model, binding, or scan group
  • Field — the connector picker shows only the fields valid for that entity

Component Connector

Reads an output from a component instance in a different environment. Used for cross-environment composition — e.g. a fast control loop in one environment feeds a slower analytics environment.

  • Environment — which environment contains the source component
  • Instance — which component instance to read from
  • Output Field — which output field to use

Wiring

Wires carry data between component pins and connectors. To create a wire:

  1. Click on an output pin (right side of a component or an input connector)
  2. Drag to an input pin (left side of a component or an output connector)
  3. Release to create the wire

Rules:

  • Each component input can have at most one incoming wire
  • Each output connector can have at most one incoming wire
  • Component outputs can fan out to multiple destinations
  • Wires automatically validate type compatibility

Wire Validation

Type compatibility is checked as you draw the wire and again at save time. If a connection is invalid, the wire paints red with a tooltip explaining why — for example, "string output cannot connect to numeric input." Invalid wires are not allowed to save: the offending wire is highlighted directly on the canvas instead of failing with a generic error.

The same contract runs in the component engine at runtime. If a wire ever produces a type mismatch — for example, an upstream component changes type after a library upgrade — the affected instance enters an ERROR state with the offending pin called out in the diagnostics.

Allowed coercions:

  • intfloat (numeric widening)
  • boolint or float (truthy promotion)
  • Identical types: strstr, listlist, dictdict

Strings, lists, and dicts cannot be silently coerced to other types.

Custom Wire Routing

Click any wire to reveal a midpoint handle. Drag it perpendicular to the wire's direction to de-stack overlapping wires or reshape the route for readability. Double-click the wire to reset it to the default path. Routing is saved with the canvas and survives copy/paste.

Dependency Ordering

When components are wired together, the engine automatically determines the correct execution order using topological sorting. Components whose outputs feed into other components' inputs execute first, ensuring data flows correctly in a single scan cycle.

If a circular dependency is detected (A feeds B, B feeds C, C feeds A), the engine logs a warning and executes the components in a best-effort order. Components in the cycle will see values from the previous scan cycle rather than the current one.

Per-Instance Pin Layouts

Every instance has its own pin layout. The component type ships a default ordering, and you can layer your own customizations on top — reorder, insert gaps for visual grouping, or hide pins you don't need on this particular instance.

Open the Pin Layout tab on the instance configuration drawer (or click the pin layout icon on the node) to open the editor:

  • Drag pins in the input or output column to reorder them
  • Insert a gap between pins for visual separation
  • Hide a pin by dragging it to the hidden tray on the right
  • Restore a hidden pin by dragging it back from the tray
  • Reset to default to discard the instance's overrides and fall back to the component type's layout

Layouts persist across canvas saves, environment clones, and copy/paste operations. Cross-side drags (e.g., trying to move an input pin to the output column) are rejected with visual feedback.

Offline Values

Each input field can have an offline value — a fallback used when the input is not wired or when live data is unavailable. Configure offline values in the instance's Configuration tab.

You can also click Save Live to Offline to capture the current runtime values as the new offline defaults. This is useful for initializing components with known-good values after a period of live operation.

Saving the Canvas

Changes to the canvas (adding/removing instances, moving nodes, creating wires, editing pin layouts, customizing wire routes) are held locally until you click Save in the toolbar. The save operation is atomic — all changes are applied together or not at all.

If a save is rejected, the canvas highlights the specific instance, connector, or wire that failed validation rather than showing a generic error.

The toolbar also provides:

ButtonAction
Undo / RedoStep through recent changes (including arrow-key nudges and selection changes)
RefreshReload the canvas from the server (discards unsaved changes)
DeleteRemove the selected node or wire
SavePersist all changes to the server

Monitoring Live Values

When the environment is enabled, the canvas shows live values flowing through wires and pins. Input and output fields on each instance display their current values, updating in real time at the environment's scan rate.

Use the Execution tab on the environment detail page for performance metrics, and the Logs tab to stream per-instance log output for debugging.

What's Next