# How Magnitude Utilizes Effect-TS for Its Reactive, Event-Driven Architecture

> Discover how Magnitude uses Effect-TS for its reactive, event-driven architecture. Leverage typed side effects, scoped resources, and dependency injection for deterministic systems.

- Repository: [Magnitude/magnitude](https://github.com/magnitudedev/magnitude)
- Tags: architecture
- Published: 2026-09-05

---

**Magnitude leverages the Effect-TS library to model every side effect as a typed, composable value, enabling a deterministic, event-driven architecture through scoped resource management, dependency injection, and reactive streams.**

The Magnitude repository wires together complex browser automation, UI state, and background processing by treating asynchronous workflows as data. Built on **Effect-TS**, the codebase replaces imperative promise chains with functional effects, ensuring that resource cleanup, error paths, and concurrent data flows are handled explicitly rather than managed implicitly.

## Effect-Based Async Workflows

At the heart of Magnitude’s runtime is the `Effect` type. Instead of native `async/await`, developers use `Effect.gen` to describe sequential operations and `Effect.runPromise` or `Effect.runFork` to execute them.

In **[message-uploads.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/lib/message-uploads.ts)**, the ingestion pipeline wraps file I/O with `Effect.gen`, allowing the compiler to track success and failure types through the entire chain. Composed effects are executed concurrently using `Effect.all` or sequenced with `Effect.forEach`, giving fine-grained control over parallelism without losing type safety.

## Scoped Resource Management

Long-lived connections such as the ACN (Agent Control Network) daemon require deterministic cleanup. Magnitude uses **Effect-TS** `Scope` to bracket resource acquisition with guaranteed release.

The browser integration layer in **[browser.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/lib/browser.ts)** creates an `acnScope` via `Scope.make`. When the effect finishes—whether successfully or with an error—the scope is closed with `Scope.close(acnScope, Exit.void)`, preventing memory leaks. This pattern appears throughout the codebase wherever external processes or network sockets are managed.

## Dependency Injection via Context

Magnitude decouples services using the Effect-TS **Context** system. Services are declared as tags (e.g., `AcnInstanceManager`) and fulfilled at the edge of the system via `Effect.provideService`.

Rather than importing concrete classes, business logic requests capabilities through tags. This architectural boundary, documented in **[client-common/AGENTS.md](https://github.com/magnitudedev/magnitude/blob/main/client-common/AGENTS.md)**, allows the same effect code to run against mocks in tests or live implementations in production without modification.

## Reactive State with Effect-Query

The reactive layer is powered by **Effect-Query**, a package that watches the event store and materializes read models (projections) such as `Window` and `TaskGraph`. When underlying events change, the query layer re-executes the effect pipeline, pushing updates to observers.

In **[observed-state.ts](https://github.com/magnitudedev/magnitude/blob/main/packages/icn/src/observed-state.ts)** within the `packages/icn` directory, projections are built by replaying events through Effect workflows, ensuring that the UI always reflects a consistent, deterministic state derived from the event log.

## Typed Error Handling and Structured Logging

Errors are not thrown; they are returned as tagged values. The codebase defines specific error tags like `ConversationPreferenceStorageError` and handles them with `Effect.catchTag`. This makes failure paths explicit and exhaustively checkable by TypeScript.

Operational visibility comes from `Effect.logWarning` and `Effect.annotateLogs`, used heavily in **[conversation-preferences.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/stores/conversation-preferences.ts)** to enrich log entries with correlation IDs and user context before persisting state.

## Streaming for Real-Time Data Flows

For high-volume, real-time data, Magnitude uses `Effect.Stream`. The development server orchestration in **[dev-server.ts](https://github.com/magnitudedev/magnitude/blob/main/apps/cli/src/dev-server.ts)** combines `Stream`, `Layer`, and `Scope` to tail log files and broadcast build events to connected browsers, automatically applying back-pressure when consumers slow down.

## Practical Implementation Examples

### Orchestrating Scoped Resources

The following pattern demonstrates how Magnitude manages an ACN connection lifecycle explicitly:

```typescript
import { Effect, Scope, Exit } from "effect";
import { AcnInstanceManager } from "@magnitudedev/acn-protocol";

const acnScope = await Effect.runPromise(Scope.make());

const manager = await Effect.runPromise(
  Effect.provide(
    AcnInstanceManager,
    await AcnInstanceManager.create(),
    // … your effect body …
  )
);

await Effect.runPromise(
  manager.close.pipe(
    Effect.ensuring(Scope.close(acnScope, Exit.void))
  )
);

```

### Declaring and Injecting Services

Dependency injection is configured at the composition root:

```typescript
import { Effect, Context } from "effect";

export interface Logger {
  log: (msg: string) => void;
}
export const Logger = Context.Tag<Logger>();

class ConsoleLogger implements Logger {
  log(msg: string) { console.log(msg); }
}

const greet = Effect.gen(function* () {
  const logger = yield* Logger;
  logger.log("Hello, Magnitude!");
});

await Effect.runPromise(
  greet.pipe(Effect.provideService(Logger, new ConsoleLogger()))
);

```

### Subscribing to Reactive Projections

UI components observe state changes through Effect-Query subscriptions:

```typescript
import { EffectQuery } from "@magnitudedev/effect-query";
import { Projection } from "@magnitudedev/event-core";

const windowProjection = Projection.make("Window");

const subscription = EffectQuery.subscribe(windowProjection, {
  onNext: (state) => console.log("Window state:", state),
  onError: (e) => console.error(e),
});

await Effect.runPromise(subscription.close);

```

## Key Files Driving the Architecture

| Architectural Area | Key File | Implementation Detail |
|--------------------|----------|----------------------|
| Reactive stores | **[conversation-preferences.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/stores/conversation-preferences.ts)** | Uses `Effect.tryPromise` and error tagging for persistent state. |
| Browser integration | **[browser.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/lib/browser.ts)** | Demonstrates scoped ACN connections and `Effect.provideService`. |
| File uploads | **[message-uploads.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/lib/message-uploads.ts)** | Orchestrates concurrent processing with `Effect.all` and `Effect.forEach`. |
| UI lifecycle | **[use-menu-actions.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/hooks/use-menu-actions.ts)** | Leverages `Effect.gen` and `Effect.addFinalizer` for cleanup. |
| Dev server | **[dev-server.ts](https://github.com/magnitudedev/magnitude/blob/main/apps/cli/src/dev-server.ts)** | Combines `Stream`, `Layer`, and `Scope` for live reloading. |
| Automation scripts | **[reset-onboarding.ts](https://github.com/magnitudedev/magnitude/blob/main/scripts/reset-onboarding.ts)**, **[kill-all.ts](https://github.com/magnitudedev/magnitude/blob/main/scripts/kill-all.ts)**, **[accept-release-candidate.ts](https://github.com/magnitudedev/magnitude/blob/main/scripts/accept-release-candidate.ts)** | Complex CLI workflows composed with `Effect.gen` and layered services. |
| Event projections | **[observed-state.ts](https://github.com/magnitudedev/magnitude/blob/main/packages/icn/src/observed-state.ts)** | Materializes read models using Effect-Query subscriptions. |
| DI boundaries | **[client-common/AGENTS.md](https://github.com/magnitudedev/magnitude/blob/main/client-common/AGENTS.md)** | Documents the effect-based service contracts used across packages. |

## Summary

- **Effect-TS** provides the functional foundation for all asynchronous work in Magnitude, replacing untracked promises with typed `Effect` values.
- **Scoped resources** guarantee cleanup of browser connections and file handles through explicit `Scope` management.
- **Dependency injection** via `Context.Tag` decouples business logic from infrastructure, enabling testable, modular architecture.
- **Reactive projections** built with Effect-Query turn the event store into live, observable state streams.
- **Typed errors** and structured logging make operational failures explicit and debuggable.

## Frequently Asked Questions

### How does Effect-TS improve error handling compared to native try/catch?

Magnitude models errors as distinct tags (e.g., `ConversationPreferenceStorageError`) rather than generic `Error` instances. Using `Effect.catchTag`, developers handle specific failure modes exhaustively, and the TypeScript compiler ensures that no error case is accidentally ignored.

### What is the role of Scope in Magnitude's browser automation?

`Scope` acts as a value-based bracket for resources. In **[browser.ts](https://github.com/magnitudedev/magnitude/blob/main/web/src/lib/browser.ts)**, the ACN connection is acquired within a scope and automatically released when the scope closes, preventing resource leaks even when tabs crash or network errors occur.

### Why use Effect-Query instead of a traditional state management library?

Effect-Query integrates with Magnitude’s event-sourced core. It re-executes effect pipelines when new events arrive, producing projections like `Window` or `TaskGraph` that are always consistent with the event log. This eliminates the need for manual cache invalidation or imperative state updates.

### Can I run Magnitude's effects in a standard Node.js script?

Yes. Scripts such as **[reset-onboarding.ts](https://github.com/magnitudedev/magnitude/blob/main/scripts/reset-onboarding.ts)** run standalone by invoking `Effect.runPromise` at the entry point. The same effect code can execute in Node.js, the browser, or test environments without modification, provided the required services are supplied via layers.