Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Multi-Agent AI Support Assistant

A production-style FastAPI application using Semantic Kernel that routes customer support requests to specialised AI agents, queries a PostgreSQL (Pagila) database through typed tools, applies guardrails, and returns structured JSON.

Built for the Netsol AI CoE take-home assignment.


Architecture

Request → TriageAgent → Specialist Agent → GuardrailAgent → AgentResponse

Layers (Clean Architecture)

Layer Contents
Presentation app/api/ – FastAPI router, Pydantic validation
Application app/orchestration/, app/services/, app/agents/
Domain app/plugins/, app/repositories/, app/schemas/
Infrastructure app/db/, app/models/, Alembic migrations
Cross-cutting app/logging/, app/middleware/, app/observability/

Agents

Agent Intent Tool
TriageAgent Routes all requests —
CatalogAgent catalog_search search_film_catalog
SubscriptionAgent subscription_question get_customer_streaming_subscription
RentalHistoryAgent rental_history get_customer_rental_history
KnowledgeAgent knowledge_question search_kb
HumanHandoffAgent human_handoff / unsafe_request create_handoff_ticket
GuardrailAgent Post-processes every response —

Quick Start

1. Clone and install

git clone <repo-url>
cd multi-agent-ai-support

cd backend
pip install -e ".[dev]"
cd ..

2. Configure environment

cp backend/.env.example backend/.env
# Edit backend/.env – set OPENAI_API_KEY and, if you want traces, Langfuse credentials

3. Start PostgreSQL with Pagila

The Pagila SQL files are already included under backend/scripts/. Start PostgreSQL with Docker Compose from the project root:

docker compose up db -d

4. Run migrations

cd backend
alembic upgrade head
cd ..

5. Seed streaming data

cd backend
python scripts/seed.py
cd ..

6. Start the API

cd backend
uvicorn app.main:app --reload

API is now available at http://localhost:8000.


API

POST /agent/respond

curl -X POST http://localhost:8000/agent/respond \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": 1,
    "conversation_id": "conv_001",
    "message": "Is Alien available for streaming?"
  }'

Response:

{
  "conversation_id": "conv_001",
  "intent": "catalog_search",
  "selected_agent": "CatalogAgent",
  "answer": "ALIEN | Rating: R | Rental Rate: $4.99 | Streaming: Yes",
  "confidence": 0.95,
  "tools_used": ["CatalogPlugin.search_film_catalog"],
  "citations": [],
  "next_action": "none",
  "guardrail_result": "PASS"
}

MCP Server (pagila-support-mcp)

A local MCP server exposing two DB-backed tools:

  • search_film_catalog
  • get_customer_streaming_subscription
# Install MCP CLI if needed
pip install mcp

# Run the MCP server
cd backend
python mcp_server/server.py

Connect from any MCP client using stdio transport.


Tests

cd backend
pytest tests/ -v
cd ..

Tests cover: routing, plugins, repositories, API, guardrails, and migrations.


Evals

12 evaluation examples are in backend/evals/eval_cases.json, covering all required prompts from the assignment including safety scenarios (prompt injection, SQL injection, account mutation attempts).


Database Setup

The project uses the Pagila PostgreSQL sample database with three custom migrations:

Migration Change
001 ALTER TABLE film ADD COLUMN streaming_available BOOLEAN NOT NULL DEFAULT FALSE
002 Creates streaming_subscription table + seeds one active subscription
003 Creates conversation_message table for persistent conversation memory

Project Structure

backend/app/
  api/            FastAPI router and dependency injection
  agents/         7 specialist agents (TriageAgent, CatalogAgent, …)
  orchestration/  SemanticKernelRouter – triage → specialist → guardrail
  plugins/        5 Semantic Kernel plugin classes (DB-backed)
  prompts/        System prompt per agent
  tools/          MCP metadata + ToolTracker
  repositories/   Async Repository Pattern (SQLAlchemy)
  schemas/        Pydantic v2 request/response/plugin schemas
  models/         SQLAlchemy ORM models
  db/             Engine, session factory, DeclarativeBase
  services/       SupportService (thin application layer)
  middleware/     Request ID, CORS
  logging/        Structured logging (structlog)
  observability/  Langfuse tracing helpers
backend/mcp_server/       pagila-support-mcp (senior signal)
backend/migrations/       Alembic async migrations
backend/docs/
  kb/             Knowledge base markdown files
  design.md       Architecture decisions
  implementation_plan.md  Phased plan
  ai_usage.md     AI tooling disclosure
backend/evals/            12 evaluation examples
backend/tests/            pytest test suite
backend/scripts/          Seed and utility scripts
frontend/                 Streamlit PoC frontend
docs/                     Assignment and architecture documentation

Observability — Langfuse Tracing

The application integrates Langfuse for end-to-end LLM observability.
Tracing is optional — the app runs normally without it (all trace calls fall back to no-ops).

What is traced

Span Type What you see
support_request span Full request — customer ID, intent, agent, guardrail result, tools used
triage_agent generation Triage input context + raw JSON classification output
CatalogAgent / SubscriptionAgent / etc. generation Specialist input message + answer
guardrail_agent generation Guardrail payload + PASS/FAIL result
CatalogPlugin.search_film_catalog span Query + result count + latency
SubscriptionPlugin.get_customer_streaming_subscription span Customer ID + found/not-found
RentalPlugin.get_customer_rental_history span Customer ID + record count
KnowledgePlugin.search_kb span Query + result count + latency
HandoffPlugin.create_handoff_ticket span Ticket ID + reason

Every span includes latency in milliseconds and is nested under the parent support_request trace, giving you a full waterfall view per request in the Langfuse dashboard.

How to enable

  1. Sign up at cloud.langfuse.com (free tier) or self-host using the included langfuse/ Docker Compose.
  2. Create a project and copy the API keys.
  3. Add to backend/.env:
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_BASE_URL=https://cloud.langfuse.com
  1. Restart the API — tracing starts automatically. On shutdown, buffered events are flushed via flush_tracing().

Without Langfuse

Leave the three env vars unset (or comment them out). The app logs a langfuse_disabled info message and continues with full functionality.


Design Notes

See docs/design.md for architecture decisions, tradeoffs, and MCP readiness strategy.


Requirements

  • Python 3.12+
  • PostgreSQL 14+ with Pagila
  • OpenAI API key (GPT-4o-mini or later)

About

Production-style multi-agent AI support assistant built with FastAPI, Semantic Kernel, and PostgreSQL (Pagila). Routes customer support messages to specialist AI agents, applies guardrails, and returns structured JSON. Includes tests, eval examples, Alembic migrations, local KB retrieval, MCP-ready tools, and optional Langfuse tracing

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages