think
16px
820px

Integration prompt — ai-ahu-chatbot (filled, gateway live at http://192.168.83.20:8200)

We are introducing a central GPU/LLM gateway (ahu-gpu-manager) that all model traffic must flow through. It is already deployed and verified at http://192.168.83.20:8200 (OpenAI-compatible /v1/*, synthesis route at /synthesis/v1/*, priority queueing, audit events). Canonical contract: ../ahu-gpu-manager/docs/CONVENTIONS.md — read it first; on any conflict it wins. Your job is to prepare this repo for it. Hard constraint: every change must be backwards-compatible and dormant — with no new env vars set, behavior must be byte-for-byte identical to today. Do not flip any live env values in infra/env/*.env; only add commented-out entries showing the future values.

1. Header propagation in the Agno agents

In apps/internal-agent/dash/agents.py and its mirror apps/public-agent/dash/agents.py, the models built by _resolve_model() / _build_model_from_slot() (via OpenAILike) currently send no identifying headers — only the orchestrator's direct calls do. Add default headers to the model construction:

  • X-Tenant-Id: ahu-chatbot
  • X-Surface: from the existing SURFACE env (internal | public)
  • X-Priority: interactive for both the tool-loop model and the synthesis model (the gateway maps legacy planning/synthesis values to interactive anyway; use interactive directly)

If Agno supports per-run extra headers, also propagate the per-run user_id as X-User-Id; if it only supports client-level headers, add the static ones and leave a # TODO(gateway) noting the per-run limitation. Verify against the installed agno==2.4.7 API — do not guess.

2. Close the bare-OpenAI egress

apps/internal-agent/app/api/knowledge.py:421 (and the public-agent mirror if present) constructs a bare OpenAI() client calling model="gpt-4o" — this bypasses MODEL_GATEWAY_URL and hits api.openai.com directly. Change it to construct the client from the same gateway-resolution logic the agents use (base_url from MODEL_GATEWAY_URL + /v1 when set, model name from a new env KNOWLEDGE_LLM_MODEL defaulting to the current gpt-4o). When MODEL_GATEWAY_URL is unset, behavior must be unchanged.

3. Queue-awareness in the orchestrator LLM client

In apps/public-web/src/lib/orchestrator/llm/client.ts:

  • On 429 or 503 responses, read Retry-After and X-Queue-Depth headers and include them in the thrown error object so callers can degrade with a friendly "sistem sedang sibuk" message instead of a generic failure.
  • Add opt-in structured queue events: when a new env LLM_QUEUE_EVENTS=on is set, send header X-Queue-Events: on on streaming requests and parse SSE frames of the form event: queue / data: {"position":N,"eta_ms":M} that may arrive before the first chat chunk. Surface them via a callback so orchestrate.ts can forward a status event to the browser stream (reuse the existing SSE status/error event channel) — the user should see "Antrian ke-N (±Xs)" rather than a spinner. Also handle event: error frames (data: {"status":..., "code":...}) that the gateway may emit after an early-committed stream if the upstream fails. Unknown SSE event types must be ignored gracefully.
  • Send an Idempotency-Key header on each request, derived from the existing per-request/session identifiers (deterministic — never random-per-attempt).

4. Env preparation (commented, not active)

In infra/env/internal.env, infra/env/public.env, infra/env/shared.env, add commented blocks:

# --- ahu-gpu-manager gateway (uncomment to flip; revert = re-comment + redeploy) ---
# MODEL_GATEWAY_URL=http://192.168.83.20:8200
# SYNTHESIS_GATEWAY_URL=http://192.168.83.20:8200/synthesis
# EMBEDDER_BASE_URL=http://192.168.83.20:8200/v1
# LLM_QUEUE_EVENTS=on

Note in a comment that once flipped, SYNTHESIS_API_KEY is no longer needed by this repo (the gateway holds the DashScope key server-side and its registry refuses external upstreams in prod) and should be removed from these env files.

Model names: keep sending the canonical names (Qwen/Qwen3.6-35B-A3B-FP8, qwen3.5-397b-a17b, Qwen/Qwen3-Embedding-4B) — the gateway routes by model name but forwards request bodies verbatim, so aliases the upstream doesn't recognize will 404 at the model server.

5. Verification

  • Run the existing test suites; nothing may regress.
  • With no new envs set, confirm (by reading the constructed clients or a local smoke run) that request URLs, headers minus the new static X- headers, and bodies are unchanged against the current vLLM endpoint.
  • Optional live check (safe, additive): with the new envs exported in a local shell only, one chat turn through http://192.168.83.20:8200 — the gateway is live and its /healthz should show your call in gateway_requests_total{tenant="ahu-chatbot"} on /metrics.
  • Type-check and lint clean.

Report back: files changed, any Agno API limitations found for per-run headers, and anything in the header/queue-event contract that needed interpretation.