KB-CEC3

GPT Deep Investigation Report 2026-04-03

9 min read Revision 1

GPT Deep Investigation Report — 2026-04-03

Mission: S135H — Tìm nguyên nhân gốc rễ GPT action "chập chờn" Status: CHỈ ĐIỀU TRA, KHÔNG SỬA Investigator: Claude CLI Agent


EXECUTIVE SUMMARY

Nguyên nhân gốc: Agent Data chạy uvicorn SINGLE WORKER (1 process) với /chat endpoint SYNC BLOCKING (gọi OpenAI LLM qua langroid). Khi 1 request /chat block trên OpenAI API call chậm → TOÀN BỘ server đóng băng — bao gồm health check, MCP, và mọi request khác. Đã xảy ra 2 lần trong 72h gần nhất.

Evidence: 31 upstream timeout errors trong nginx error log; container freeze 2h12m (Apr 2 03:26→05:38); zero error trong application logs (process bị freeze không log được).


1. NGINX ACCESS LOGS — GPT Requests (72h)

GPT Request Summary

  • Tổng ChatGPT-User requests: 56
  • HTTP 200: 56/56 (100%)
  • HTTP 4xx/5xx: 0
  • Endpoints GPT dùng:
    • POST /api/chat — main search/RAG (most frequent)
    • GET /api/health — validation
    • GET /api/kb/get/{doc_id} — document retrieval
    • POST /api/documents/batch — batch read
    • POST /api/documents?upsert=true — document upsert
    • GET /api/documents/{doc_id} — single doc read
  • GPT KHÔNG dùng /api/search (endpoint không tồn tại, trả 404)

GPT Request Timeline (raw)

01/Apr 03:56-04:16 — 15 requests, all 200
01/Apr 13:59-14:34 — 12 requests, all 200
02/Apr 08:25-08:41 — 8 requests, all 200
03/Apr 06:31-09:15 — 21 requests, all 200

Nhận xét: 100% GPT requests thành công. NHƯNG không có GPT request nào trong window outage (03:30-05:38 Apr 2). Nếu GPT gọi trong window đó → chắc chắn fail.


2. NGINX ERROR LOGS — SMOKING GUN

31 upstream timeout errors trong 72h:

Incident 1 — Apr 1, 22:42-22:47 (5 phút):

2026/04/01 22:42:41 [error] upstream timed out — POST /api/mcp
2026/04/01 22:45:01 [error] upstream timed out — POST /api/mcp
2026/04/01 22:47:35 [error] upstream timed out — POST /api/mcp

3 MCP timeouts. Internal probes vẫn OK → event loop bị block bởi sync operation, background thread probes vẫn chạy.

Incident 2 — Apr 2, 03:31-05:36 (2 tiếng 5 phút) — CRITICAL:

2026/04/02 03:31:42 [error] upstream timed out — POST /api/mcp
2026/04/02 03:32:22 [error] upstream timed out — GET /api/health
... (28 more errors, every ~6 min) ...
2026/04/02 05:36:54 [error] upstream timed out — GET /api/health

Last application log before freeze: 2026-04-02 03:26:22 - Qdrant probe OK Next application log: 2026-04-02 05:38:19 - WARNING - REDIS_PASSWORD (container restart) Gap: 2 tiếng 12 phút — TOÀN BỘ process đóng băng, kể cả background probe threads.

Container restart at: 2026-04-02T05:37:59.840Z


3. APPLICATION LOGS

Trong 24h gần nhất (sau restart):

  • Zero errors — chỉ có INFO health probes
  • Qdrant probe: 7-47ms (healthy)
  • PostgreSQL probe: 0-5ms (healthy)
  • Tất cả HTTP requests: 200 OK
  • Không có OpenAI/embedding errors
  • Không có rate limit (429) errors

Trước khi freeze (Apr 2):

  • Probes bình thường đến 03:26:22
  • Sau đó → im lặng hoàn toàn → process freeze
  • Không có error/exception nào được log → process bị kill hoặc deadlock trước khi kịp log

4. ENDPOINT LATENCY TEST

10 rapid /api/chat requests từ local machine (qua internet):

Test 1:  HTTP 200 — 2.010s
Test 2:  HTTP 200 — 1.220s
Test 3:  HTTP 200 — 4.374s  ← spike
Test 4:  HTTP 200 — 1.205s
Test 5:  HTTP 200 — 1.400s
Test 6:  HTTP 200 — 1.166s
Test 7:  HTTP 200 — 1.341s
Test 8:  HTTP 200 — 1.134s
Test 9:  HTTP 200 — 1.192s
Test 10: HTTP 200 — 1.211s

Average: 1.625s | Max: 4.374s | Min: 1.134s 10/10 thành công — server hiện tại healthy.

NHƯNG: Test 3 spike 4.4s. Với single worker, trong 4.4s đó, mọi request khác phải CHỜ. GPT Actions timeout ~30s → bình thường OK, nhưng nếu OpenAI API chậm (>30s) → GPT timeout.


