Architecture

Express-Inspired Flow

Liz uses an Express-style middleware architecture where each request flows through a series of middleware functions. This approach provides a clear, predictable processing pipeline that's easy to understand and extend.

Standard Middleware Pipeline

  1. validateInput: Ensures required fields are present
  2. loadMemories: Retrieves relevant conversation history
  3. wrapContext: Builds the context for LLM interactions
  4. createMemoryFromInput: Stores the user's input
  5. router: Determines and executes the appropriate route handler

Agent Framework

The AgentFramework class in src/framework orchestrates the middleware pipeline and handles request processing:

import { AgentFramework } from "./framework";
import { standardMiddleware } from "./middleware";

const framework = new AgentFramework();

// Add middleware
standardMiddleware.forEach((middleware) => 
  framework.use(middleware)
);

// Process requests
framework.process(input, agent, res);

Agents vs. Middleware

Agent

  • Defines personality and capabilities
  • Holds system prompt and style context
  • Manages route definitions
  • Provides agent-specific context

Middleware

  • Handles request processing
  • Manages memory operations
  • Builds context for LLM
  • Routes requests to handlers

Route Handling

Routes define how an agent handles different types of interactions. The router middleware uses LLM to select the most appropriate handler:

// Adding a route to an agent
agent.addRoute({
  name: "conversation",
  description: "Handle natural conversation",
  handler: async (context, req, res) => {
    const response = await llmUtils.getTextFromLLM(
      context,
      "anthropic/claude-3-sonnet"
    );
    await res.send(response);
  }
});

Request Flow Example

1. Client sends request to /agent/input
   ↓
2. validateInput checks required fields
   ↓
3. loadMemories fetches conversation history
   ↓
4. wrapContext builds prompt with memories
   ↓
5. createMemoryFromInput stores request
   ↓
6. router selects appropriate handler
   ↓
7. handler processes request with LLM
   ↓
8. Response sent back to client