| ⚡ Resolution Time | 🔁 Self-Correction | 🧪 Test Coverage | 🚀 Deployment |
|---|---|---|---|
| 45–90 min → <60s | Up to 3 retries | 70% covered | AWS Lambda · API Gateway |
An enterprise-grade, production-deployed Agentic RAG system built with LangGraph, GPT-4o, and AWS that autonomously investigates network alarms, retrieves vendor SOPs, drafts incident resolution tickets, and self-evaluates for safety compliance — deployed as a serverless microservice on AWS Lambda and publicly accessible via API Gateway.
The agent is deployed and running on AWS. You can trigger it right now — no setup required:
curl.exe -X POST https://yjhndtxwxh.execute-api.us-east-1.amazonaws.com/alarm -H "Content-Type: application/json" -d '{"alarm_id": "ALARM-001", "error_message": ""}'Try all four alarm scenarios:
alarm_id |
Device | Fault Type | Severity |
|---|---|---|---|
ALARM-001 |
Arris E6000 CMTS | DOCSIS T3 Timeout — 347 modems affected | CRITICAL |
ALARM-002 |
Nokia 7360 ISAM FX OLT | GPON ONU Rx Power Degradation | MAJOR |
ALARM-003 |
Cisco ASR9001 Core Router | BGP Session Flap — 14 flaps/hour | CRITICAL |
ALARM-004 |
Juniper MX480 Edge Router | Interface Queue Congestion — 98.7% util | MAJOR |
Expected response (~20–40s on cold start, ~5s warm):
{
"alarm_id": "ALARM-001",
"is_safe": true,
"safety_feedback": "The proposed resolution ticket is SAFE. All steps are directly traceable to the SOPs...",
"resolution_ticket": "INCIDENT RESOLUTION TICKET\n==========================\n...",
"iterations": 1,
"elapsed_seconds": 19.38
}In modern Telecom Network Operations Centers, L3 engineers spend an average of 45–90 minutes per critical alarm manually:
- Correlating live telemetry from NMS dashboards
- Searching through hundreds of pages of vendor manuals
- Drafting step-by-step resolution procedures
- Getting peer review for safety compliance
This agent compresses that entire workflow to under 60 seconds, with built-in SOP compliance enforcement — reducing Mean Time to Resolution (MTTR), minimizing human error, and freeing senior engineers for complex escalations.
The agent runs as a 4-node LangGraph state machine deployed on AWS Lambda, resolving NOC alarms in under 60 seconds with a built-in self-correction loop.
flowchart TD
A([🌐 API Gateway\nHTTP POST /alarm]) --> B
B[λ AWS Lambda\nPython 3.12 · 1GB RAM]
B --> C
subgraph GRAPH [LangGraph State Machine]
direction TB
C[🔍 check_network\nFetch alarm telemetry\nfrom DynamoDB]
C --> D
D[📚 get_manuals\nRAG retrieval · cosine similarity\nOpenAI text-embedding-3-small]
D --> E
E[✍️ draft_fix\nGenerate resolution ticket\nGPT-4o · temp=0.1]
E --> F
F{🛡️ safety_check\nCritic audit\nGPT-4o · temp=0.0}
end
F -->|✅ Safe| G([📋 Resolution Ticket\nreturned to caller])
F -->|❌ Unsafe · iter < 3\nfeedback injected| D
F -->|❌ Max 3 iterations\nexit gracefully| G
subgraph AWS [AWS Infrastructure]
H[(DynamoDB\nSOPs Table)]
I[(DynamoDB\nTelemetry Table)]
end
C --- I
D --- H
style GRAPH fill:#1a1a2e,stroke:#4a9eff,color:#fff
style AWS fill:#1a2e1a,stroke:#4aff9e,color:#fff
style F fill:#2e1a1a,stroke:#ff4a4a,color:#fff
style G fill:#1a2e1a,stroke:#4aff9e,color:#fff
⚡ Mean time to resolution: 45–90 min → under 60 seconds
┌─────────────────────────────────┐
curl / HTTP client │ AWS API Gateway (HTTP API) │
POST /alarm ───────► │ yjhndtxwxh.execute-api... │
└────────────────┬────────────────┘
│ triggers
▼
┌─────────────────────────────────┐
│ AWS Lambda │
│ telecom-noc-agent │
│ Python 3.12 · 1 GiB · 300s │
│ │
│ ┌──────────────────────────┐ │
│ │ Docker Container (ECR) │ │
│ │ public.ecr.aws/lambda/ │ │
│ │ python:3.12 │ │
│ │ │ │
│ │ lambda_handler.py │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ LangGraph StateGraph │ │
│ │ (4 nodes + critic loop)│ │
│ └──────────────────────────┘ │
└────┬────────────────────┬───────┘
│ │
IAM role │ │ OpenAI API
(no keys) ▼ ▼
┌──────────────────────┐ ┌──────────────────┐
│ AWS DynamoDB │ │ GPT-4o │
│ │ │ text-embedding │
│ telecom-noc-sops │ │ -3-small │
│ (5 SOP documents) │ │ │
│ │ │ Brain: temp=0.1 │
│ telecom-noc- │ │ Critic: temp=0.0 │
│ telemetry │ │ (structured out) │
│ (4 alarm scenarios) │ └──────────────────┘
└──────────────────────┘
- API Gateway receives a
POST /alarmrequest with analarm_idand routes it to Lambda. - Lambda (Docker container from ECR) runs the LangGraph workflow.
- Node 1 queries DynamoDB for live device telemetry (CPU, SNR, error counters, etc.).
- Node 2 fetches all SOPs from DynamoDB, embeds them with
text-embedding-3-small, and returns the top-3 most relevant via numpy cosine similarity — no vector database required. - Node 3 (GPT-4o Brain) synthesizes telemetry + SOPs into a structured resolution ticket.
- Node 4 (GPT-4o Critic) audits every step for SOP compliance using structured output.
- If the ticket fails the audit, the agent loops back to Node 2 with the critic's feedback for a more targeted SOP retrieval — up to 3 iterations.
- The final approved ticket is returned as JSON to the API caller.
START → check_network → get_manuals → draft_fix → safety_check
▲ │
│ (is_safe=False, │
└─── iterations < 3) ◄───┘
│
(is_safe=True
OR iterations ≥ 3)
│
END
NOC engineers manually spend 45–90 minutes per incident searching vendor documentation and drafting resolution tickets. This agent is designed to compress that entire workflow to under 60 seconds by combining semantic SOP retrieval with a self-auditing critic loop — reducing human error in high-pressure network operations environments.
| Layer | Technology | Notes |
|---|---|---|
| Orchestration | LangGraph ≥0.2.0 | StateGraph with conditional routing |
| LLM | GPT-4o via LangChain | Brain (temp=0.1) + Critic (temp=0.0, structured output) |
| Embeddings | text-embedding-3-small | Cached per Lambda container lifecycle |
| RAG / Vector Search | DynamoDB + numpy cosine similarity | No vector DB — free tier, cloud-native |
| Data Store | AWS DynamoDB | PAY_PER_REQUEST billing — free tier forever |
| Compute | AWS Lambda | 1 GiB RAM, 300s timeout, Docker image |
| Container Registry | AWS ECR | linux/amd64 image, public.ecr.aws base |
| API | AWS API Gateway (HTTP API) | POST /alarm, auto-deploy, CORS enabled |
| Validation | Pydantic v2 | SafetyAuditResult enforces boolean is_safe + feedback |
| Runtime | Python 3.12 | uv for local dependency management |
| Testing | pytest + moto | DynamoDB mocked via moto; OpenAI mocked via unittest.mock |
| Linting / Formatting | Ruff + mypy | Enforced via pre-commit hooks and CI |
| CI | GitHub Actions | 3-stage pipeline: lint → test → docker build |
telecom-noc-agent/
├── src/
│ ├── state.py # NOCAgentState TypedDict — single source of truth
│ ├── tools.py # @tool: query_nms_for_alarm_telemetry
│ ├── retriever.py # DynamoDB SOP loader + numpy cosine similarity RAG
│ ├── nodes.py # 4 LangGraph node functions
│ └── graph.py # StateGraph compilation + conditional routing
├── tests/
│ ├── conftest.py # Shared fixtures: moto DynamoDB, mock OpenAI, sample data
│ ├── test_state.py # NOCAgentState schema validation
│ ├── test_retriever.py # RAG: DynamoDB load + cosine similarity
│ ├── test_nodes.py # Node unit tests (check_network, draft_fix, safety_check)
│ └── test_lambda_handler.py # Lambda handler integration tests
├── data/
│ ├── sops.json # Source of truth for 5 SOP documents (seeds DynamoDB)
│ ├── mock_telemetry.json # Source of truth for 4 alarm scenarios (seeds DynamoDB)
│ └── mock_telemetry.py # DynamoDB telemetry loader with module-level cache
├── scripts/
│ └── seed_dynamodb.py # One-time script: creates DynamoDB tables + uploads data
├── .github/
│ └── workflows/ci.yml # CI pipeline: lint → test → docker build
├── lambda_handler.py # AWS Lambda entry point (graph built per invocation; CORS + 400/500 handling)
├── Dockerfile # Lambda container — public.ecr.aws/lambda/python:3.12
├── pyproject.toml # pytest, ruff, mypy, and coverage configuration
├── .pre-commit-config.yaml # Pre-commit: ruff, mypy, detect-secrets, JSON/YAML checks
├── main.py # CLI entry point (local dev)
├── requirements.txt # Python dependencies (boto3, numpy, langgraph, openai...)
└── .env.example # Environment variable template
| Component | File | Responsibility |
|---|---|---|
| State Schema | src/state.py |
NOCAgentState TypedDict + SafetyAuditResult Pydantic model |
| NMS Tool | src/tools.py |
LangChain @tool wrapper (used by main.py; nodes use boto3 directly) |
| RAG Engine | src/retriever.py |
DynamoDB scan + numpy cosine similarity; retrieve_relevant_sops() is primary API |
| Node 1 | src/nodes.py:check_network |
Fetches live device telemetry via boto3 directly |
| Node 2 | src/nodes.py:get_manuals |
Semantic SOP retrieval; enriches query with safety feedback on retry |
| Node 3 | src/nodes.py:draft_fix |
GPT-4o resolution ticket drafting |
| Node 4 | src/nodes.py:safety_check |
GPT-4o critic with structured Pydantic output; increments iterations on failure |
| Graph | src/graph.py |
LangGraph compilation + MAX_ITERATIONS=3 routing |
| Lambda Handler | lambda_handler.py |
API Gateway body parsing, alarm_id validation (400), CORS headers, 500 on error |
| CLI Runner | main.py |
Local development with 4 pre-built alarm scenarios |
Five realistic SOP documents are stored in the telecom-noc-sops DynamoDB table, embedded on Lambda cold start, and retrieved by cosine similarity at query time:
| SOP ID | Title | Source |
|---|---|---|
| SOP-001 | Arris E6000 CMTS — DOCSIS T3 Timeout Remediation | Arris E6000 Guide v4.2 |
| SOP-002 | Nokia 7360 ISAM FX — GPON ONU Rx Power Low | Nokia 7360 Manual Rev 3.1 |
| SOP-003 | BGP Session Flap — Core Router Runbook | Internal NOC Runbook v2.8 |
| SOP-004 | Interface Queue Congestion — QoS Runbook | Internal NOC Runbook v2.8 |
| SOP-005 | NOC Escalation and Communication Protocol | NOC Operations Policy v5.0 |
pytest # all tests, coverage enforced at 70%
pytest -m unit # unit tests only (no external services)
pytest --no-cov -v # quick run without coverageTests use moto to mock DynamoDB and unittest.mock for OpenAI — no real API calls or AWS credentials needed. Test markers: unit, integration, slow.
ruff check --fix . # lint and auto-fix
ruff format . # format
mypy src/ # type checkpre-commit install # install hooks (one-time)
pre-commit run --all-filesHooks run ruff, ruff-format, mypy, and security scanners (detect-secrets, detect-private-key) on every commit.
GitHub Actions runs three jobs in sequence on every push:
- Lint & Type Check — ruff + mypy
- Unit & Integration Tests — pytest with coverage report (≥70%)
- Docker Build Check — verifies the Lambda container builds successfully
- Python 3.10+
- uv (
pip install uv) - An OpenAI API key with access to
gpt-4oandtext-embedding-3-small - AWS credentials with DynamoDB read access (
aws configure)
git clone https://github.com/DevMLAI01/telecom-noc-agent.git
cd telecom-noc-agent
uv venv && .venv/Scripts/activate # Windows
# or: source .venv/bin/activate # macOS / Linux
uv pip install -r requirements.txtcp .env.example .env
# Edit .env — fill in OPENAI_API_KEY and AWS credentialspython scripts/seed_dynamodb.py
# Creates telecom-noc-sops and telecom-noc-telemetry tables
# and uploads all SOPs and telemetry data from the data/ JSON filespython main.py # ALARM-001 (default)
python main.py --alarm ALARM-002 # Nokia GPON ONU Rx Low
python main.py --alarm ALARM-003 # Cisco ASR9001 BGP Flap
python main.py --alarm ALARM-004 # Juniper MX480 Congestion# Build the Lambda container image (linux/amd64 — required for Lambda)
docker buildx build --platform linux/amd64 --provenance=false \
-t 585707316150.dkr.ecr.us-east-1.amazonaws.com/telecom-noc-agent:latest \
--push .
# Update Lambda to pull the new image
aws lambda update-function-code \
--function-name telecom-noc-agent \
--image-uri 585707316150.dkr.ecr.us-east-1.amazonaws.com/telecom-noc-agent:latest
--provenance=falseis required when building on Docker Desktop for Windows — without it, Docker pushes a multi-arch manifest list that AWS Lambda rejects.
- Add an entry to
data/mock_telemetry.json - Run
python scripts/seed_dynamodb.pyto upload it - Add the scenario to
ALARM_SCENARIOSinmain.py
Replace the DynamoDB loader in data/mock_telemetry.py with an API call:
def get_telemetry_for_alarm(alarm_id: str) -> dict:
response = requests.get(
f"https://your-nms/api/alarms/{alarm_id}",
headers={"Authorization": f"Bearer {os.getenv('NMS_API_KEY')}"}
)
return response.json()- Add entries to
data/sops.json(or load from PDFs withPyPDFLoader) - Re-run
python scripts/seed_dynamodb.py - Redeploy Lambda to clear the in-memory embedding cache
from langgraph.checkpoint.sqlite import SqliteSaver
memory = SqliteSaver.from_conn_string("noc_agent_memory.db")
graph = build_graph().compile(checkpointer=memory)This project is provided for educational and demonstration purposes. For production use, ensure compliance with your organization's AI governance and change management policies.