5. MCP vs REST CODE PATH COMPARISON

Architecture:

GPT Actions → nginx → /api/chat → server.py:query_knowledge() [SYNC]
                                    ↓
                          _retrieve_query_context() → Qdrant vector search
                                    ↓
                          agent.llm_response() → OpenAI API (embedding + completion) [BLOCKS]

MCP (Claude) → mcp_server/stdio_server.py → _request_with_fallback()
                                              ↓
                                    HTTP POST /chat → same server.py
                                              ↓
                                    FALLBACK: local → cloud endpoint

Key Differences:

Aspect REST (GPT) MCP (Claude/Gemini)
Timeout Unlimited (sync blocking) 30s timeout
Fallback None Local → Cloud endpoint
Workers 1 (single process!) N/A (client-side)
Blocking agent.llm_response() blocks event loop Client times out and retries
Error handling Exception caught, logged Connection error → try cloud

ROOT CAUSE Analysis:

File: agent_data/server.py:787

@app.post("/chat", ...)
def query_knowledge(payload):  # ← SYNC def, not async
    ...
    agent_reply = agent.llm_response("!" + llm_input)  # Line 888 — BLOCKS

Comment in code (line 791-792):

"This is a sync endpoint (not async) because langroid internally uses asyncio.run() which conflicts with FastAPI's async event loop."

Dockerfile CMD:

CMD ["bash", "-lc", "uvicorn agent_data.server:app --host 0.0.0.0 --port ${PORT:-8080}"]

NO --workers flag → defaults to 1 worker.

VPS confirms single process:

PID 3511834 — /usr/local/bin/python /usr/local/bin/uvicorn agent_data.server:app --host 0.0.0.0 --port 8000

6. NGINX CONFIG

proxy_read_timeout 300s;  (for both /api/(chat|kb/list|kb/get|ingest) and general /api/)
keepalive_timeout 65;

→ Nginx timeout 300s — đủ rộng, KHÔNG phải bottleneck.


7. CONTAINER CONFIGURATION

agent-data:
  mem_limit: 1536m  # 1.5GB
  restart: unless-stopped
  healthcheck:
    test: python -c 'urllib.request.urlopen("http://localhost:8000/info")'
    interval: 15s
    timeout: 10s
    retries: 10

Current usage: 521.3MB / 1.5GB (33.94%) VPS total: 11GB RAM, 5.9GB free


8. KẾT LUẬN — NGUYÊN NHÂN GỐC

Nguyên nhân #1 (CHÍNH): Single Worker + Sync Blocking

  • Uvicorn chạy 1 worker duy nhất
  • /chat endpoint là sync (không async) vì langroid dùng asyncio.run() nội bộ
  • agent.llm_response() (line 888) gọi OpenAI API → block toàn bộ event loop
  • Khi 1 request chậm → MỌI request khác phải chờ → GPT timeout

Nguyên nhân #2 (CRITICAL): Process Freeze / OOM

  • Apr 2: Process hoàn toàn đóng băng 2h12m
  • Không có error log → process bị kill hoặc deadlock ở level thấp hơn (memory, GIL)
  • Container memory limit 1.5GB — có thể bị OOM khi langroid/OpenAI xử lý large documents
  • Container restart giải quyết tạm, nhưng CHƯA fix gốc

Nguyên nhân #3: MCP có fallback, REST không

  • MCP client có: local → cloud fallback + 30s timeout
  • REST/GPT không có cơ chế nào — single point of failure
  • Đây là lý do MCP "ổn hơn" GPT Actions

Tại sao GPT logs 100% success?

  • GPT request chỉ đến khi user dùng → ban ngày VN (UTC+7)
  • Outage xảy ra 03:30-05:38 UTC (10:30-12:38 VN) — không có GPT request nào
  • Khi server đang healthy, latency 1-4s → dưới GPT 30s timeout → OK
  • "Chập chờn" xảy ra khi: (a) slow OpenAI call block worker, hoặc (b) process freeze

9. KHUYẾN NGHỊ (KHÔNG THỰC HIỆN — chỉ ghi nhận)

  1. Tăng uvicorn workers--workers 2 hoặc --workers 3 (trong giới hạn 1.5GB RAM)
  2. Hoặc chuyển sang gunicorn + uvicorn workers — process manager tự restart worker bị freeze
  3. Thêm request timeout — timeout từng request /chat (vd 25s) để không block mãi
  4. Monitor memory — log memory usage, alert khi >80% limit
  5. Health check chặt hơn — health check nên gọi qua HTTP (giống nginx) thay vì urllib internal

Report date: 2026-04-03 09:35 UTC Container uptime: 28 hours (healthy since Apr 2 05:38) Next risk window: Bất kỳ lúc nào có concurrent requests hoặc slow OpenAI API call