DEV Community

Cover image for Building a Real-Time AI Agent Dashboard in Angular 21: How We Used Signals, OnPush to Ship a Production-Ready LLM Monitor
Square Bootstrap
Square Bootstrap

Posted on • Originally published at squarebootstrap.com

Building a Real-Time AI Agent Dashboard in Angular 21: How We Used Signals, OnPush to Ship a Production-Ready LLM Monitor

AgentOps Pro launches March 10, 2026 — a production-ready Angular 21 template for teams monitoring LLM agents at scale. Here's how we built it, and why every architectural decision matters.


AI teams are deploying agents faster than they can monitor them. You have GPT-4o orchestrating sub-agents, Claude 3.5 handling reasoning chains, Gemini processing retrieval — and your observability stack is a mix of console logs and Grafana panels that weren't designed for agent workflows.

We built AgentOps Pro to close that gap. It's a fully-featured Angular 21 dashboard template with 23 pages, 31 reusable components, real-time WebSocket integration, and a signal-based architecture that delivers 60fps performance even while streaming thousands of agent events per minute.

Here's the complete architecture story.


Why Angular 21 for an AI Dashboard?

When we evaluated frameworks, Angular 21 won on three counts:

  1. Signals are production-stable — Angular's reactive primitive eliminates zone.js overhead. Every state change is precise, targeted, and zero-allocation on unchanged subtrees.
  2. Standalone components are now the default — No NgModules means full tree-shaking. Our initial bundle is under 800kB for 23 routes.
  3. Lazy loading is first-class — Each of our 23 feature pages loads as a separate content-hashed chunk. Users loading the Dashboard don't download the Compliance Audit module.

React would have worked. Vue would have worked. But for a team already comfortable with TypeScript-first tooling and wanting ChangeDetectionStrategy.OnPush baked in everywhere, Angular 21 was the productive choice.


The Signal-Based State Architecture (No NgRx)

This is the architectural decision we're most proud of. We rejected NgRx entirely and built a central AgentStore using Angular's native signal APIs.

@Injectable({ providedIn: 'root' })
export class AgentStore {
  // Private mutable state
  private readonly _agents = signal<Agent[]>([]);
  private readonly _executions = signal<AgentExecution[]>([]);
  private readonly _metrics = signal<SystemMetrics>(defaultMetrics);

  // Public read-only exposure — components can't mutate directly
  readonly agents = this._agents.asReadonly();
  readonly executions = this._executions.asReadonly();
  readonly metrics = this._metrics.asReadonly();

  // Computed derived state — memoized, recalculates only on dependency change
  readonly activeAgents = computed(() =>
    this._agents().filter(a => a.status === 'active')
  );

  readonly totalCost = computed(() =>
    this._executions().reduce((sum, e) => sum + e.cost, 0)
  );

  readonly executionStats = computed<ExecutionStats>(() => {
    const execs = this._executions();
    const completed = execs.filter(e => e.status === 'completed');
    return {
      total: execs.length,
      successRate: completed.length / execs.length,
      avgDuration: avg(completed.map(e => e.duration)),
      totalTokens: execs.reduce((sum, e) => sum + e.tokens, 0),
    };
  });
}
Enter fullscreen mode Exit fullscreen mode

The pattern is simple: private signals, public read-only, computed derivations. No actions. No reducers. No selectors. Just TypeScript.

Every service follows the same convention:

@Injectable({ providedIn: 'root' })
export class CostOptimizerService {
  private readonly store = inject(AgentStore);

  readonly recommendations = computed(() => {
    const executions = this.store.executions();
    // Analyze expensive model usage, caching opportunities, batch patterns
    return this.generateRecommendations(executions);
  });
}
Enter fullscreen mode Exit fullscreen mode

The result: 31 services, zero subscription leaks, and derived state that's always consistent.

OnPush Change Detection Everywhere
Every component in AgentOps Pro uses ChangeDetectionStrategy.OnPush. Not as an optimization pass we added later — as a requirement from day one.

