How the Next.js Client Interacts with the Backend in OpenMAIC

OpenMAIC bridges the React frontend and server logic through Next.js 13 App Router API routes, where client-side fetch calls invoke server-only handlers under app/api/** that execute business logic and return JSON responses.

OpenMAIC implements a classic client-server architecture using Next.js 13's App Router to separate UI rendering from data processing. The frontend operates as a React client using 'use client' directives, while backend functionality resides in API route handlers that run exclusively on the server. This pattern allows the application to offload heavy operations like session management and agent runtime orchestration to serverless Node.js functions while maintaining a lightweight browser interface.

Architecture Overview

The codebase follows a strict separation between client and server concerns. UI components marked with 'use client' execute in the browser and communicate via standard HTTP requests to internal endpoints.

Server-only execution occurs in files under app/api/**, which export route handlers configured for the Node.js runtime:

export const runtime = 'nodejs';

These handlers have unrestricted access to environment variables like DATABASE_URL and server-only utilities such as @/lib/config/feature-flags or the durable session store. Because they reside outside the 'use client' boundary, they can securely perform database operations and interact with external services without exposing credentials to the browser.

API Route Communication Flow

Every backend interaction follows a consistent request lifecycle:

  1. Client dispatch – React components invoke fetch() with relative paths to /api/* endpoints
  2. Route handling – Next.js matches the URL to the corresponding route.ts file (e.g., /api/agent/sessions → app/api/agent/sessions/route.ts)
  3. Server execution – The handler validates requests, queries databases, and queues background workers
  4. JSON response – Results serialize to JSON and return to the client
  5. State hydration – React hooks (useEffect, useState) parse responses and update the UI

This architecture ensures that sensitive operations and heavy computational tasks remain server-side while the client manages only presentation logic.

Runtime and Session Management

The primary interaction points demonstrate how OpenMAIC handles agent availability checks and conversation lifecycle management through specific API contracts.

Probing Agent Runtime Availability

When the home page loads at app/page.tsx, it verifies whether the Pro workbench should render by querying the runtime status:

useEffect(() => {
  fetch('/api/agent/runtime')
    .then(r => r.ok ? r.json() : null)
    .then(body => {
      workbenchRuntimeCache = body?.enabled === true;
      setWorkbenchRuntimeEnabled(workbenchRuntimeCache);
    })
    .catch(() => {/* ignore */});
}, []);

The handler at app/api/agent/runtime/route.ts evaluates feature flags and infrastructure health, returning a structured object:

{ "enabled": true, "runtimeEnabled": true }

This boolean response determines whether the UI exposes advanced agent capabilities or falls back to basic functionality.

Listing Active Sessions

The workspace shell in components/workbench/workspace/WorkspaceShell.tsx populates the navigation rail by fetching durable session records. The implementation includes timeout handling and credential propagation:

async function fetchSessions(): Promise<ProHomeSessionItem[]> {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 15000);
  try {
    const response = await fetch('/api/agent/sessions', {
      credentials: 'include',
      signal: controller.signal,
    });
    if (!response.ok) throw new Error(`${response.status}`);
    const body = await response.json();
    if (!Array.isArray(body)) throw new Error('invalid list response');
    return body as ProHomeSessionItem[];
  } finally {
    clearTimeout(timeout);
  }
}

The corresponding handler in app/api/agent/sessions/route.ts validates the request context, extracts the owner ID from the session, and queries the persistent store for metadata arrays. This endpoint supports both retrieval and mutation operations depending on the HTTP method.

Creating New Agent Sessions

When users initiate conversations, the client POSTs structured payloads to the same sessions endpoint:

await fetch('/api/agent/sessions', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    prompt: userPrompt,
    skill: selectedSkillId,
    materialIds: uploadedIds,
  }),
});

The POST handler in app/api/agent/sessions/route.ts (lines 37‑84) performs transactional operations: creating the session record, binding uploaded materials through foreign key relationships, and queuing the initial user message for background processing by the agent worker pool. This ensures that session state persists even if the client disconnects during the request.

Server-Side Implementation Details

API routes in OpenMAIC leverage the full Node.js ecosystem because they explicitly opt out of edge runtime constraints. The export const runtime = 'nodejs' declaration enables native modules and database drivers required for the application’s durable storage layer.

Handlers import shared server utilities using path aliases:

import { checkFeatureFlag } from '@/lib/config/feature-flags';
import { sessionStore } from '@/lib/db/session-store';

This modular structure keeps business logic decoupled from HTTP transport concerns. Responses maintain a consistent JSON schema that client-side TypeScript interfaces consume, ensuring type safety across the network boundary.

Summary

  • OpenMAIC uses Next.js 13 App Router API routes under app/api/** to expose backend functionality to the React client.
  • Client components call fetch('/api/agent/*') to check runtime availability, list sessions, and create new conversations.
  • Server handlers execute in the Node.js runtime with access to databases and feature flags, returning JSON that hydrates React state.
  • Session management combines GET requests for retrieval and POST requests for creation, both handled by app/api/agent/sessions/route.ts.
  • Security-critical operations remain server-only, preventing exposure of database connections or internal configuration to the browser.

Frequently Asked Questions

How does the OpenMAIC frontend detect if the agent runtime is available?

On initialization, the home page in app/page.tsx sends a fetch request to /api/agent/runtime. The handler returns a boolean enabled flag derived from infrastructure health checks and feature flag evaluations. If the runtime is unavailable, the UI suppresses Pro workbench features and displays fallback content.

What distinguishes GET from POST requests to /api/agent/sessions?

The GET method retrieves an array of existing session metadata for the authenticated user, validating credentials via the credentials: 'include' option. The POST method creates a new session record, accepts a JSON body containing the initial prompt and skill selection, and triggers background job queuing for agent processing.

Why does OpenMAIC use API routes instead of Next.js Server Actions?

According to the OpenMAIC source code, the application relies on API routes to maintain explicit HTTP semantics and support complex request lifecycle management, such as AbortController timeouts and streaming responses. Additionally, API routes provide clearer separation of concerns for external client integration and enable consistent error handling patterns across the agent runtime interface.

How does the client maintain authentication state across backend requests?

The client includes credentials: 'include' in all fetch calls to /api/agent/sessions, ensuring cookies or bearer tokens transmit automatically with each request. Server handlers validate these credentials against the session store before executing database operations, enforcing row-level security based on the extracted owner ID.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →