Framework · 2026

Omega
Architecture

The autonomous nervous system for high‑complexity Flutter applications.

This site is the complete documentation for Omega. It includes: data flow step by step, a glossary of terms, everything the framework offers, examples by use case, core concepts, comparison with BLoC and Riverpod, diagram, installation, CLI, integration, flow lifecycle, API reference for each class, persistence, inspector and testing. For more examples in the repo see doc/GUIA.md and the example/ app. Production app built with Omega: Kashira (full working architecture).

Created by: Yeferson Segura

Leading a new era in Flutter

Framework Version: 1.0.0-Stable

GitHub Instagram

What’s new in Omega

Quick summary of recent improvements to the framework and tools. For full details see CHANGELOG.md in the repository.

0.0.26 — CLI Robustness & UX

Enhances developer experience with a smarter CLI that automates route wiring and initial setup without errors.

  • Automatic Route Registration: When generating a module (ecosystem), the CLI now automatically registers the route and adds the UI import in omega_setup.dart.
  • Fixed Smoke Tests: test/widget_test.dart generation is now fully compatible with Omega, removing residual MyApp dependencies.
  • Quick Start: New section in the documentation for activating and creating apps in seconds, including AI environment variable configuration.
  • Windows Robustness: Improved path resolution and forced overwriting to ensure a clean initial setup.

Key command:

# Activate the updated CLI locally
dart pub global activate --source path .
0.0.25 — Orchestration & App Creation

Introducing omega create app, an orchestrator that automates the full setup of an Omega project from scratch, including intelligent AI assistance.

  • App Creator: omega create app <Name> coordinates flutter create, dependencies, and omega init in a single step.
  • AI Kickstart: The --kickstart flag allows the AI to write real business logic (agents, flows, and UI) based on your description, moving beyond generic templates.
  • Standard Navigation: OmegaNavigator now supports onGenerateRoute, enabling the use of Navigator.pushNamed with Omega routes.
  • Automatic Smoke Tests: The generator cleans up default Flutter tests to ensure the new project compiles and passes tests out of the box.

Example:

# Create a crypto app with real logic generated by AI
omega create app omega_crypto --kickstart "real-time crypto dashboard" --provider-api
0.0.23 — AI Evolution & Advanced Generation

Supercharge your development workflow with AI-assisted commands to diagnose, audit, and generate full modules following Omega's best practices.

  • omega ai coach module: Generates full ecosystems (WorkflowFlow, StatefulAgent, Typed Events, Contracts, and Tests) with a single command.
  • Feature Auditing: ai coach audit analyzes your real project, detecting wiring (setup) gaps, missing contracts, or tests for a feature.
  • Editor Reports: AI commands now default to opening a temporary Markdown report in your editor for better readability, with a --stdout option.
  • Plug-and-Play UI Templates: Generated UI pages now dynamically connect to FlowManager via OmegaScope without manually passing the agent.

Command Example:

# Generate a full module with assisted advanced architecture
dart run omega_architecture:omega ai coach module "Payment" --template advanced
0.0.22 — Reactive agents and workflow flow

This release adds two optional capabilities to scale UI/processes without compromising the core: OmegaStatefulAgent + OmegaAgentBuilder, and OmegaWorkflowFlow.

  • Reactive agent state: OmegaStatefulAgent<TState> exposes viewState/stateStream so UI can react to agent state without duplicating logic.
  • UI helper: OmegaAgentBuilder listens to agent state and rebuilds widgets (loading/error/view state) declaratively.
  • Optional workflow engine: OmegaWorkflowFlow models step-based processes with defineStep, startAt, next, failStep, and completeWorkflow.

Example:

class AuthAgent extends OmegaStatefulAgent<AuthViewState> {
  AuthAgent(OmegaEventBus channel) : super(
    id: "Auth",
    channel: channel,
    behavior: AuthBehavior(),
    initialState: AuthViewState.empty,
  );
}

OmegaAgentBuilder<AuthAgent, AuthViewState>(
  agent: authAgent,
  builder: (context, state) => state.isLoading
      ? const CircularProgressIndicator()
      : const SizedBox.shrink(),
);
0.0.21 — Typed events

Introduces OmegaTypedEvent and emitTyped so your events can be classes with name + data instead of plain strings with loose payloads.

  • OmegaTypedEvent + emitTyped: define event classes (for example LoginRequestedEvent) and emit them with channel.emitTyped(...); listeners read them with event.payloadAs<LoginRequestedEvent>().
  • Updated example: the auth flow in the example app uses typed events to showcase the recommended pattern.
  • Docs aligned: README.md and doc/GUIA.md now present typed events as the preferred style, reducing magic strings and runtime bugs.

Example:

// Define the typed event
class LoginRequestedEvent implements OmegaTypedEvent {
  LoginRequestedEvent(this.email, this.password);
  final String email;
  final String password;
  @override
  String get name => AppEvent.authLoginRequest.name;
}

// Emit from the flow
channel.emitTyped(LoginRequestedEvent(email, password));

// Read in the agent
final ev = event.payloadAs<LoginRequestedEvent>();
if (ev != null) {
  // use ev.email, ev.password
}

Quick Start

Activate Omega globally and create your first project in seconds.

🌍

1. Global Activation

Install the Omega CLI on your system to use it from any folder:

dart pub global activate omega_architecture

PATH Setup (if command is not recognized):

  • Windows: Add %LOCALAPPDATA%\Pub\Cache\bin to your user Path variable.
  • macOS/iOS/Linux: Add export PATH="$PATH":"$HOME/.pub-cache/bin" to your ~/.zshrc or ~/.bashrc.
🚀

2. Create your App

Use the create app command to generate a pre-configured project:

omega create app my_app

This creates the project, adds dependencies, and initializes Omega.

🤖

Want to go faster? Use the AI kickstart to generate initial business logic:

omega create app my_app --kickstart "an e-commerce" --provider-api

Getting started with Omega

Installation, first use and running the example in three steps.

1. Add the dependency

In your app’s pubspec.yaml:

dependencies:
  omega_architecture: ^0.0.27

2. Initialize in your app

From the project root:

dart run omega_architecture:omega init

This creates lib/omega/omega_setup.dart. Then register agents, flows and routes inside createOmegaConfig.

3. Generate an ecosystem (optional): dart run omega_architecture:omega g ecosystem Auth generates agent, flow, behavior and page in the current directory and registers them in omega_setup.dart.

Run the example: cd example && flutter run. It includes login, navigation with typed payload and usage of OmegaRoute.typed<T> and payloadAs<T>.

Data flow in Omega

In Omega the UI does not call business methods; it emits intents. The channel, flows and agents do the work; the UI only reflects the result.

Step 1 — The UI emits an intent

The user taps “Sign in”. The screen does not call AuthService.login(); it calls flowManager.handleIntent(OmegaIntent.fromName(AppIntent.authLogin, payload: creds)). The intent carries the semantic name ("auth.login") and the data (credentials).

Step 2 — The flow (running) receives the intent

OmegaFlowManager sends the intent only to flows that are in running state. AuthFlow receives it in onIntent(ctx). There it can: emit a “loading” expression for the UI, and emit an event on the channel to ask the agent to work: channel.emit(OmegaEvent.fromName(AppEvent.authLoginRequest, payload: ctx.intent!.payload)).

Step 3 — The agent reacts and emits events

The agent is subscribed to the channel. Its behavior engine evaluates the context (event "auth.login.request") and returns a reaction, for example "doLogin" with the payload. The agent executes onAction("doLogin", payload): it calls the API, validates and emits emit("auth.login.success", payload: user) or emit("auth.login.error", payload: error).

Step 4 — The flow reacts to the event and updates UI / navigation

The flow listens to the channel. When "auth.login.success" arrives, in onEvent(ctx) it emits an expression toward the UI (emitExpression("success", payload: ctx.event!.payload)) and, if appropriate, a navigation intent: channel.emit(OmegaEvent(..., name: "navigation.intent", payload: OmegaIntent.fromName(AppIntent.navigateHome, payload: userData))).

