A production-ready multi-agent AI system powered by Claude Sonnet.
Ask any business question — the system routes it through a pipeline of specialised AI agents and returns a professional stakeholder report.
┌─────────────────────────────────────────────────────────────┐
│ User (HTTP Client) │
│ POST /api/query/stream (SSE) │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ FastAPI Backend │
│ Streaming via Server-Sent Events │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ LangGraph State Graph │
│ AgentState flows through nodes sequentially │
└──────┬───────────┬───────────┬──────────────┬──────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Manager │→│Research │→│Analysis │→│ Report │
│ Agent │ │ Agent │ │ Agent │ │ Agent │
│ │ │ │ │ │ │ │
│ Routes │ │Gathers │ │Extracts │ │Formats │
│question │ │ facts │ │insights │ │ report │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
│ │ │ │
└───────────┴───────────┴──────────────┘
│
▼
┌─────────────────────┐
│ Stakeholder Report │
│ (Markdown via SSE) │
└─────────────────────┘
| Agent | Role | Output |
|---|---|---|
| 🧠 Manager | Understands the question, creates a routing plan | JSON routing plan |
| 🔍 Research | Reads documents + applies Claude's knowledge | Markdown findings |
| 📊 Analysis | Extracts insights, trends, risks, recommendations | Structured JSON |
| 📝 Report | Formats everything for a non-technical stakeholder | Markdown report |
- Multi-agent orchestration via LangGraph
StateGraph - Real-time streaming using Server-Sent Events (SSE)
- Document ingestion — drop PDF or TXT files into
data/sample_docs/for the Research Agent to read - Structured analysis — JSON output with insights, trends, risks, KPIs, and prioritised recommendations
- Two API modes — blocking (
/api/query) and streaming (/api/query/stream) - Azure-ready — multi-stage Dockerfile with health check and non-root user
- Interactive API docs at
/docs(Swagger UI)
- Python 3.11+
- An Anthropic API key
git clone https://github.com/YOUR_USERNAME/ai-operations-assistant.git
cd ai-operations-assistant
python -m venv .venv
# Windows:
.venv\Scripts\activate
# macOS / Linux:
source .venv/bin/activate
pip install -r requirements.txtcp .env.example .envOpen .env and set your API key:
ANTHROPIC_API_KEY=sk-ant-...your-key-here...
CLAUDE_MODEL=claude-sonnet-4-5uvicorn backend.main:app --reloadOpen http://localhost:8000/docs — you'll see the full interactive API documentation.
{
"status": "ok",
"model": "claude-sonnet-4-5",
"version": "1.0.0"
}Runs the full pipeline and returns a complete JSON response.
Request:
{
"question": "What are the main risks in our Q3 business performance?",
"context": "We are a mid-size SaaS company."
}Response:
{
"question": "...",
"routing_plan": { "understanding": "...", "research_focus": "...", ... },
"research_findings": "## Key Findings\n...",
"analysis_results": {
"executive_summary": "...",
"key_insights": [...],
"risks": [...],
"recommendations": [...]
},
"final_report": "# Q3 Risk Assessment\n...",
"current_step": "complete",
"errors": []
}Returns a Server-Sent Events stream. Listen for these event types:
| Event | When | Data |
|---|---|---|
pipeline_start |
Pipeline begins | { question, agents, message } |
agent_start |
Agent about to run | { agent, label, message } |
agent_complete |
Agent finished | { agent, label, summary, errors } |
pipeline_complete |
All done | { final_report, routing_plan, errors } |
error |
Something failed | { message } |
JavaScript example:
const response = await fetch('http://localhost:8000/api/query/stream', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
question: 'What are the main risks in our Q3 business performance?'
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).split('\n');
for (const line of lines) {
if (line.startsWith('data:')) {
const data = JSON.parse(line.slice(5));
if (data.type === 'pipeline_complete') {
console.log('Final Report:', data.final_report);
}
}
}
}cURL example:
curl -X POST http://localhost:8000/api/query/stream \
-H "Content-Type: application/json" \
-d '{"question": "What are the key risks in Q3 performance?"}' \
--no-bufferai-operations-assistant/
│
├── backend/
│ ├── __init__.py
│ ├── main.py # FastAPI app + SSE streaming
│ ├── graph.py # LangGraph StateGraph definition
│ ├── config.py # Configuration & validation
│ ├── schemas.py # Pydantic request/response models
│ └── agents/
│ ├── __init__.py
│ ├── manager.py # 🧠 Orchestrator agent
│ ├── research.py # 🔍 Research sub-agent
│ ├── analysis.py # 📊 Analysis sub-agent
│ └── report.py # 📝 Report sub-agent
│
├── data/
│ └── sample_docs/ # Drop PDFs or TXT files here for Research Agent
│ └── q3_business_report.txt
│
├── .env.example # Copy to .env and add your API key
├── .gitignore
├── Dockerfile # Azure-ready multi-stage build
├── requirements.txt
└── README.md
# Health check
curl http://localhost:8000/health
# Blocking query (uses the included sample document)
curl -X POST http://localhost:8000/api/query \
-H "Content-Type: application/json" \
-d '{"question": "What are the main risks in Q3 performance and what should we do about them?"}'
# Streaming query
curl -X POST http://localhost:8000/api/query/stream \
-H "Content-Type: application/json" \
-d '{"question": "Summarise the Q3 revenue performance and key trends."}' \
--no-bufferTry these sample questions with the included q3_business_report.txt:
- "What are the top 3 risks we need to address immediately?"
- "Why is customer churn increasing and what should we do?"
- "Summarise Q3 revenue performance for the board."
- "What is our competitive position against Orion Analytics?"
# 1. Login
az login
# 2. Create resource group
az group create --name rg-ai-operations --location eastus
# 3. Create Container Registry
az acr create --resource-group rg-ai-operations \
--name aiopassistantacr --sku Basic
# 4. Build & push image
az acr build --registry aiopassistantacr \
--image ai-operations-assistant:latest .
# 5. Create Container Apps environment
az containerapp env create \
--name ai-ops-env \
--resource-group rg-ai-operations \
--location eastus
# 6. Deploy
az containerapp create \
--name ai-operations-assistant \
--resource-group rg-ai-operations \
--environment ai-ops-env \
--image aiopassistantacr.azurecr.io/ai-operations-assistant:latest \
--target-port 8000 \
--ingress external \
--registry-server aiopassistantacr.azurecr.io \
--secrets anthropic-key=YOUR_ANTHROPIC_API_KEY \
--env-vars ANTHROPIC_API_KEY=secretref:anthropic-key \
CLAUDE_MODEL=claude-sonnet-4-5 \
--cpu 1 --memory 2Gi \
--min-replicas 1 --max-replicas 3# Build the image locally
docker build -t ai-operations-assistant .
# Run locally to verify
docker run -p 8000:8000 \
-e ANTHROPIC_API_KEY=your_key_here \
ai-operations-assistant
# Deploy to App Service
az webapp create \
--resource-group rg-ai-operations \
--plan ai-ops-plan \
--name ai-operations-assistant \
--deployment-container-image-name ai-operations-assistant:latest
az webapp config appsettings set \
--resource-group rg-ai-operations \
--name ai-operations-assistant \
--settings ANTHROPIC_API_KEY=your_key_here CLAUDE_MODEL=claude-sonnet-4-5- ChromaDB memory — persistent vector store for long-term document search
- Tavily web search — live internet research for the Research Agent
- Reflection loop — Manager reviews Report quality and re-delegates if needed
- Next.js frontend — live agent activity panel with streaming UI
- Document upload API — drag-and-drop PDF ingestion
- Conversation history — multi-turn business conversations
MIT — feel free to use, modify, and deploy.
Built with FastAPI · LangGraph · Anthropic Claude