Skip to content

Architecture

Understanding how AgentForge processes requests.

Request Flow

┌─────────────────────────────────────────────────────────────────┐
│                         User Request                            │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│                      Middleware Pipeline                        │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐  ┌─────────────┐  │
│  │  Logging  │→ │   Retry   │→ │  Circuit  │→ │   Custom    │  │
│  │           │  │           │  │  Breaker  │  │             │  │
│  └───────────┘  └───────────┘  └───────────┘  └─────────────┘  │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│                         Agent Core                              │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                    Message Builder                       │   │
│  │         (system prompt + history + user input)           │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│                          Provider                               │
│         (OpenAI / Anthropic / Cohere / Gemini / Together)       │
└─────────────────────────────────────────────────────────────────┘


                    ┌───────────────────────┐
                    │   Tool Calls Needed?  │
                    └───────────────────────┘
                         │            │
                        Yes           No
                         │            │
                         ▼            │
┌────────────────────────────────┐    │
│       Tool Execution Loop      │    │
│  ┌──────────────────────────┐  │    │
│  │  1. Parse tool call      │  │    │
│  │  2. Validate with Zod    │  │    │
│  │  3. Execute tool         │  │    │
│  │  4. Return result        │  │    │
│  │  5. Send back to LLM     │  │    │
│  └──────────────────────────┘  │    │
│         ↻ Repeat if needed     │    │
└────────────────────────────────┘    │
                         │            │
                         ▼            ▼
┌─────────────────────────────────────────────────────────────────┐
│                       Final Response                            │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│                         Event Hooks                             │
│     (request:complete, tool:execute, tokens:used, etc.)         │
└─────────────────────────────────────────────────────────────────┘

Core Components

Agent

The central orchestrator that manages the conversation loop:

typescript
const agent = new Agent({
  provider,      // LLM provider instance
  tools,         // Array of tool definitions
  middleware,    // Request/response processors
  memory,        // Conversation history manager
  systemPrompt,  // Base instructions for the LLM
});

Provider

Abstraction layer for LLM APIs. All providers implement the same interface:

typescript
interface Provider {
  generate(messages: Message[], options?: GenerateOptions): Promise<Response>;
  stream(messages: Message[], options?: StreamOptions): AsyncIterable<Chunk>;
}

Middleware

Processors that wrap requests and responses:

typescript
interface Middleware {
  name: string;
  before?(context: RequestContext): Promise<RequestContext>;
  after?(context: ResponseContext): Promise<ResponseContext>;
  onError?(error: Error, context: ErrorContext): Promise<void>;
}

Tools

Type-safe function definitions the LLM can call:

typescript
const tool = defineTool({
  name: 'search',
  description: 'Search the web',
  schema: z.object({ query: z.string() }),
  execute: async ({ query }) => {
    return { results: await searchApi(query) };
  },
});

Resilience Layer

┌─────────────────────────────────────────────────────────────┐
│                    Resilience Stack                         │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐   │
│  │                  Circuit Breaker                     │   │
│  │   Prevents cascade failures when provider is down    │   │
│  │   States: CLOSED → OPEN → HALF_OPEN → CLOSED        │   │
│  └─────────────────────────────────────────────────────┘   │
│                           │                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                  Retry with Backoff                  │   │
│  │   Exponential backoff: 1s → 2s → 4s → 8s (max)      │   │
│  │   Retryable: RATE_LIMIT, TIMEOUT, SERVER_ERROR      │   │
│  └─────────────────────────────────────────────────────┘   │
│                           │                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                     Fallback                         │   │
│  │   Switch to backup provider if primary fails         │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Memory Management

typescript
// Conversation history is managed automatically
agent.memory.add({ role: 'user', content: 'Hello' });
agent.memory.add({ role: 'assistant', content: 'Hi there!' });

// Strategies for long conversations
const memory = new SlidingWindowMemory({ maxMessages: 20 });
const memory = new TokenLimitMemory({ maxTokens: 4000 });
const memory = new SummaryMemory({ summarizeAfter: 10 });

Released under the MIT License.