Step 5 — The UI and the navigator react

The screen is listening to flow.expressions; when it receives "success" it calls setState and shows the result. OmegaNavigator (wired to the channel with wireNavigator) receives the "navigation.intent" event, extracts the intent and performs pushReplacement to the "home" route, passing the payload as arguments. The home screen receives the data already typed if you use OmegaRoute.typed<LoginSuccessPayload>.

Glossary: key definitions

Terms you will use across the whole Omega ecosystem.

Term Definition
Event (OmegaEvent) Representation of “something that happened” in the system. It has a name (e.g. "auth.login.success") and optional payload. It is published on the channel and received by all subscribers (agents, flows, OmegaBuilder).
Intent (OmegaIntent) Business‑level request: “I want to log in”, “I want to go home”. The UI emits intents; it does not call methods. OmegaFlowManager routes them to flows in running state. They are also used for navigation; the payload reaches the screen as route arguments.
Expression (OmegaFlowExpression) Message that a flow sends to the UI: “loading”, “success”, “error” (with type and payload). The UI subscribes to flow.expressions and rebuilds. The flow announces state; the UI does not poll “are you loading?”.
Channel (OmegaChannel) Global event bus. Single communication point: anyone can emit(OmegaEvent) and anyone can subscribe to events. Decouples who emits from who listens.
Agent (OmegaAgent) Autonomous logic unit with an id, channel and behavior engine. Reacts to events (and optionally to direct intents). The behavior returns a reaction (action + payload); the agent executes it in onAction and can emit new events. Encapsulates logic that is testable without Flutter.
Flow (OmegaFlow) Business flow (login, checkout, etc.) with states (idle, running, paused, sleeping, ended). Only in running does it process events and intents. It orchestrates: receives intents from the UI, emits events for agents, listens to events, emits expressions for the UI and emits navigation intents.
FlowManager (OmegaFlowManager) Registers flows, activates/pauses them (activate, switchTo) and routes intents only to those in running. Connects the channel to the navigator (wireNavigator) so that "navigate.*" and "navigation.intent" change screens.
Behavior (behavior engine) Defines when an agent reacts and which action to return. Composed of rules (condition + reaction). Evaluates the context (event or intent) and returns the first OmegaAgentReaction that matches.
Snapshot State “photo”: of a flow (OmegaFlowSnapshot) or the whole app (OmegaAppSnapshot). Includes flowId, state, memory and last expression. Used for debugging, persistence (save/restore on close/open) and time‑travel style tools.
Offline queue Queue of pending intents when the app is offline (OmegaQueuedIntent, OmegaOfflineQueue, OmegaMemoryOfflineQueue). A flow enqueues intents on connectivity failures and another service retries them when the connection comes back. See the Offline-first (intent queue) section in doc/GUIA.md.

Everything Omega offers

A summary of the framework’s capabilities and tools.

Communication and semantics

  • Global event bus (OmegaChannel): decoupled emit and listen.
  • Events with name and payload; typed names with OmegaEventName and OmegaEvent.fromName.
  • Intents with name and payload; typed names with OmegaIntentName and OmegaIntent.fromName.
  • Typed payload access: payloadAs<T>() on events, intents and expressions.

Agents and behavior

  • Autonomous agents (OmegaAgent) with id, channel and behavior engine.
  • Rule engine (OmegaAgentBehaviorEngine): addRule(condition, reaction).
  • Evaluation context (OmegaAgentBehaviorContext): event, intent, state.
  • Reaction: OmegaAgentReaction(action, payload) executed in onAction.
  • Agent protocol: direct messages (send) and broadcast.

Flows and orchestration

  • Business flows (OmegaFlow) with states: idle, running, sleeping, paused, ended.
  • OmegaFlowManager: registerFlow, activate, switchTo, handleIntent, wireNavigator.
  • Expressions toward the UI: emitExpression(type, payload); the UI listens to expressions.
  • Per‑flow memory (memory) that persists and is included in the snapshot.
  • Snapshot per flow and for the whole app; toJson/fromJson for persistence.

UI, navigation and bootstrap

  • OmegaScope: injects channel and flowManager; OmegaScope.of(context).
  • OmegaBuilder: widget that reacts to a channel event (optionally filtered by eventName).
  • Decoupled navigation: "navigate.id" (pushReplacement), "navigate.push.id" (push); payload → arguments.
  • Typed routes: OmegaRoute.typed<T> and routeArguments<T>(context).
  • OmegaConfig and OmegaRuntime.bootstrap: single bootstrap point; optional initialFlowId.

Persistence, inspector and CLI

  • Persistence: getAppSnapshot → toJson → save; on open, fromJson → restoreFromSnapshot. OmegaSnapshotStorage (save/load) can be implemented with disk or backend.
  • Inspector: debug panel (OmegaInspector) with latest events and flow snapshots. On web: OmegaInspectorLauncher opens a separate window; OmegaInspectorReceiver shows the data via BroadcastChannel.
  • CLI: omega doc, omega inspector (local Inspector + VM Service), omega init, omega g ecosystem|agent|flow, omega validate, omega trace, omega doctor, omega create app, omega ai …. Full list: CLI section below and doc/COMANDOS_CLI.md.

Going beyond traditional limits

The Glass Ceiling of BLoC

Structural rigidity. Strong coupling between Streams and Widgets. Exponential complexity in large apps.

The Riverpod Maze

Hard‑to‑trace flows. Provider fragmentation. Technical learning curve on top of business semantics.

The Paradigm Shift

In Omega, business logic does not “live” in the UI. Logic lives in Autonomous Agents that operate independently and communicate through a Semantic Layer.

UI as a Mirror

The interface is a “dumb” mirror that reflects the expressions of the business process.

Actor‑Based

Inspired by the Elixir/Erlang actor model for total isolation of responsibilities.

Scalable‑First

Designed for large teams where modularity is the only path to success.

Evolutionary Architecture

🧠

Distributed Intelligence

Autonomous agents reduce load on the main thread and decouple logic from the widget lifecycle.

📡

Reactive Global Bus

Asynchronous communication channels allow 100% observability of system activity.

🎭

Semantic Layer

Intents and Expressions remove direct coupling between user intent and system response.

Decoupled Architecture


// The Agent: brain of the logic
class AuthAgent extends OmegaAgent {
  void _login(credentials) {
    emit("auth.login.success", payload: user);
  }
}

// The Flow: navigation orchestrator
class AuthFlow extends OmegaFlow {
  void onEvent(ctx) {
    if (ctx.event?.name == "auth.login.success") {
       emitExpression("success");
       navigate("home");
    }
  }
}
                

Atomic Decoupling

Business code does not mention widgets, contexts or routes. It is pure logic, 100% portable and testable in seconds without emulators.

High‑level view of Omega

High‑level diagram showing how the UI, agents, flows, event channel, FlowManager, navigator and CLI interact.

Omega Architecture diagram: UI, OmegaScope, OmegaBuilder, OmegaChannel, OmegaAgent, Behavior Engine, OmegaFlow, OmegaFlowManager, OmegaNavigator and Omega CLI.

Omega vs BLoC vs Riverpod

Observable, persistable and reproducible state; agents, flows and intents at the core; the UI only reflects. With snapshot, inspector and persistence/restore.

Feature Omega Architecture BLoC / Riverpod
Logic autonomy Independent agents Dependent on UI/Providers
Semantic traceability Native (event bus) Manual (debug prints)
Decoupled navigation Yes (via flows) No (via BuildContext)
Team scalability Modular (micro‑agents) Prone to “spaghetti”

Omega vs BLoC: In Omega, logic lives in agents that do not know the UI; in BLoC it lives in Blocs tied to Streams and widgets. Omega decouples navigation (intents); BLoC usually uses BuildContext.

Omega vs Riverpod: Riverpod is very flexible (providers, ref); Omega fixes a model (agents + flows + channel) and gives explicit traceability (named events/intents). Navigation in Omega does not depend on context.

For a detailed table and when to choose each one, see doc/COMPARATIVA.md in the repo.

When to choose Omega

Choose Omega if...

