Updated architecture with current structure
This commit is contained in:
parent
1042ee5d22
commit
8398a9aba4
2 changed files with 335 additions and 0 deletions
331
ARCHITECTURE.md
Normal file
331
ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,331 @@
|
||||||
|
# Agent System Architecture Diagram
|
||||||
|
|
||||||
|
## System Overview (current stack)
|
||||||
|
|
||||||
|
Docker Compose (dev) services on one network:
|
||||||
|
|
||||||
|
- `web` (Vite dev) :5173
|
||||||
|
- `api` (Django + Channels) :8000
|
||||||
|
- `celery` worker shares Django code
|
||||||
|
- `fyp-redis` broker/channel :6379
|
||||||
|
- `mcp-agent-server` MCP runtime :8001 (HTTP)
|
||||||
|
|
||||||
|
MCP wiring:
|
||||||
|
|
||||||
|
- `MCP_AGENT_URL=http://mcp-agent-server:8001` (required)
|
||||||
|
- MCP server runs in HTTP mode, exposes `/execute` and `/health` endpoints
|
||||||
|
- All agent execution delegates to the remote MCP server (no local LLM fallback)
|
||||||
|
|
||||||
|
Flow: Frontend → API (HTTP), Frontend ↔ AgentConsumer (WS), API queues Celery, Celery calls MCP server over HTTP, events return via Redis → Channels → WS.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ FRONTEND (Vue 3 + TypeScript) │
|
||||||
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────────┐ │
|
||||||
|
│ │ Agents.vue │ │ AgentDetail.vue │ │ agentStore.ts │ │
|
||||||
|
│ ├─────────────────┤ ├──────────────────────┤ ├─────────────────────┤ │
|
||||||
|
│ │ • List agents │ │ • Run execution │ │ • WebSocket connect │ │
|
||||||
|
│ │ • Fetch from API│ │ • JSON input │ │ • Event handling │ │
|
||||||
|
│ │ • Show status │ │ • Live log display │ │ • State management │ │
|
||||||
|
│ └────────┬────────┘ │ • Stop button │ │ • Auto-reconnect │ │
|
||||||
|
│ │ │ • Status indicator │ │ • Type-safe API │ │
|
||||||
|
│ │ └────────┬─────────────┘ └─────────────────────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
└───────────┼────────────────────┼─────────────────────────────────────────┘
|
||||||
|
│ │
|
||||||
|
│ │ WebSocket
|
||||||
|
│ HTTP/REST │
|
||||||
|
▼ ▼
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ BACKEND (Django + Channels) │
|
||||||
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌─────────────────┐ ┌──────────────────────────┐ ┌─────────────────┐ │
|
||||||
|
│ │ AgentViewSet │ │ AgentConsumer │ │ Middleware │ │
|
||||||
|
│ ├─────────────────┤ ├──────────────────────────┤ ├─────────────────┤ │
|
||||||
|
│ │ REST API: │ │ WebSocket Handler: │ │ • Auth check │ │
|
||||||
|
│ │ • GET /agent/ │ │ • connect() │ │ • User validate │ │
|
||||||
|
│ │ • POST /agent/ │ │ • receive() │ │ • Group mgmt │ │
|
||||||
|
│ │ • GET /agent/id │ │ • handle_start_agent() │ └─────────────────┘ │
|
||||||
|
│ │ │ │ • handle_stop_agent() │ │
|
||||||
|
│ │ Returns: Agent │ │ • agent_event() │ ┌─────────────────┐ │
|
||||||
|
│ │ metadata │ │ • agent_completed() │ │ Serializers │ │
|
||||||
|
│ └────────┬────────┘ │ • agent_error() │ ├─────────────────┤ │
|
||||||
|
│ │ └────────┬─────────────────┘ │ • AgentSerializer │
|
||||||
|
│ │ │ │ • ExecutionSer. │ │
|
||||||
|
│ │ │ │ • EventSerializer │
|
||||||
|
│ │ │ └────────┬────────┘ │
|
||||||
|
│ │ │ │ │
|
||||||
|
│ ▼ ▼ ▼ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Django Database (SQLite/PostgreSQL) │ │
|
||||||
|
│ ├─────────────────────────────────────────────────────────────────┤ │
|
||||||
|
│ │ • Agent (uuid, name, description, status, user) │ │
|
||||||
|
│ │ • AgentExecution (uuid, input_data, output_data, status) │ │
|
||||||
|
│ │ • AgentEvent (uuid, event_type, content, timestamp) │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
└──────────────────────┬───────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
│ Celery Task Queue
|
||||||
|
▼
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ CELERY WORKER PROCESS │
|
||||||
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ start_agent_task_mcp() [MCP-only execution] │ │
|
||||||
|
│ ├──────────────────────────────────────────────────────────────────┤ │
|
||||||
|
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
|
||||||
|
│ │ │ 1. Initialize & Output "started" event │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ 2. Call MCPAgentClient.execute_agent() │ │ │
|
||||||
|
│ │ │ └─ POST to {MCP_AGENT_URL}/execute │ │ │
|
||||||
|
│ │ │ with: agent_id, query, input_data │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ 3. Await response from MCP server │ │ │
|
||||||
|
│ │ │ (handles all RAG, LLM, context retrieval) │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ 4. Forward any events from MCP to WebSocket │ │ │
|
||||||
|
│ │ │ └─ Progress, message, step events displayed live │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ │ 5. Save result & Output "completed" event │ │ │
|
||||||
|
│ │ │ └─ Send via Channel Layer to WebSocket Group │ │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ └──────────────────────────────────────────────────────────┘ │ │
|
||||||
|
│ └──────────────────────────────────────────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
└──────────────────────┬───────────────────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
│ Channel Layer Broadcast
|
||||||
|
▼
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ REDIS (Message Broker & Cache) │
|
||||||
|
├──────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ • Celery task queue │
|
||||||
|
│ • Channel layer for WebSocket group communication │
|
||||||
|
│ • Session cache (optional) │
|
||||||
|
└──────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
MCP Runtime (HTTP mode)
|
||||||
|
|
||||||
|
- Service: `mcp-agent-server` (container `dynavera-mcp-agent`)
|
||||||
|
- Listens on `0.0.0.0:8001` with `/execute` and `/health` HTTP endpoints
|
||||||
|
- Handles all agent execution: RAG retrieval, LLM inference, context management
|
||||||
|
- Shares code and `build/rag_db` read-only from host
|
||||||
|
- Completely separate from Django/Celery; communicates only via HTTP
|
||||||
|
|
||||||
|
## Execution Flow Sequence
|
||||||
|
|
||||||
|
```
|
||||||
|
Frontend Backend LLM System
|
||||||
|
│ │ │
|
||||||
|
├─ User Input ──────────────>│ │
|
||||||
|
│ (JSON via WebSocket) │ │
|
||||||
|
│ │ │
|
||||||
|
│ ├─ Create Execution │
|
||||||
|
│ │ Record │
|
||||||
|
│ │ │
|
||||||
|
│ ├─ Queue Celery Task │
|
||||||
|
│ │ │
|
||||||
|
│<── execution_started ──────┤ │
|
||||||
|
│ (WebSocket message) │ │
|
||||||
|
│ │ │
|
||||||
|
│ ├─ Output "initializing" │
|
||||||
|
│<── agent_event ────────────┤ │
|
||||||
|
│ (WebSocket) │ │
|
||||||
|
│ │ │
|
||||||
|
│ ├─ Load GPT4All Model │
|
||||||
|
│ │ │
|
||||||
|
│ │─────────────────────────>│ Load Model
|
||||||
|
│ │ (~10-30 seconds) │
|
||||||
|
│ │<───────────────────────── Model Ready
|
||||||
|
│ │ │
|
||||||
|
│ ├─ Output "retrieving" │
|
||||||
|
│<── agent_event ────────────┤ │
|
||||||
|
│ (WebSocket) │ │
|
||||||
|
│ │ │
|
||||||
|
│ ├─ Query RAG DB (if exists) │
|
||||||
|
│ │ (ChromaDB) │
|
||||||
|
│ │ │
|
||||||
|
│ ├─ Output "generating" │
|
||||||
|
│<── agent_event ────────────┤ │
|
||||||
|
│ (WebSocket) │ │
|
||||||
|
│ │ │
|
||||||
|
│ │───────────────────────────>│ Generate
|
||||||
|
│ │ generate(prompt, │ Response
|
||||||
|
│ │ max_tokens=200) │
|
||||||
|
│ │<───────────────────────── Response
|
||||||
|
│ │ (5-30 seconds) │
|
||||||
|
│ │ │
|
||||||
|
│<── execution_completed ────┤ │
|
||||||
|
│ (WebSocket with output) │ │
|
||||||
|
│ │ │
|
||||||
|
└ Display Log & Result │ │
|
||||||
|
```
|
||||||
|
|
||||||
|
## Data Flow: Input to Output
|
||||||
|
|
||||||
|
```
|
||||||
|
User Enters JSON
|
||||||
|
↓
|
||||||
|
{"query": "What is fNIRS?"}
|
||||||
|
↓
|
||||||
|
Frontend sends via WebSocket
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────┐
|
||||||
|
│ AgentConsumer.receive(text_data) │
|
||||||
|
└──────────────┬──────────────────────┘
|
||||||
|
│
|
||||||
|
├─ Parse JSON
|
||||||
|
├─ Validate action
|
||||||
|
└─ Route to handler
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────┐
|
||||||
|
│ handle_start_agent() │
|
||||||
|
├─────────────────────────────────────┤
|
||||||
|
│ • Get agent from DB │
|
||||||
|
│ • Create AgentExecution │
|
||||||
|
│ • Queue Celery task │
|
||||||
|
└──────────────┬──────────────────────┘
|
||||||
|
│
|
||||||
|
├─ Send execution_started event
|
||||||
|
│ (back to WebSocket)
|
||||||
|
│
|
||||||
|
├─ Queue in Celery/Redis
|
||||||
|
│
|
||||||
|
┌──────────────┴──────────────────────┐
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
Celery Worker Database Updated
|
||||||
|
│ │
|
||||||
|
├─ Fetch execution │
|
||||||
|
├─ Initialize models │
|
||||||
|
├─ Send progress events │
|
||||||
|
│ │
|
||||||
|
├─ Query RAG (if available) │
|
||||||
|
│ ├─ Load embedder │
|
||||||
|
│ ├─ Connect to ChromaDB │
|
||||||
|
│ └─ Query for context │
|
||||||
|
│ │
|
||||||
|
├─ Initialize LLM │
|
||||||
|
│ ├─ Load GPT4All model │
|
||||||
|
│ └─ Prepare prompt │
|
||||||
|
│ │
|
||||||
|
├─ Generate response │
|
||||||
|
│ └─ model.generate() │
|
||||||
|
│ │
|
||||||
|
├─ Create result dict │
|
||||||
|
│ │
|
||||||
|
├─ Save to AgentExecution │
|
||||||
|
│ ├─ output_data │
|
||||||
|
│ ├─ status = 'completed' │
|
||||||
|
│ └─ completed_at │
|
||||||
|
│ │
|
||||||
|
└─ Send via Channel Layer
|
||||||
|
to WebSocket Group
|
||||||
|
│
|
||||||
|
├─ event_type: agent_event
|
||||||
|
├─ event_type: agent_completed
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Frontend receives
|
||||||
|
│
|
||||||
|
├─ Update agentStore
|
||||||
|
├─ Push to eventLog
|
||||||
|
├─ Display in UI
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
User sees result
|
||||||
|
```
|
||||||
|
|
||||||
|
## Component Interaction
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ FRONTEND STATE MANAGEMENT │
|
||||||
|
├─────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ agentStore (Pinia) │
|
||||||
|
│ ├─ socket: WebSocket connection │
|
||||||
|
│ ├─ isConnected: boolean │
|
||||||
|
│ ├─ agentId: UUID │
|
||||||
|
│ ├─ currentExecutionId: UUID │
|
||||||
|
│ ├─ executionStatus: 'idle'|'running'|'completed' │
|
||||||
|
│ ├─ events: Array<AgentEvent> │
|
||||||
|
│ │ │
|
||||||
|
│ ├─ connect(agentId) │
|
||||||
|
│ ├─ startAgent(inputData) │
|
||||||
|
│ ├─ stopAgent() │
|
||||||
|
│ ├─ disconnect() │
|
||||||
|
│ └─ handleMessage(data) │
|
||||||
|
│ │
|
||||||
|
│ AgentDetail.vue (Uses Store) │
|
||||||
|
│ ├─ Subscribes to: │
|
||||||
|
│ │ ├─ agentStore.isConnected │
|
||||||
|
│ │ ├─ agentStore.executionStatus │
|
||||||
|
│ │ └─ agentStore.eventLog │
|
||||||
|
│ │ │
|
||||||
|
│ └─ Calls: │
|
||||||
|
│ ├─ agentStore.connect() on mount │
|
||||||
|
│ ├─ agentStore.startAgent() on button click │
|
||||||
|
│ ├─ agentStore.disconnect() on unmount │
|
||||||
|
│ └─ agentStore.stopAgent() on stop button │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Message Type Mapping
|
||||||
|
|
||||||
|
```
|
||||||
|
WebSocket Message Type → Handler Function → Event Display
|
||||||
|
|
||||||
|
"execution_started" → handleMessage → "Started" tag + message
|
||||||
|
"agent_event" → handleMessage → Event type specific
|
||||||
|
├─ "progress" → Display stage → [PROGRESS] stage: message
|
||||||
|
├─ "message" → Display text → [MESSAGE] content
|
||||||
|
└─ "step" → Display step → [STEP] content
|
||||||
|
|
||||||
|
"execution_completed" → handleMessage → "Completed" tag + output
|
||||||
|
"execution_error" → handleMessage → "Error" tag + message
|
||||||
|
"execution_stopped" → handleMessage → "Stopped" tag + message
|
||||||
|
"error" → handleMessage → "Error" tag + message
|
||||||
|
"connection" → handleMessage → Console log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database Schema Relationships
|
||||||
|
|
||||||
|
```
|
||||||
|
User (from auth)
|
||||||
|
│
|
||||||
|
├─────── (1:N) ─────────> Agent
|
||||||
|
│ ├─ uuid (PK)
|
||||||
|
│ ├─ name
|
||||||
|
│ ├─ description
|
||||||
|
│ ├─ status
|
||||||
|
│ ├─ created_at
|
||||||
|
│ └─ updated_at
|
||||||
|
│ │
|
||||||
|
│ ├─────── (1:N) ──────────> AgentExecution
|
||||||
|
│ ├─ uuid (PK)
|
||||||
|
│ ├─ status
|
||||||
|
│ ├─ input_data (JSON)
|
||||||
|
│ ├─ output_data (JSON)
|
||||||
|
│ ├─ error_message
|
||||||
|
│ ├─ created_at
|
||||||
|
│ ├─ started_at
|
||||||
|
│ ├─ completed_at
|
||||||
|
│ │ │
|
||||||
|
│ │ ├─ (1:N) ──> AgentEvent
|
||||||
|
│ │ ├─ uuid (PK)
|
||||||
|
│ │ ├─ event_type
|
||||||
|
│ │ ├─ content (JSON)
|
||||||
|
│ │ └─ timestamp
|
||||||
|
│ │
|
||||||
|
│ └─ user_id (FK)
|
||||||
|
│ │
|
||||||
|
└──────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
@ -35,6 +35,10 @@ The main objectives of this project are:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
See [ARCHITECTURE.md](./ARCHITECTURE.md) for a detailed system overview, component interaction, execution flow, and data flow diagrams.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Automated onboarding workflow for new hires.
|
- Automated onboarding workflow for new hires.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue