Skip to content

Architecture Overview

Nexomatic is built around three roles: Sources, the Hub, and Sinks. Understanding how they interact explains everything else in the platform.

flowchart LR A["Sources
(Webhooks, Schedules, EventGrid)"] B["Hub
(Queues and dispatches events)"] C["Sinks
(Windows, Linux, Kubernetes)"] A --> B --> C

A Source is anything that produces an event. Sources are stateless — they call the Hub to register an event and then their job is done.

Built-in sources include:

SourceHow it triggers
WebhookAn HTTP POST to a unique URL creates an event
SchedulerA cron expression fires an event on a schedule
Azure EventGridMessages from an Azure Event Grid topic become events
MCPAI agents using the Model Context Protocol create events directly

Every event carries a payload — an arbitrary JSON document that is passed to the sink when the task executes.

Sources are executed by nodes — deployed agents that receive events on the platform’s behalf (webhook node, scheduler node, EventGrid node). A single multi-tenant node runs sources for many tenants at once; a tenant-pinned node serves just one tenant. Either way, the Source row belongs to your tenant and always appears in your Sources list — the node is only the worker.

Platform templates become usable through Make my copy (POST /sourcetype/{id}/copy): the tenant’s copy carries the template’s config, secret, and node coverage, so the node serving the template serves the copy too. Every new tenant is automatically onboarded with a Scheduler copy — scheduled events work from day one without manual setup.

The controller stamps last_authenticated on every source and sink whenever their serving node registers or pings. The instance screens derive the status chip from that stamp: Awaiting node (never stamped), Online (stamped < 2 min ago), Offline (2+ min without a heartbeat). Lifecycle states such as KILLING still show their own chip.


The Hub sits at the centre of the platform. It:

  • Accepts events from Sources and stores them in a queue
  • Tracks which Sink agents are connected and what they can handle
  • Dispatches queued events to available Sinks over a persistent, outbound-only connection
  • Receives task results from Sinks and stores logs and outcome data
  • Enforces rate limits and back-pressure when sinks are busy

Sink agents connect outbound from your network to the Hub. No inbound firewall rules are required on your side.


A Sink is an agent process running inside your infrastructure. It maintains a persistent outbound connection to the Hub and waits for tasks to be dispatched.

When a matching event arrives, the Hub sends a Task Request to an available Sink. The Sink:

  1. Resolves any secrets it needs (fetched securely from the Hub at runtime)
  2. Executes the configured code module
  3. Streams the result and logs back to the Hub

The Hub stores the result, updates the event state, and optionally triggers a follow-on event.

Sinks never receive inbound connections. Everything flows outbound from the Sink to the Hub.

Sinks run on nodes — a remote node can serve sinks for many tenants at once, or be pinned to a single tenant. The Sink row stays tenant-owned and visible in that tenant’s Sinks list regardless of which node runs it.


stateDiagram-v2 direction LR [*] --> QUEUED : Source fires QUEUED --> RUNNING : Hub dispatches RUNNING --> SUCCESS RUNNING --> WARNING QUEUED --> TIMED_OUT : newer schedule fires RUNNING --> ERROR SUCCESS --> QUEUED : follow-on event (optional) ERROR --> QUEUED : failure-handler event (optional)

Events stay in QUEUED state until a suitable Sink comes online. If no Sink is available, events accumulate safely and drain when connectivity is restored.


RoleAccess
AdminFull read/write access to all resources
ViewerRead-only access to all resources

Roles are assigned by an Admin in the User Management screen.