You want business logic outside the UI and easy to test without Flutter, decoupled navigation, teams that need a clear structure (agents, flows, intents) or apps with high complexity.

Choose BLoC or Riverpod if...

You prefer something very widely adopted (documentation, examples, community), you are fine with events → states → UI or flexible providers and you do not need the agents model or the intents layer.

Omega does not compete in popularity; it differentiates itself through agents + behavior + channel + flows + intents and navigation without BuildContext. It is architecture, not just state management.

The importance of Omega

A framework that brings together clear architecture, real decoupling, and tools available from day one.

Omega is not “just another BLoC”. It is a way to organize the application where the business logic lives in agents, orchestration happens in flows, and the UI simply reflects what the system decides. This reduces bugs, speeds up testing, and allows the application to scale easily with the team.

🎯

Clarity from day one

You always know where things belong: agents for logic, flows for orchestration, and intents for communication. No guessing which Provider or Bloc holds each rule.

🧪

Truly testable

The logic does not depend on Flutter. You can test agents and flows with pure unit tests, without pumpWidget or context mocks.

📦

Scalable by design

Ecosystems (agent + flow + behavior + UI) allow multiple developers to work on features without interfering with each other. The CLI also generates a consistent structure.

Why it is worth using

Less coupling, less technical debt

The UI does not know about routes or navigation contexts. Flows emit intents, and the navigator reacts. Changing screens or flows does not break the business logic.

Clear traceability

Events and intents have names and payloads. You can easily track who requested what and who responded, without relying on prints or blind debugging.

Centralized configuration

The omega_setup.dart file gathers agents, flows, and routes of the application. A quick look lets you understand how the entire app is structured.

Low investment, high benefit

With omega init and omega g ecosystem the structure is generated automatically. This lets you focus on business rules and user experience instead of building layers manually.

In summary: Omega is worth using when you want an architecture that scales with complexity, is easy to test, and allows the whole team to understand the system without getting lost in scattered Providers or Blocs.

About the software

Omega is a reactive and agent‑based framework for Flutter: business logic lives in agents and flows that communicate through an event channel; the UI only emits intents and reacts to events and expressions.

Short definition: In Omega, an event = "something that happened" (emitted to the channel). An intent = "I want this to happen" (emitted by the UI; the FlowManager distributes it to flows in the running state). An expression = message from the flow to the UI ("loading", "success", "error"). Agents and flows listen to events; flows also receive intents and emit expressions and navigation intents.

🤖

Reactive agents

Autonomous entities with id, channel and behavior engine. They react to system events (and to intents if the flow delegates to them). They execute logic in onAction and emit new events. Testable without Flutter.

⚙️

Behavior engine

Set of rules (condition + reaction). It evaluates the context (event or intent) and returns the first matching OmegaAgentReaction. This way the agent is not a giant switch; it is composed by rules.

📡

Event‑driven

Everything goes through OmegaChannel: emit(OmegaEvent) and subscription to events. Agents and flows subscribe; the UI can use OmegaBuilder to react to a specific event.

Flow management

OmegaFlow orchestrates a use case (login, checkout). It has states (idle, running, paused, sleeping, ended); only in running it processes events and intents. OmegaFlowManager registers flows, activates/pauses them and distributes intents. Several flows can be active at the same time with activate(id); switchTo(id) leaves only one active.

Semantic intents

OmegaIntent represents a named request (e.g. "auth.login", "navigate.home") with a payload. The UI does not call methods; it emits intents. For typed names: an enum that implements OmegaIntentName and OmegaIntent.fromName(AppIntent.xxx, payload: ...). For navigation, the intent payload arrives at the screen as arguments (with OmegaRoute.typed<T> the view receives the type directly).

Examples by use case

Typical code for the most common scenarios.

Production sample app (full Omega in action): Kashirayefersonsegura.com/projects/kashira/

Emit an event and listen to it (channel)

final channel = OmegaChannel();
channel.emit(OmegaEvent.fromName(AppEvent.userUpdated, payload: user));
channel.events.listen((e) {
  if (e.name == AppEvent.userUpdated.name) {
    final u = e.payloadAs<User>();
    if (u != null) refreshUI(u);
  }
});

The UI requests login (intent + flow + agent)

// On the login screen
scope.flowManager.handleIntent(
  OmegaIntent.fromName(AppIntent.authLogin, payload: LoginCredentials(email: e, password: p)),
);

// The flow in onIntent emits "loading" and delegates to the agent
channel.emit(OmegaEvent.fromName(AppEvent.authLoginRequest, payload: ctx.intent!.payload));

// The agent in onAction calls the API and emits success/error
emit("auth.login.success", payload: LoginSuccessPayload(token: t, user: u));

Navigate to a screen with typed data

// From the flow, after successful login
channel.emit(OmegaEvent.fromName(
  AppEvent.navigationIntent,
  payload: OmegaIntent.fromName(AppIntent.navigateHome, payload: userData),
));

// Registration of a typed route (in omega_setup)
navigator.registerRoute(OmegaRoute.typed<LoginSuccessPayload>(
  id: "home",
  builder: (context, userData) => HomePage(userData: userData),
));

// In HomePage you receive userData already as LoginSuccessPayload

Save and restore state (persistence)

// On close or at a save point
final snapshot = flowManager.getAppSnapshot();
await prefs.setString("omega_state", jsonEncode(snapshot.toJson()));

// When opening the app
final loaded = prefs.getString("omega_state");
if (loaded != null) {
  final snapshot = OmegaAppSnapshot.fromJson(jsonDecode(loaded));
  flowManager.restoreFromSnapshot(snapshot);
}

Show the inspector in debug

if (kDebugMode)
  Stack(
    children: [
      MyApp(),
      Positioned(right: 0, top: 0, child: OmegaInspector(eventLimit: 20)),
    ],
  )

// On web: OmegaInspectorLauncher in the AppBar opens the separate window

Kashira: example in production

POS (point of sale) system built with Omega Architecture. Small and medium stores: sales, inventory, products and real‑time reports.

Live app: yefersonsegura.com/projects/kashira/

Vision

Register sales, manage inventory, handle products and consult reports from an intuitive app. Control daily operations, best‑selling products, up‑to‑date stock and sales history. Simple management to improve organization and decision‑making.

Why Omega in Kashira

  • Single channel: all communication through OmegaChannel (emit/onEvent).
  • Agents and flows per domain: Auth, Theme, Home, Sales, Inventory, Products (Agent + Flow for each one).
  • Behaviors: rules that translate events into actions (OmegaBehaviorEngine).
  • Declarative navigation: routes in configuration; the UI emits intents, Omega resolves to Navigator.
  • Typing: KashiraEvent, KashiraIntent, OmegaRoute.typed<T>(), payloadAs<T>().
  • Snapshots: persistence of flow state when reopening the app.
  • Inspector: in debug, window/dialog for events and snapshots.

Omega components used

Component Use in Kashira
OmegaChannel Single event channel; emission from UI and agents.
OmegaAgent Auth, Theme, Home, Products, Inventory, Sales.
OmegaFlow One flow per domain; listens to events and emits expressions to the UI.
OmegaFlowManager Flow registration and activation; activate(flowId), restoreFromSnapshot.
OmegaBehaviorEngine Behaviors per agent: auth, theme, sales, inventory, products, home.
OmegaNavigator Routes: login, home, sales, inventory, productForm, etc.
OmegaRoute / OmegaRoute.typed<T>() productForm route receives a typed Producto?.
OmegaEvent / OmegaIntent Typed names (KashiraEvent, KashiraIntent).
OmegaScope Provides channel, flowManager, initialFlowId.
OmegaAppSnapshot / OmegaSnapshotStorage Save/load state when pausing/closing the app.
OmegaInspectorLauncher / OmegaInspectorReceiver Debugging of events and snapshots (debug).

Flows and agents per domain

Flow / Agent Responsibility
Theme Light/dark mode; persistence in ThemeStorage.
Auth Login, logout, session restore; navigation after login.
Home Entry point of the dashboard.
Sales Products for sale, sale creation (simulated service).
Inventory Stock summary, movements (simulated service).
Products Catalog and categories; navigation to product form.