@Component({
  selector: 'app-agent-monitor',
  standalone: true,
  imports: [ExecutionTimeline, AgentQueuePanel, MetricsPanel],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    @for (agent of activeAgents(); track agent.id) {
      <app-execution-timeline [agent]="agent" />
    }
  `
})
export class AgentMonitorComponent {
  private readonly store = inject(AgentStore);
  readonly activeAgents = this.store.activeAgents;
}
Enter fullscreen mode Exit fullscreen mode

When a WebSocket event updates _agents, Angular's signal graph propagates the change to only the components that depend on it. With 200+ agent executions streaming per minute, this is the difference between 60fps and 12fps.

Note the @for control flow — Angular 17+ syntax, not *ngFor. It's faster and catches duplicate tracking key errors at compile time.

Real-Time WebSocket with Dual-Mode Operation
The WebSocketService supports two modes: real WebSocket connection and a fully-simulated mock mode for offline development and the ThemeForest template distribution.

// In environment.themeforest.ts — the $59 template tier
export const environment = {
  mockMode: true,
  realTimeWebSocket: true, // Mock ticker, no actual WS server needed
  features: {
    orchestrationPlanner: true,
    complianceAudit: true,
    halluccinationDetection: true,
    // All 10 showcase features work with zero backend
  }
};
Enter fullscreen mode Exit fullscreen mode

In mock mode, the service generates statistically realistic event sequences — agent status transitions, cost accumulations, completion events — at 2-second intervals. When you flip mockMode: false and point wsUrl at a real endpoint, everything works with zero code changes.

The connection manager handles reconnection with exponential backoff:

readonly connectionStatus = signal<'connected' | 'connecting' | 'disconnected' | 'error'>('disconnected');

private reconnect() {
  const delay = Math.min(3000 * Math.pow(2, this.attempts), 30000);
  setTimeout(() => this.connect(), delay);
}
Enter fullscreen mode Exit fullscreen mode

10 Showcase Features: What's Inside
AgentOps Pro ships with 23 fully implemented pages. Here are the 10 that define the product:

  1. Real-Time Dashboard
    Canvas-based 60fps wave animation with particle effects. Live system metrics — token count, cost burn rate, context window utilization — update in real time as agents execute. A force-directed D3.js graph shows agent topology with animated connection edges.

  2. Agent Monitor
    Per-agent execution timelines. Queue depth tracking. Phase-by-phase step inspector (planning → executing → responding). Per-execution cost and latency breakdown with token counts.

  3. Orchestration Planner
    DAG visualization of multi-agent plans using ngx-graph. Task dependency resolution, blocked task detection, and load distribution across the agent fleet.

  4. Cost Optimizer
    Real-time model pricing for GPT-4o, Claude 3.5, Gemini 1.5, and others. Identifies expensive model usage on low-token tasks, recommends batching, and flags caching opportunities.

  5. Prompt Manager
    Git-like version history for prompts. A/B testing with configurable traffic splits. Statistical significance tracking. Automatic rollback.

  6. Agent Performance
    Benchmark leaderboard. Side-by-side model comparison on latency, cost, and quality. Live load test runner.

  7. Session Replay
    Frame-accurate step-through debugger with scrubber timeline. Decision tree visualization at each reasoning step.

  8. Hallucination Detection
    Confidence scoring with animated SVG circular gauge. Source citation engine. Side-by-side ground-truth diff viewer.

  9. LLM Playground
    Multi-model sandbox with streaming responses, parameter tuning (temperature, topP, max tokens), and tool calling simulation.

  10. Compliance Audit
    PII detection. GDPR/HIPAA/SOC2 ruleset enforcement. Immutable audit log. OpenTelemetry trace links per compliance event.

The Design System: 150+ CSS Custom Properties
The dark neon theme is fully token-driven. Zero hardcoded colors anywhere in the codebase. A few examples:

// _tokens.scss
--accent-primary: #00e5ff;    // Cyan — primary actions
--accent-success: #00e676;    // Green — healthy agents
--accent-warning: #ff9100;    // Orange — degraded state
--accent-error: #ff5252;      // Red — critical alerts
--accent-ai: #b388ff;         // Purple — AI/ML features

--glass-bg: rgba(8, 16, 28, 0.9);
--backdrop-blur: blur(8px);

--transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-normal: 200ms cubic-bezier(0.4, 0, 0.2, 1);
Enter fullscreen mode Exit fullscreen mode

Glassmorphism panels use layered backgrounds — dark navy base, backdrop-filter: blur, and a 5–15% white border — to create depth without performance cost on modern GPUs.

Lazy Loading: 23 Routes, Each a Separate Chunk

// app.routes.ts
export const routes: Routes = [
  {
    path: 'dashboard-v1',
    loadComponent: () => import('./features/dashboard-v1/dashboard-v1')
      .then(m => m.Dashboardv1Component)
  },
  {
    path: 'compliance-audit',
    loadComponent: () => import('./features/compliance-audit/compliance-audit')
      .then(m => m.ComplianceAuditComponent)
  },
  // ... 21 more routes
];
Enter fullscreen mode Exit fullscreen mode

Each chunk is content-hashed. dashboard-v1.abc123.js. When we ship a fix to the Compliance Audit page, only users who navigate there download the update. The rest hit CDN cache.

31 Shared Components with Barrel Exports

// src/app/shared/components/index.ts
export * from './agent-network/agent-network';
export * from './circular-gauge/circular-gauge';
export * from './execution-timeline/execution-timeline';
export * from './wave-canvas/wave-canvas';
// ... 27 more

// In any feature component:
import { AgentNetwork, CircularGauge, WaveCanvas } from '@app/shared/components';
Enter fullscreen mode Exit fullscreen mode

This is the pattern that makes the 31-component library composable. Feature pages assemble dashboards from atomic components. Each component is standalone — it declares its own imports, has its own SCSS, and is independently tree-shakeable.

What We Learned
Use signals everywhere, not just in stores. We started with signals only in services, but moved them into components too. The result: no AsyncPipe, no subscribe() calls, no manual cleanup.

OnPush is not optional for real-time UIs. During development, we temporarily removed OnPush from the Agent Monitor to debug a rendering issue. Frame rate dropped from 60 to 8fps under normal load. It went back on immediately.

Mock mode pays for itself. Building the full UI against a mock data layer first — before the backend existed — let us validate UX assumptions without API dependencies. When we connected the real backend, the UI worked on the first attempt.

CSS custom properties beat CSS-in-JS for dashboards. Our glassmorphism effects, glow intensities, and animation timings are all tokens. Theming is a variable swap, not a component tree rewrite.

Launch: March 10, 2026
AgentOps Pro v1.0.0 launches on March 10, 2026 on ThemeForest.

23 fully implemented pages
31 reusable Angular 21 components
Signal-based state management (no NgRx)
Real-time WebSocket + mock mode
Dark neon design system with 150+ CSS tokens
Full source code, commercial license
View the live demo → AgentOps AI - Angular Dashboard Template

If you're building an AI product or need a production-ready Angular dashboard foundation, this is worth a look. Questions? Drop them in the comments.

Built with Angular 21, TypeScript 5.9, Chart.js, D3.js, ngx-graph, and a lot of real-time thinking.

Top comments (0)