REST API Handlers Architecture in AgentsView: A Modular Huma-Based Design

AgentsView implements its REST API handlers using a three-layer architecture built on the Huma router library, separating routing configuration, thin endpoint handlers, and delegated business logic into distinct concerns.

The AgentsView codebase (available at kenn-io/agentsview) organizes its HTTP interface through a clean, modular REST API handlers architecture that leverages the Huma framework for type-safe routing. This design splits responsibilities across router configuration, handler implementation, and data access layers, making the API extensible and testable.

Three-Layer Architecture of the REST API Handlers

The REST API handlers architecture in AgentsView follows a strict separation of concerns across three distinct layers.

Router and Route Groups

The top-level routing logic resides in internal/server/huma_route_groups.go. This file defines the main Huma router instance, registers sub-routers for each logical domain (sessions, search, settings, etc.), and applies shared middleware including logging, authentication, request ID injection, and timeout handling. The router groups aggregate related endpoints under common path prefixes such as /api/v1/sessions.

Endpoint Handler Functions

Individual handler files follow the naming convention huma_routes_[domain].go (e.g., huma_routes_sessions.go, huma_routes_search.go, huma_routes_pins.go). Each file contains tiny, single-purpose handler functions that receive a *huma.Context parameter. These handlers remain deliberately thin: they validate input through typed request structs, delegate data operations to the database layer, translate models into API DTOs, and write JSON responses or SSE events.

Business Logic and Data Access

Heavy computational work lives outside the handlers in dedicated packages under internal/db, internal/postgres, internal/parser, and internal/sync. Handlers import these packages to execute SQL queries, FTS5 search operations, analytics calculations, and file import pipelines. This delegation ensures that huma_routes_*.go files contain only HTTP-specific concerns while complex business rules remain testable in isolation.

Request Flow Through the Handler Pipeline

When a client sends an HTTP request, it traverses a standardized pipeline before returning a response:

  1. Incoming request arrives via net/http and enters the Huma router created in internal/server/server.go.
  2. Path matching occurs as the router compares the request path and HTTP verb against registered route groups (e.g., /api/v1/sessions/:id).
  3. Middleware chain executes from internal/server/middleware.go, handling authentication, request ID injection, and timeout management.
  4. Handler invocation passes a typed request struct (e.g., SessionDetailRequest) and the response writer (*huma.Context) to the specific endpoint function.
  5. Service delegation occurs as the handler calls the appropriate database or service layer (e.g., h.db.GetSessionByID).
  6. Response marshaling converts results into a response struct (e.g., SessionDetailResponse) and writes JSON to the client.
  7. Streaming handling for SSE endpoints registers the connection with broadcaster.go to push real-time events to subscribed clients.

Handler Implementation Pattern

All REST API handlers follow an identical structural pattern. A typical implementation in huma_routes_sessions.go looks like this:

func (h *handler) GetSessionDetail(ctx *huma.Context) error {
    // 1️⃣ Validate & decode request parameters (already done by Huma)
    req := ctx.Request.(*SessionDetailRequest)

    // 2️⃣ Call the DB layer
    sess, err := h.db.GetSessionByID(ctx, req.ID)
    if err != nil {
        return ctx.Error(http.StatusNotFound, "session not found", err)
    }

    // 3️⃣ Build response DTO
    resp := SessionDetailResponse{
        ID:      sess.ID,
        Title:   sess.Title,
        Created: sess.Created,
        // …
    }

    // 4️⃣ Write JSON
    return ctx.JSON(http.StatusOK, resp)
}

Because Huma generates request and response structs from the OpenAPI specification defined in openapi.go, the API contract remains synchronized with the implementation automatically.

Endpoint Categories and Route Organization

The REST API handlers are organized into logical groups, each residing in its own huma_routes_*.go file:

Key Source Files in the Architecture

Understanding the REST API handlers architecture requires familiarity with these specific files:

  • internal/server/server.go: Creates the Huma router, wires middleware, and starts the HTTP server.
  • internal/server/huma_route_groups.go: Configures top-level route groups and sub-router registration.
  • internal/server/middleware.go: Implements common middleware for logging, authentication, request IDs, and timeouts.
  • huma_routes_*.go: Individual handler files for each domain (sessions, search, pins, settings, analytics, import).
  • broadcaster.go: Central hub managing SSE event distribution to connected clients.
  • openapi.go: OpenAPI specification used by Huma to generate typed request/response structs.
  • internal/db/*.go, internal/postgres/*.go, internal/parser/*.go, internal/sync/*.go: Business logic and data access layers called by handlers.

Summary

  • AgentsView uses a three-layer architecture for its REST API handlers: router configuration, thin HTTP handlers, and delegated business logic.
  • The Huma framework provides type-safe routing and automatic request/response validation via OpenAPI specifications in openapi.go.
  • Handlers remain deliberately thin, delegating complex operations to packages like internal/db and internal/parser while focusing on HTTP concerns.
  • Middleware (logging, auth, timeouts) is applied at the router group level in huma_route_groups.go.
  • Real-time features use Server-Sent Events managed by broadcaster.go alongside standard JSON endpoints.

Frequently Asked Questions

Why does AgentsView use the Huma router instead of the standard library?

AgentsView adopts the Huma router because it generates type-safe request and response structs directly from the OpenAPI specification defined in openapi.go. This eliminates manual JSON marshaling errors, ensures the API documentation always matches the implementation, and provides built-in validation before handlers execute. According to the source code, this approach keeps handler functions in files like huma_routes_sessions.go focused on business logic rather than boilerplate parsing.

How does the REST API handler architecture support real-time updates?

The architecture supports real-time updates through Server-Sent Events (SSE) handled in huma_routes_events.go and managed by broadcaster.go. When a client connects to GET /api/v1/events, the handler registers the connection with the broadcaster, which maintains a registry of active client streams. When data changes occur elsewhere in the system, the broadcaster pushes events to all subscribed connections while the main handler logic remains stateless and non-blocking.

Where is authentication middleware applied in the request flow?

Authentication middleware is applied at the router group level in internal/server/huma_route_groups.go. The middleware chain defined in internal/server/middleware.go runs after the router matches a request path but before the specific handler function executes. This ensures that authentication, logging, and request ID injection occur consistently across all endpoints within a route group without requiring repetitive code in individual handlers.

How are request and response structs validated in the API handlers?

Validation occurs automatically through Huma's OpenAPI integration. The openapi.go file defines the API contract, which Huma uses to generate typed structs like SessionDetailRequest and SessionDetailResponse. When a request arrives, Huma validates the input against the specification before the handler function receives the context. If validation fails, Huma returns an appropriate error response before execution reaches the business logic in huma_routes_*.go files.

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 →