Events and intents (typed)

Centralized in kashira_semantics.dart: events (KashiraEvent) such as navigationIntent, themeRequest, authLoginRequest, productosLoadRequest, ventasCrearVenta, etc.; intents (KashiraIntent) such as navigateLogin, navigateHome, navigatePushProductoForm, authLogin, etc. Usage: OmegaEvent.fromName(KashiraEvent.navigationIntent, payload: OmegaIntent.fromName(KashiraIntent.navigateHome)).

Routes

Defined in omega_setup.dart: login, register, home, ventas, inventory, productoForm (typed with Producto?).

Tech stack

Flutter (mobile + web), omega_architecture ^0.0.27, shared_preferences (mobile/desktop), web (localStorage on web for session, theme and snapshots).

Main features

  • Sales: fast registration, cart, discounts, category search, currency S/.
  • Inventory: stock summary, alerts, movements, adjustments.
  • Products: catalog (code/SKU, category, prices), create/edit form (typed route with Producto?).
  • Theme: light/dark with Omega (ThemeFlow/ThemeAgent) and persistence.
  • Session: login and restore; persistence depending on platform.
  • Reports: sales history and views for analysis.

Project structure (Kashira)

lib/
├── main.dart              # Omega bootstrap, theme, snapshots, inspector
├── core/                  # theme, storage (session/theme/snapshot io+web), utils
├── omega/
│   ├── omega_setup.dart   # OmegaConfig: agents, flows, routes
│   └── kashira_semantics.dart  # KashiraEvent, KashiraIntent
└── features/
    ├── auth/              # AuthAgent, AuthFlow, auth_behavior, auth_page
    ├── theme/             # ThemeAgent, ThemeFlow, theme_behavior
    ├── home/              # HomeAgent, HomeFlow, home_behavior, home_page
    ├── ventas/            # VentasAgent, VentasFlow, ventas_behavior, ventas_page, service
    ├── inventory/         # InventoryAgent, InventoryFlow, inventory_behavior, inventory_page, service
    └── productos/         # ProductosAgent, ProductosFlow, producto_form_page, service, producto_model

Goal: accessible and reliable solution to digitize small businesses and optimize sales and inventory, with clear and maintainable architecture thanks to Omega.

Core concepts

Summary of each piece of the system and its role.

Concept Description
OmegaChannel Central event bus. emit(OmegaEvent) to publish; events (Stream) to subscribe. All agents and flows use the same channel. Whoever creates it must call dispose() on shutdown.
OmegaEvent Represents "something that happened". Fields: id, name, payload. Create with OmegaEvent.fromName(OmegaEventName, payload) for typed names. Read the payload with type: event.payloadAs<T>().
OmegaIntent Action request with name and payload. The UI emits intents via flowManager.handleIntent(intent). For navigation the payload is passed as route arguments. Typed names: OmegaIntent.fromName(OmegaIntentName, payload).
OmegaAgent Autonomous logic unit: id, channel, behavior. Subscribes to the channel; the behavior evaluates the context and returns an OmegaAgentReaction; the agent executes in onAction(action, payload) and can emit(name, payload). Call dispose() when closing.
OmegaAgentBehaviorEngine Rule engine. addRule(OmegaAgentBehaviorRule(condition, reaction)). evaluate(OmegaAgentBehaviorContext) returns the first reaction whose condition is met, or null.
OmegaFlow Business flow with states (idle, running, sleeping, paused, ended). Only in running it processes onEvent and onIntent. Emits expressions to the UI with emitExpression(type, payload); the UI listens to expressions. It has memory (map) and getSnapshot() / restoreMemory().
OmegaFlowManager Registers flows with registerFlow(flow). activate(id) activates without pausing others; switchTo(id) activates one and pauses the rest. handleIntent(intent) sends the intent to all flows in the running state. wireNavigator(navigator) connects the channel to the navigator. getAppSnapshot() and restoreFromSnapshot(snapshot) for persistence.
OmegaFlowExpression Message from the flow to the UI: type ("loading", "success", "error") and payload. Read with type: expr.payloadAs<T>(). The UI subscribes to flow.expressions.
OmegaScope / OmegaBuilder OmegaScope injects channel and flowManager; any child uses OmegaScope.of(context). OmegaBuilder is a widget that rebuilds when an event arrives (optionally filtering by eventName).
OmegaNavigator / OmegaRoute Navigator translates "navigate.id" (pushReplacement) and "navigate.push.id" (push); the intent payload goes to RouteSettings.arguments. Routes with registerRoute(OmegaRoute). OmegaRoute.typed<T>(id, builder: (context, T? args)) lets the screen receive the type without casting; alternatively routeArguments<T>(context).

Use cases

High‑complexity apps

Multiple flows (auth, checkout, onboarding) with decoupled logic and clear traceability.

Large teams

Modularity by ecosystems (agent + flow + behavior + UI). Each feature can be developed in isolation.

Testing without UI

Business logic in agents and flows, 100% testable without emulators or widgets.

Decoupled navigation

Flows emit navigation intents; the navigator reacts without depending on BuildContext.

Installation

In your host app (the Flutter project that uses Omega), add the dependency. The omega_setup.dart file is created in your app with omega init, it does not come inside the library. There you define createOmegaConfig(OmegaChannel) with the list of agents, flows and routes that the runtime will register.

Add to your pubspec.yaml (from pub.dev):

dependencies:
  omega_architecture: ^0.0.27

Complete example in the package: The example/ folder contains an app with a login flow: login screen that emits intents with LoginCredentials, agent that validates and emits success/error with LoginSuccessPayload, flow that reacts in onIntent and onEvent, navigation to home with typed route OmegaRoute.typed<LoginSuccessPayload> and use of payloadAs<T>() in events and expressions. Run with cd example && flutter run.

Omega CLI

The CLI runs in your app (the one that uses omega_architecture). From a project that depends on omega_architecture: dart run omega_architecture:omega <command> [options]

Developer reference (table + all flags): doc/COMANDOS_CLI.md in the repository (Spanish). The README has the same commands in English with sample output.

Why

Open the official docs from the terminal without searching the web or bookmarking the URL.

Instruction

dart run omega_architecture:omega doc

Concept

Opens the official Omega web documentation in the browser (online). Does not create or modify any files.

Example (success)

Opening documentation: http://yefersonsegura.com/proyects/omega/

Why

Connect the Omega Inspector UI to a running Flutter app via the Dart VM Service (debug builds) without manually opening the hosted inspector URL.

Instruction

dart run omega_architecture:omega inspector

Concept

Opens the local Inspector HTML in the browser. Paste or connect to your app’s VM Service link (printed when you run flutter run). Same layout as the online inspector: flows, events, JSON details. For embedding in the app (FAB, web receiver), see INSPECTOR.md in the repo and the Inspector section on this page.

Example

flutter run
# In another terminal:
dart run omega_architecture:omega inspector

Why

Your app needs one central place to register routes, agents and flows; init creates that file so you don’t have to write the boilerplate by hand.

Instruction (both forms)

dart run omega_architecture:omega init
dart run omega_architecture:omega init --force

Without --force: creates omega_setup.dart only if it does not exist; if it already exists, the CLI reports an error (so you do not overwrite by mistake). With --force: overwrites the existing file (use when you want to reset or regenerate the setup).

Concept

Creates lib/omega/omega_setup.dart in your app with an empty OmegaConfig (agents, flows, routes). Run from the project root. By default the command is safe (no overwrite); use --force only when you intend to replace the current file.

Example (success)

Omega setup created.
  Project root: C:\...\my_app
  File: C:\...\my_app\lib\omega\omega_setup.dart

Example (failure)

Error: omega_setup.dart already exists.
  Use --force to overwrite.

Why

A full feature (e.g. Auth, Orders) usually needs an agent, a flow, a behavior and a page; this command creates all four and wires them in omega_setup.dart so you can focus on logic instead of boilerplate.

Instruction

dart run omega_architecture:omega g ecosystem <Name>

Concept

Generates agent, flow, behavior and page in the current directory. Registers agent and flow in omega_setup.dart. Run from the folder where you want the files (e.g. lib/ or lib/features/).

Example (success)

Creating in current directory: C:\...\my_app\lib
Ecosystem Auth created.
  Path: C:\...\my_app\lib\auth
Registered Auth (agent, flow) in omega_setup.dart

Example (failure)

Error: omega_setup.dart not found.
  Run from app root: omega init

Why

Sometimes you need only a new agent (and its behavior) for an existing flow or a feature that doesn’t need a full ecosystem; this avoids generating an extra flow and page.

Instruction

dart run omega_architecture:omega g agent <Name>

Concept

Generates only agent + behavior in the current directory. Updates only the agent import and registration in omega_setup.dart (does not touch the flow).

Example (success)

Agent Orders created.
  Path: C:\...\my_app\lib\orders

Why

When you need only a new flow (orchestrator) without a new agent or page, this creates just the flow and registers it in omega_setup.dart without touching the rest.

Instruction

dart run omega_architecture:omega g flow <Name>

Concept

Generates only flow in the current directory. Updates only the flow import and registration in omega_setup.dart (does not touch the agent).

Example (success)

Flow Profile created.
  Path: C:\...\my_app\lib\profile

Instruction

dart run omega_architecture:omega validate [path]

Concept

Checks omega_setup.dart: createOmegaConfig, OmegaConfig, agents:, and no duplicate agent/flow registrations. Starts from the bash directory (or optional path).

Example (success)

Directorio (bash): C:\...\my_app
Valid.
  File: C:\...\my_app\lib\omega\omega_setup.dart
  Agents: 2, Flows: 3

Example (failure)

Error: Duplicate flow registration: Auth.
  Remove duplicate XFlow(channel) from omega_setup.dart.

Why

Recorded sessions (events + snapshot) can be saved as JSON; trace view and trace validate let you inspect or validate those files from the CLI (debugging, CI, or sharing a bug report) without running the app.

Instruction

dart run omega_architecture:omega trace view <file.json>
dart run omega_architecture:omega trace validate <file.json>

Concept

Trace = JSON file with a recorded session (channel events and optional initial snapshot). Built by OmegaTimeTravelRecorder in your app when you call stopRecording(); the developer chooses where to save the JSON (mobile: path_provider; web: download). trace view shows a summary (events, snapshot). trace validate checks the structure; exit 0 if valid, 1 otherwise. Used for debugging, reproducing bugs, or sharing a case.

Example: export session to JSON

import 'dart:convert';
final session = recorder.stopRecording();
final jsonString = jsonEncode(session.toJson());
// Mobile: path_provider + File(path).writeAsString(jsonString)
// Web: blob + <a download> (see doc/TIME_TRAVEL.md)

Full code (mobile/web) in TIME_TRAVEL.md → “Export session to JSON (trace file)”.

Example view (success)

Trace: C:\...\trace.json
  Events: 42
  Initial snapshot: yes

Example validate (success)

Valid trace file.
  Path: C:\...\trace.json

Example (failure)

Error: Invalid trace structure (expected 'events' list and optional 'initialSnapshot').

Why

One command to see if your Omega setup is valid, how many agents/flows you have, and optional hints (e.g. flows/agents without a contract), so you can fix issues before they cause problems at runtime.

Instruction (both forms)

dart run omega_architecture:omega doctor
dart run omega_architecture:omega doctor <path>

Without path: uses the current directory (bash CWD) to find the app root. With path: starts the search from that path (e.g. omega doctor example when you are at the package root and want to check the example/ app).

Concept

Project health: validates omega_setup.dart, counts agents and flows, optionally lists flows/agents without a contract. By default it starts from the current directory; in a real project there is no example/ folder. If you are in lib/, it looks for the omega/ folder there. The optional <path> tells the CLI where to start looking (useful in repos with an example/ or multiple apps).

Example (success)

Directory (bash): C:\...\my_app\lib
Omega Doctor
  Setup: C:\...\my_app\lib\omega\omega_setup.dart
  Agents: 2, Flows: 3

Health check passed.

Example (errors)

Error: Duplicate flow registration: Auth.
  Remove duplicate XFlow(channel) from omega_setup.dart.

Fix the issues above and run omega doctor again.

Example (optional warnings)

Omega Doctor
  Setup: ...
  Agents: 2, Flows: 3

Optional (contracts):
  Flow without contract: ...\lib\orders\orders_flow.dart
  Agent without contract: ...\lib\provider\provider_agent.dart
  Tip: add a contract getter for clearer semantics and debug warnings.

Health check passed.

Why

Bootstrap a professional Flutter project with Omega in seconds, with all the initial wiring and optionally business logic generated by AI.

Instruction

omega create app <Name> [--kickstart "description"] [--provider-api]

Steps for Success

  1. Activate command: Run dart pub global activate omega_architecture first.
  2. Configure PATH: If omega is not recognized, add Dart's bin folder to your environment variables.
  3. Without AI: Run the simple command for a clean architecture setup.
  4. With AI: Set your OMEGA_AI_API_KEY first. The AI will write real business modules based on your description.

Concept

Orchestrates flutter create, adds omega_architecture, runs omega init, and generates a clean main.dart with Omega's bootstrap. If you use --kickstart, the AI analyzes your idea and generates custom modules (agents, flows, and UI) specific to your app. Must be executed outside existing projects.

Example (AI)

omega create app my_store --kickstart "e-commerce with cart and payments" --provider-api

Why

Diagnose traces with optional AI assistance while keeping a zero-cost offline mode as default/fallback.

Instruction

dart run omega_architecture:omega ai doctor
dart run omega_architecture:omega ai env
dart run omega_architecture:omega ai explain <file.json>
dart run omega_architecture:omega ai explain <file.json> --json
dart run omega_architecture:omega ai explain <file.json> --provider-api
dart run omega_architecture:omega ai explain <file.json> --stdout
dart run omega_architecture:omega ai coach start "<feature>"
dart run omega_architecture:omega ai coach audit "<feature>"
dart run omega_architecture:omega ai coach module "<feature or Name: description>" [--template basic|advanced] [--provider-api] [--json] [--stdout] [--module|-m <Name>]
dart run omega_architecture:omega ai coach redesign "<Module: UI change>" [--template basic|advanced] [--provider-api] ...

Concept

ai explain uses the same trace structure as omega trace (events list + optional initialSnapshot). Without flags it runs local heuristics (top events, namespaces, error/repetition patterns). With --provider-api, it tries provider mode (OpenAI today) and automatically falls back to offline on config/network failure.

Default output: ai explain and ai coach write a temporary report to .dart_tool/omega_ai_temp and open it; use --stdout for direct console output.

