Architecture Overview
Tiny Systems separates the control plane (where you prompt and inspect) from the execution plane (the modules that run agents as real workloads in your cluster). Kubernetes-native throughout.
The usual control plane is the tiny CLI: one binary that serves the MCP endpoint (localhost:7776/mcp) and the browser flow editor (localhost:7775), talking straight to your cluster over your kubeconfig. The hosted platform is the optional alternative for teams — same execution plane either way.
High-Level Architecture
+-----------------------------------------------------------------------+
| CONTROL PLANE (pick one) |
| |
| tiny CLI (local) Hosted platform (teams) |
| +---------------------------+ +---------------------------+ |
| | MCP server :7776/mcp | | Web editor + Manager API | |
| | Flow editor :7775 | | Cluster watcher, auth | |
| +---------------------------+ +---------------------------+ |
+-----------------------------------------------------------------------+
|
Kubernetes API (kubeconfig)
|
+---------------------------+---------------------------+
v v v
+-------------------+ +-------------------+ +-------------------+
| CLUSTER A | | CLUSTER B | | CLUSTER C |
| | | | | |
| +---------------+ | | +---------------+ | | +---------------+ |
| | common-module | | | | http-module | | | | custom-module | |
| | http-module | | | | db-module | | | | | |
| +---------------+ | | +---------------+ | | +---------------+ |
| | | | | |
| TinyNode CRDs | | TinyNode CRDs | | TinyNode CRDs |
| TinyModule CRDs | | TinyModule CRDs | | TinyModule CRDs |
+-------------------+ +-------------------+ +-------------------+
Component Details
Control Plane
Local (tiny) — the default:
| Component | Purpose |
|---|---|
| MCP server | 25 tools for building, running, and debugging flows from any MCP client |
| Flow editor | Browser canvas served at localhost:7775 |
| Provisioner | tiny up installs CRDs, the NATS broker, the OTEL collector, and core modules |
Hosted platform (teams): web editor, manager API, cluster watcher, and workspace auth — the same cluster runtime underneath.
Cluster runtime
tiny up installs alongside the modules:
| Component | Purpose |
|---|---|
| NATS / JetStream | Durable cross-module transport and the run ledger — hops requeue (Nak) rather than drop |
| OTEL collector | Traces for every hop, readable via get_traces |
| CRDs | TinyModule, TinyNode, TinySignal, TinyFlow, TinyProject, TinyScenario |
Modules (Execution Plane)
Modules run in your Kubernetes clusters as operators:
+-------------------------------------------------------------------+
| MODULE OPERATOR |
| |
| +-----------------+ +-----------------+ +-----------------+ |
| | Controller | | Scheduler | | gRPC Server | |
| | | | | | | |
| | - Watch CRDs | | - Route messages| | - Cross-module | |
| | - Reconcile | | - Manage runners| | communication | |
| | - Update status | | - Handle errors | | | |
| +-----------------+ +-----------------+ +-----------------+ |
| |
| +-------------------------------------------------------------+ |
| | COMPONENT REGISTRY | |
| | +---------+ +---------+ +---------+ +---------+ ... | |
| | | Router | | Split | | Ticker | | Debug | | |
| | +---------+ +---------+ +---------+ +---------+ | |
| +-------------------------------------------------------------+ |
+-------------------------------------------------------------------+
Each module:
- Deploys as a Kubernetes Deployment (via Helm)
- Watches TinyNode CRDs that reference its components
- Executes component logic when nodes receive messages
- Updates TinyNode status with port schemas and errors
Message Flow
When a flow executes, messages traverse the system:
+-----------------------------------------------------------------+
| MESSAGE EXECUTION FLOW |
+-----------------------------------------------------------------+
1. TRIGGER
+------------------+
| External Request | (HTTP, webhook, timer, manual)
+--------+---------+
|
v
2. SIGNAL CREATION
+------------------+
| TinySignal CRD | (Created in Kubernetes)
+--------+---------+
|
v
3. CONTROLLER PROCESSING
+------------------+
| Signal Controller| (Leader pod only)
+--------+---------+
|
v
4. SCHEDULER ROUTING
+------------------+
| Scheduler.Handle | (Find target runner)
+--------+---------+
|
v
5. COMPONENT EXECUTION
+------------------+
| Component.Handle | (Your component code)
+--------+---------+
|
v
6. OUTPUT CALLBACK
+------------------+
| output(port,data)| (Send to output port)
+--------+---------+
|
v
7. EDGE EVALUATION
+------------------+
| Expression Eval | (Transform data via expressions)
+--------+---------+
|
+--- Same module? --> Go channel (fast)
|
+--- Different module? --> NATS (durable; transient failures
are retried, hops Nak not drop)
|
v
8. NEXT NODE
+------------------+
| Repeat from step 4|
+------------------+
Custom Resource Definitions
TinySystems uses CRDs to represent runtime state:
TinyNode
Represents a node instance:
apiVersion: operator.tinysystems.io/v1alpha1
kind: TinyNode
metadata:
name: router-abc123
labels:
tiny.systems/flow-id: "flow-xyz"
spec:
module: github.com/tiny-systems/common-module
component: router
version: "1.0.0"
edges:
- id: "edge-1"
port: "out_success"
to: "next-node"
toPort: "input"
configuration:
context: "{{$.result}}"
status:
moduleName: common-module
component: router
ports:
- name: input
schema: {...}
metadata:
custom-key: "custom-value"
TinyModule
Registers a module for discovery:
apiVersion: operator.tinysystems.io/v1alpha1
kind: TinyModule
metadata:
name: common-module-v1
status:
address: "common-module-v1:50051"
version: "1.0.0"
components:
- name: router
- name: split
- name: ticker
TinySignal
Triggers node execution:
apiVersion: operator.tinysystems.io/v1alpha1
kind: TinySignal
metadata:
name: trigger-abc
spec:
node: router-abc123
port: input
data:
message: "Hello World"
Cross-Module Communication
When nodes in different modules need to communicate:
+-----------------+ gRPC +-----------------+
| common-module | <--------------------> | http-module |
| | | |
| Router node | ModuleService.Send | Server node |
| sends to | ---------------------> | receives |
| http-server | | message |
+-----------------+ +-----------------+
| |
+-------- ClientPool manages connections --+
- Modules discover each other via TinyModule CRDs
- ClientPool maintains gRPC connections
- Messages are serialized for cross-module calls
- Same-module communication uses Go channels (no serialization)
Scalability
Each module supports horizontal scaling:
+-------------------------------------------------------------------+
| SCALED MODULE (3 replicas) |
| |
| +---------+ +---------+ +---------+ |
| | LEADER | | READER | | READER | |
| | | | | | | |
| | Updates | | Watches | | Watches | |
| | CRs | | CRs | | CRs | |
| +----+----+ +----+----+ +----+----+ |
| | | | |
| +--------------------+--------------------+ |
| | |
| Kubernetes Service |
| (load balancing) |
+-------------------------------------------------------------------+
- Leader election via Kubernetes Leases
- Only leader updates CRD status
- All replicas handle incoming messages
- State shared via TinyNode metadata
Next Steps
- Quick Start - Create your first flow
- Developer Guide - Build custom modules