ai coach start builds an implementation guide (steps, required artifacts and validation checks). ai coach audit audits a real feature and returns score, findings and gaps (wiring, contracts, tests, etc.). ai coach module generates or evolves a full module (WorkflowFlow, StatefulAgent, contracts, etc.). ai coach redesign regenerates only ui/*_page.dart; it does not change events, agent, flow, or behavior — use it when the rest of the module is already correct.

Future Capabilities (WIP)

  • ai coach fix-gaps — Automatically creates files and wiring detected in audit.
  • ai coach generate-tests — Generates real test cases by analyzing flow/agent logic.
  • ai suggest-contracts — Proposes declarative contract definitions by analyzing code.
  • ai review-architecture — Senior-level architectural report (couplings, naming, complexity).

Response language

Provider and offline output follow the system locale (country/language). You can override it with OMEGA_AI_LANG or OMEGA_AI_LANGUAGE.

Environment variables

OMEGA_AI_ENABLED=true|false
OMEGA_AI_PROVIDER=openai|anthropic|gemini|ollama|none
OMEGA_AI_API_KEY=...
OMEGA_AI_MODEL=...
OMEGA_AI_BASE_URL=...
OMEGA_AI_LANG=es|en|pt|...

Example (provider)

dart run omega_architecture:omega ai explain trace.json --provider-api

Example (coach audit)

dart run omega_architecture:omega ai coach audit "auth"

Global options: -h, --help · -v, --version

Other documentation

In the repository (doc/) there are additional guides and references:

  • COMANDOS_CLI.md — Full CLI command reference for developers (Spanish): how to run, quick table, ai coach, traces, inspector, optional Omega Studio note.
  • CONTRACTS.md — Declarative contracts (OmegaFlowContract, OmegaAgentContract), examples and using the contract getter for semantics and debug warnings.
  • TIME_TRAVEL.md — Recording and replaying sessions with OmegaTimeTravelRecorder and OmegaRecordedSession; replay for debugging.
  • GUIA.md — Usage guide: channel, agents, flows, navigation, persistence, Inspector, offline-first, time-travel.
  • ROADMAP.md — Framework roadmap, future ideas and status of features.
  • TESTING.md — How to test agents and flows without Flutter, and tests with OmegaTimeTravelRecorder.
  • ARQUITECTURA.md — Architecture vision and design decisions.
  • MEJORAS.md — History of improvements applied (steps 1–7, etc.).

This web is the main documentation; the doc/ folder complements it with detail and examples in the repo.

Usage: agent and behavior

The agent subscribes to the channel; when an event (or an intent) arrives, the behavior evaluates the context and returns a reaction (action + payload); the agent executes it in onAction. You can use rules with addRule instead of overriding evaluate.

// Option 1: rules (recommended)
class AuthBehavior extends OmegaAgentBehaviorEngine {
  AuthBehavior() {
    addRule(OmegaAgentBehaviorRule(
      condition: (ctx) => ctx.event?.name == AppEvent.authLoginRequest.name,
      reaction: (ctx) => OmegaAgentReaction("doLogin", payload: ctx.event?.payload),
    ));
  }
}

class AuthAgent extends OmegaAgent {
  AuthAgent(OmegaChannel c) : super(id: "Auth", channel: c, behavior: AuthBehavior());

  @override void onMessage(OmegaAgentMessage msg) {}

  @override
  void onAction(String action, dynamic payload) {
    if (action == "doLogin") _login(payload);
  }
              void _login(dynamic payload) {
    final creds = payload is LoginCredentials ? payload : null;
    if (creds == null) { emit("auth.login.error", payload: OmegaFailure(...)); return; }
    // API call... then:
    emit("auth.login.success", payload: LoginSuccessPayload(token: t, user: u));
  }
}

Flow

Channel emits event → agent receives → behavior evaluates context (event/intent) → returns OmegaAgentReaction("doLogin", payload)onAction("doLogin", payload) executes the logic (e.g. calling an API) and emits "auth.login.success" or "auth.login.error".

Typed payload

In the agent you can check payload is LoginCredentials or receive the intent from the flow and use intent.payloadAs<LoginCredentials>(). Emit events with typed payloads (e.g. LoginSuccessPayload) so that the flow and the UI use payloadAs<T>().

Integrate Omega into your host app

Steps: 1) Bootstrap the runtime. 2) OmegaScope with channel, flowManager and initialFlowId. 3) MaterialApp with navigatorKey. 4) On the first frame: activate the initial flow and emit the initial navigation (e.g. to login). Optional: on web, show only the Inspector if the URL contains ?omega_inspector=1.

1. main.dart — Bootstrap and OmegaScope

// lib/main.dart
void main() {
  // Optional: on web, inspector window (OmegaInspectorLauncher opens with ?omega_inspector=1)
  if (Uri.base.queryParameters['omega_inspector'] == '1') {
    runApp(MaterialApp(home: const OmegaInspectorReceiver()));
    return;
  }
  final runtime = OmegaRuntime.bootstrap(createOmegaConfig);
  runApp(
    OmegaScope(
      channel: runtime.channel,
      flowManager: runtime.flowManager,
      initialFlowId: runtime.initialFlowId,  // e.g. "authFlow"
      child: MyApp(navigator: runtime.navigator),
    ),
  );
}

class MyApp extends StatelessWidget {
  final OmegaNavigator navigator;
  const MyApp({super.key, required this.navigator});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigator.navigatorKey,
      home: const _RootHandler(),
    );
  }
}

2. RootHandler — Activate initial flow and navigate

class _RootHandler extends StatefulWidget {
  const _RootHandler();
  @override
  State<_RootHandler> createState() => _RootHandlerState();
}

class _RootHandlerState extends State<_RootHandler> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      final scope = OmegaScope.of(context);
      // 1) Activate the initial flow (defined in createOmegaConfig with initialFlowId)
      if (scope.initialFlowId != null) {
        scope.flowManager.switchTo(scope.initialFlowId!);
      }
      // 2) Navigate to the first screen (e.g. login) with typed names
      final intent = OmegaIntent.fromName(AppIntent.navigateLogin);
      scope.channel.emit(
        OmegaEvent.fromName(AppEvent.navigationIntent, payload: intent),
      );
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: kDebugMode ? AppBar(actions: const [OmegaInspectorLauncher()]) : null,
      body: const Center(child: Text("Omega Running")),
    );
  }
}

3. omega_setup.dart — Config (agents, flows, routes, initialFlowId)

// lib/omega/omega_setup.dart (created with omega init / omega g ecosystem)
OmegaConfig createOmegaConfig(OmegaChannel channel) {
  return OmegaConfig(
    agents: [AuthAgent(channel), ProviderAgent(channel)],
    flows: [AuthFlow(channel), ProviderFlow(channel)],
    routes: [
      OmegaRoute(id: "login", builder: (context) => const LoginPage()),
      OmegaRoute.typed<LoginSuccessPayload>(id: "home", builder: (context, userData) => HomePage(userData: userData)),
    ],
    initialFlowId: "authFlow",
  );
}

Summary: createOmegaConfig is defined in lib/omega/omega_setup.dart (omega init / g ecosystem). It includes initialFlowId so that the RootHandler activates that flow on the first frame. Use OmegaIntent.fromName and OmegaEvent.fromName with your enums (AppIntent, AppEvent) to avoid magic strings. Typed routes with OmegaRoute.typed<T> so that the screen receives the payload with type. When closing the app, whoever holds a reference to the runtime can call channel.dispose() and flowManager.dispose() if needed.

Flutter: OmegaScope and OmegaBuilder

OmegaScope provides the channel and the flow manager to the entire UI. OmegaBuilder lets a part of the tree react to a channel event without the screen knowing the flow.

OmegaScope (dependency injection)

Wraps the app (usually in main) with channel, flowManager and optionally initialFlowId. Any child can access it with OmegaScope.of(context) to call handleIntent, emit events or get the flow and listen to expressions.

runApp(
  OmegaScope(
    channel: runtime.channel,
    flowManager: runtime.flowManager,
    initialFlowId: runtime.initialFlowId,
    child: MaterialApp(...),
  ),
);
// In a screen:
final scope = OmegaScope.of(context);
scope.flowManager.handleIntent(...);

OmegaBuilder (UI reactive to an event)

Widget that rebuilds when an event arrives at the channel. If you specify eventName, it only reacts to that name. Useful to show a global error banner ("auth.login.error") or a "user.updated" message without the screen knowing the flow. Requires OmegaScope in the tree.

OmegaBuilder(
  eventName: AppEvent.authLoginError.name,
  builder: (context, event) {
    final err = event?.payloadAs<OmegaFailure>();
    return err != null ? Text(err.message) : SizedBox.shrink();
  },
)

Using the Inspector (debug only)

Three options; in release all are no-op.

  • 1. Overlay: Stack(children: [MyContent(), Positioned(..., child: OmegaInspector())]) with kDebugMode.
  • 2. Launcher: AppBar(actions: [OmegaInspectorLauncher()]) — on web opens a remote window with OmegaInspectorReceiver (BroadcastChannel); on desktop/mobile opens a dialog.
  • 3. Online Inspector (VM Service + web): on Android/iOS/desktop call OmegaInspectorServer.start(channel, flowManager); the console prints a URL like http://yefersonsegura.com/projects/omega/inspector.html#<encoded-VM-URL>. Open it in your desktop browser (or paste the VM Service URL in the input) and the inspector will auto-connect.

Lifecycle of a flow

An OmegaFlow only processes events and intents when it is in the running state. Activating a flow or not defines whether it participates in the orchestration.

Flow states

  • idle: created but has not started yet. Does not process anything.
  • running: active. Receives events/intents and executes onEvent/onIntent. onStart() is called on entry.
  • sleeping: keeps memory, but ignores events/intents. Useful to "hibernate" logic.
  • paused: temporarily stopped. It does not process anything until it is reactivated.
  • ended: finished. Closes its expression stream and releases resources.

Activate and deactivate

  • flowManager.activate("flowId"): puts the flow in running without touching the others. You can have several active flows at the same time.
  • flowManager.switchTo("flowId"): activates one and pauses those that were in running. Ideal for a single "main" flow.
  • flowManager.activateExclusive("flowId"): similar to switchTo, but does not validate whether the id exists; it is more "aggressive".
  • If you do not activate a flow: it stays in idle, does not process events/intents and its onStart() is never called.

Pause, sleep and end

  • flowManager.pause("flowId"): moves the flow to paused. It does not process anything until it is reactivated with activate or switchTo.
  • flowManager.sleep("flowId"): calls sleep() on the flow (state sleeping). Keeps memory, but is "at rest".
  • flowManager.end("flowId"): calls end() (state ended) and it should no longer be used.
  • flowManager.endAll(): ends all registered flows and clears activeFlowId.

Practical consequences

  • Only flows in running receive OmegaIntent from handleIntent.
  • If a screen depends on a flow's expressions, you must make sure to activate it first (for example in a RootHandler or after login).
  • Use switchTo when you want a single flow to "own" navigation and the main experience.
  • Use activate when you want several flows collaborating in parallel (for example, notifications + auth + cart).

Lifecycle and dispose

Component Responsibility
OmegaChannel Whoever creates it must call channel.dispose() when closing the app.
OmegaFlowManager Call flowManager.dispose() to cancel the subscription created by wireNavigator.
OmegaAgent Call agent.dispose() to cancel the subscription to the channel.
OmegaScope Does not dispose; the widget that creates channel and flowManager must call their dispose() in State.dispose.

Project structure

lib/
├── omega/
│   ├── core/          # Channel, events, intents, types
│   ├── agents/        # OmegaAgent, behavior engine, protocol
│   ├── flows/         # OmegaFlow, OmegaFlowManager, expressions
│   ├── ui/            # OmegaScope, OmegaBuilder, navigation
│   └── bootstrap/     # Config, runtime
├── example/           # Complete example
└── omega_architecture.dart  # Public exports

Declarative contracts

A contract declares which events a flow listens to, which intents it accepts, and which expression types it emits (and for agents: events and intents). In debug mode, Omega prints a warning in the console when something is received or emitted that is not declared; this helps ensure the data you defined is respected.

Why use it? To document flow/agent boundaries, catch typos or wrong names in development, and lay the groundwork for strict mode or an Inspector that shows "what this flow expects". It is optional: if you do not define contract, behavior is unchanged.

Reference example: The package example/ app implements contracts in AuthFlow and AuthAgent. Run cd example && flutter run to see login/logout with contracts; in debug, any event or intent not in the contract will trigger a console warning. Use that app as the main reference when adding contracts to your own flows and agents.

Flow contract (OmegaFlowContract)

Override contract in your flow and return an OmegaFlowContract with event names, intent names, and expression types.

class AuthFlow extends OmegaFlow {
  AuthFlow(OmegaChannel c) : super(id: 'authFlow', channel: c);

  @override
  OmegaFlowContract? get contract => OmegaFlowContract.fromTyped(
    listenedEvents: [AppEvent.authLoginSuccess, AppEvent.authLoginError],
    acceptedIntents: [AppIntent.authLogin, AppIntent.authLogout],
    emittedExpressionTypes: {'loading', 'success', 'error'},
  );
  // ... onEvent, onIntent
}

Agent contract (OmegaAgentContract)

Override contract in your agent with the events and intents it handles.

@override
OmegaAgentContract? get contract => OmegaAgentContract.fromTyped(
  listenedEvents: [AppEvent.authLoginRequest],
  acceptedIntents: [AppIntent.authLogin],
);

Empty sets mean no constraint. Validation runs only in kDebugMode; release builds are unaffected. Full reference: example/ app (AuthFlow, AuthAgent) and doc/CONTRACTS.md.

Time-travel (record & replay)

You can record a session (channel events + initial snapshot) and replay it to go back to a previous moment: restore the snapshot and re-emit events up to an index. Useful for debugging, demos, or auditing.

Concepts: Record — on start an initial snapshot is saved and each emitted event is appended to a list. Replay — restore the snapshot and re-emit events (or only up to an index) on the channel so the app is in the state it had at that step (time-travel).

Basic usage

final recorder = OmegaTimeTravelRecorder();
recorder.startRecording(channel, flowManager);
// ... user interacts, events are recorded ...
final session = recorder.stopRecording();

// Replay all
recorder.replay(session, channel, flowManager);

// Go to step 5 (time-travel)
recorder.replay(session, channel, flowManager, upToIndex: 5);

OmegaRecordedSession holds initialSnapshot and events. During replay the recorder does not record again. See doc/TIME_TRAVEL.md.

OmegaChannel

Definition: Central event bus. All communication between agents, flows and the UI goes through the channel. The emitter does not know who is listening; this decouples logic from the UI. There should only be one channel instance per app (created in OmegaRuntime.bootstrap and injected via OmegaScope).

Member Description
events Event stream. Subscribe to react (agents, flows, OmegaBuilder).
emit(OmegaEvent event) Publishes an event. All events subscribers receive it.
dispose() Closes the channel. Call when closing the app to avoid leaks.

Example:

channel.emit(OmegaEvent.fromName(AppEvent.authLoginRequest, payload: creds));
channel.events.listen((e) {
  if (e.name == AppEvent.authLoginSuccess.name) {
    final user = e.payloadAs<User>();
    if (user != null) goToHome(user);
  }
});

OmegaEvent

Definition: Represents "something that happened" in the system. It has an id (unique), name (semantic, e.g. "auth.login.success") and payload (optional data). To avoid magic strings, define an enum that implements OmegaEventName and use OmegaEvent.fromName(AppEvent.xxx, payload: data). To read the payload with type safety: event.payloadAs<User>() (returns null if the type does not match).

Member Description
name Event name. Listeners filter by this value.
payload Optional data. Use payloadAs<T>() for typed reading.
OmegaEvent.fromName(eventName, {payload, id, meta}) Factory with typed name. Generates an id if not provided.
// Create
channel.emit(OmegaEvent.fromName(AppEvent.authLoginSuccess, payload: LoginSuccessPayload(...)));
// Read in listener
final data = event.payloadAs<LoginSuccessPayload>();

OmegaIntent

Definition: Represents an action request with business meaning: "I want to log in", "I want to go to home". The UI does not call flow or agent methods; it emits an intent with flowManager.handleIntent(OmegaIntent.fromName(AppIntent.authLogin, payload: creds)). The FlowManager only sends it to flows that are in the running state. They are also used for navigation: when the channel emits an event named "navigation.intent" and payload = OmegaIntent, the navigator executes push/pushReplacement and passes the intent payload as RouteSettings.arguments. Typed names: OmegaIntent.fromName(OmegaIntentName, payload). Typed reading: intent.payloadAs<LoginCredentials>().

Member Description
name Intent name (e.g. "auth.login", "navigate.home").
payload Data. Use payloadAs<T>().
OmegaIntent.fromName(intentName, {payload, id}) Factory with typed name (OmegaIntentName).

OmegaEventName

Contract for typed event names. Implement with an enum (e.g. enum AppEvent implements OmegaEventName { authLoginSuccess('auth.login.success'); @override final String name; }) and use OmegaEvent.fromName(AppEvent.authLoginSuccess, payload: x).

OmegaIntentName

Contract for typed intent names. Implement with an enum and use OmegaIntent.fromName(AppIntent.authLogin, payload: creds).

OmegaObject

Base class: provides id and meta (metadata map). OmegaEvent, OmegaIntent and OmegaFailure extend it.

OmegaFailure

Error representation. message (human‑readable) and optional details. Useful to emit semantic errors through the channel.

OmegaAgent

Autonomous logic unit. It has an id, channel and behavior. It subscribes to the channel; the behavior evaluates context and returns reactions; the agent executes them in onAction. Call dispose() when closing.

Member Description
receiveIntent(OmegaIntent) Evaluates the intent with the behavior and executes the reaction in onAction.
onAction(String action, dynamic payload) Abstract. Implement the logic for each action.
onMessage(OmegaAgentMessage msg) Abstract. Response to direct messages.
emit(String name, {payload}) Publishes an event to the channel.

OmegaAgentBehaviorEngine

Rule engine: given a context (event or intent), it returns the first reaction whose rule matches. addRule(OmegaAgentBehaviorRule) registers rules; evaluate(OmegaAgentBehaviorContext) returns an OmegaAgentReaction or null.

OmegaAgentBehaviorRule

Rule: condition(context) indicates whether it applies; reaction(context) returns the OmegaAgentReaction to execute.

OmegaAgentBehaviorContext

Context passed to evaluate: event, intent and a copy of the agent state.

OmegaAgentReaction

Result of a rule: action (name) and payload. The agent receives it in onAction.

OmegaAgentProtocol

Agent registry. register(OmegaAgent); send(OmegaAgentMessage) to a single agent; broadcast(action, {payload}) to all.

OmegaAgentInbox

FIFO message queue. receive(message) adds; next() returns the next or null; hasMessages indicates whether there are pending messages.

OmegaAgentMessage

Direct message: from, to, action, payload. Sent with OmegaAgentProtocol.send.

OmegaFlow

Definition: A flow is a business flow (login, checkout, onboarding). It has states (OmegaFlowState: idle, running, sleeping, paused, ended) and only when it is in running does it process channel events and intents (in onEvent and onIntent). The flow orchestrates: it receives intents from the UI, emits events to the channel so that agents act, listens to events (e.g. "auth.login.success"), emits expressions to the UI ("loading", "success", "error") and can emit a navigation intent. The UI does not ask "are you loading?"; the flow announces the state with emitExpression. The screen subscribes to flow.expressions. The flow also has memory (key/value map) that persists while it is active and is included in the snapshot for persistence.

Member Description
expressions Stream of expressions towards the UI.
memory Key/value map that persists during the flow. Included in the snapshot.
emitExpression(String type, {payload}) Notifies the UI (loading, success, error).
getSnapshot() Returns OmegaFlowSnapshot (id, state, memory, lastExpression).
restoreMemory(Map) Replaces memory (restore on launch).

OmegaFlowManager

Manages all flows: registers, activates/pauses, distributes intents to those that are in running. wireNavigator(nav) connects the channel to the navigator.

Member Description
registerFlow(OmegaFlow) Registers a flow.
activate(id) Activates the flow without pausing the others. Several can be in running.
switchTo(id) Activates one and pauses the rest. A single "main" one.
handleIntent(OmegaIntent) Sends the intent to all flows in running.
getFlow(id) Returns the registered flow. So the UI can listen to expressions.
getAppSnapshot() Snapshot of the entire app (activeFlowId + all flows).
restoreFromSnapshot(OmegaAppSnapshot) Restores memory and active flow. Call when opening the app.

OmegaFlowState

States: idle, running, sleeping, paused, ended. Only in running are events and intents processed.

OmegaFlowExpression

Message from the flow to the UI: type ("loading", "success", "error") and payload. Read payload with type: expr.payloadAs<User>().

OmegaFlowContext

Context in onEvent/onIntent: event, intent and flow memory.

OmegaFlowSnapshot

Snapshot of a flow: flowId, state, memory, lastExpression. toJson() / fromJson(Map) for persistence.

OmegaAppSnapshot

Snapshot of the app: activeFlowId and list of OmegaFlowSnapshot. toJson() / fromJson(Map). Restore with FlowManager.restoreFromSnapshot.

OmegaSnapshotStorage

Optional interface: save(OmegaAppSnapshot) and load() → Future<OmegaAppSnapshot?>. Implement with disk, SharedPreferences or a backend.

OmegaScope

InheritedWidget that exposes channel and flowManager (and optionally initialFlowId). Any child uses OmegaScope.of(context).

OmegaBuilder

Widget that rebuilds when an event arrives at the channel. Optionally filter by eventName. Requires OmegaScope in the tree.

OmegaNavigator

Converts intents "navigate.id" / "navigate.push.id" into push/pushReplacement. navigatorKey is assigned to MaterialApp.navigatorKey. registerRoute(OmegaRoute); handleIntent(OmegaIntent) performs navigation. The intent payload → RouteSettings.arguments.

OmegaRoute / OmegaRoute.typed / routeArguments

OmegaRoute(id, builder) defines a screen. OmegaRoute.typed<T>(id, builder: (context, T? arguments)) lets the view receive the payload with type. If you do not use typed: routeArguments<T>(context) to read typed arguments.

OmegaInspector / Launcher / Receiver / Server

OmegaInspector: overlay panel with latest channel events and flow snapshots. Debug only (kDebugMode).

OmegaInspectorLauncher: button that on web opens the inspector in a new window (BroadcastChannel); on desktop/mobile opens the overlay in a dialog. In release the button is hidden.

OmegaInspectorReceiver: in the window with ?omega_inspector=1 it shows the inspector (data via BroadcastChannel). In release it shows a "debug only" message.

OmegaInspectorServer: on desktop/mobile and debug only, starts an HTTP server; open the URL printed in the console (e.g. http://localhost:9292) to view the inspector in the browser. On web it is a no-op.

OmegaConfig

Bootstrap configuration: agents, flows, routes, initialFlowId (optional). Passed to OmegaRuntime.bootstrap.

OmegaRuntime

OmegaRuntime.bootstrap(createOmegaConfig) creates the channel, builds the config, registers agents in the protocol, flows in the manager, routes in the navigator, connects the navigator to the channel and returns the runtime. The app uses channel, flowManager, navigator and initialFlowId to mount OmegaScope and MaterialApp.

Persistence and restore

Concept: A snapshot is a picture of the app state (active flow + state and memory of each flow). You can serialize it to JSON, save it when closing the app (or at save points) and restore it on open. This way the user does not lose context (e.g. current screen and in‑memory data of the flows).

Flow: On close (or at a key point): flowManager.getAppSnapshot()snapshot.toJson() → save (SharedPreferences, file with path_provider, backend). On open: load string/map → OmegaAppSnapshot.fromJson(map)flowManager.restoreFromSnapshot(snapshot). The manager restores the memory of each flow and activates the flow that was active. For persistence to be correct, the values in memory and in the payloads you save must be JSON‑serializable (primitives, List, Map).

Optional interface: OmegaSnapshotStorage defines save(OmegaAppSnapshot) and load() → Future<OmegaAppSnapshot?>. You can implement it with any storage you want (file, SharedPreferences, API) and call save/load from your app at the lifecycle points you prefer.

// Guardar
final snapshot = flowManager.getAppSnapshot();
await prefs.setString("omega", jsonEncode(snapshot.toJson()));
// Restaurar al iniciar
final s = prefs.getString("omega");
if (s != null) flowManager.restoreFromSnapshot(OmegaAppSnapshot.fromJson(jsonDecode(s)));

Testing

Agents: Create a channel and test agent that stores what it receives in onAction. Emit an event or call agent.receiveIntent(intent). After a short delay, check the variables.

Flows: Create a test flow, call flow.start(), listen to flow.expressions, call flow.receiveIntent(intent) or emit events. After a delay, check the received expression. No WidgetTester or Flutter is required.

See doc/TESTING.md in the repo for complete examples.

The Future is Reactive

Omega is not just a library; it is a way of thinking about software. Scalable, testable and ready for the real world.