Lewati ke isi

External Integrations

Purpose

Reference table of every external service HUPH talks to: purpose, env vars, and gotchas. Use this as the first stop when debugging an integration issue or when adding a new one.

Prerequisites

Integration matrix

Integration Purpose Env vars Status Gotchas
360dialog WhatsApp Business API — webhook receiver + outbound send D360_API_KEY, D360_WEBHOOK_SECRET, D360_API_BASE_URL Active — only channel Current tier does NOT expose App Secret for HMAC webhook signing; D360_WEBHOOK_SECRET is for hub.verify_token one-time subscription bootstrap only
Telegram Bot API Telegram channel TELEGRAM_BOT_TOKEN DELETED Apr 8 2026 Code removed from apps/api/src/routes/telegram.ts; do not reintroduce without product approval
Anthropic API (Claude Haiku) LLM used by apps/api for intent router Layer 3 fallback + eval judging + by Dify for chat generation ANTHROPIC_API_KEY, ANTHROPIC_MODEL Active Direct API, NOT AWS Bedrock. Model ID: claude-haiku-4-5 (no date suffix) to match Phase 1 fallback. Dify's workflow references the same model
Dify (self-hosted) Primary AI platform — chat completion (/v1/chat-messages), annotation reply (/v1/apps/annotations), KB management (/v1/datasets/*), workflow orchestration DIFY_API_URL, DIFY_APP_API_KEY, DIFY_KB_API_URL, DIFY_KB_API_KEY, DIFY_DATASET_ID, DIFY_INTENT_DATASET_ID Active (primary AI layer since early Apr 2026) FAQ annotations match in ~300ms (bypasses LLM). Stack = ~8 containers. OOM'd on Apr 8 when dify-beat hit 256m during flask upgrade-db — memory limits bumped. Lives in docker-compose.dify.yml, separate from main compose
OpenAI (embeddings) Dify uses OpenAI's embedding API when ingesting + querying KB documents OPENAI_API_KEY Active (via Dify) apps/api does NOT call OpenAI directly — only the Dify stack does. Key is threaded through docker-compose.dify.yml env
Milvus Vector DB used by Dify KB (Dify-internal URL) Active — primary vector DB Brought up via docker-compose.milvus.yml, separate from main compose. Not accessed directly by apps/api — all retrieval goes through Dify's /v1/datasets/* API
Qdrant Formerly the vector DB REMOVED late Mar / early Apr 2026 docker-compose.yml line 33 explicitly comments "Qdrant removed — replaced by Milvus". qdrant_data volume kept as 30-day backup per line 102. Do NOT try to reintroduce
Postgres Primary DB (conversations, leads, notifications, admin_users, clusters, audit_log) DATABASE_URL, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT Active Host port 5433 (container 5432)
Valkey (Redis-compatible) Session cache, short-lived state REDIS_URL Active Host port 49379 (container 6379). Service name huph-valkey. Valkey is API-compatible with Redis — same clients work. Shared across val.id infra via huph_huph-infra external network
Phoenix OpenTelemetry trace collection from apps/api port 6006 (internal) Active Local dev only; no prod auth currently
Langfuse LLM observability (prompts, latencies, cost) LANGFUSE_URL, LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY Active ClickHouse backend had self-OOM loop fixed Apr 8 (see operations/clickhouse-oom.en.md). Dify tracing integration blocked by missing Langfuse SDK in Dify 1.13.3 — verify current Dify version
mem0 (optional) Per-user long-term memory MEM0_PG_URL, MEM0_NEO4J_URL, MEM0_NEO4J_USER, MEM0_NEO4J_PASSWORD Active (if enabled) Brought up via docker-compose.mem0.yml. Neo4j backend holds PII — must use dedicated HUPH instance, never share (per feedback_dedicated_infra memory)
Neo4j (mem0 backend) Graph DB for mem0 memory same as mem0 env vars Active (when mem0 enabled) Port 48687 bolt / 48474 http in local dev (see CREDENTIALS.md)
UPH Admission API (Laravel) Legacy student data enrichment — cross-reference to one.uph.edu UPH_API_URL, UPH_API_KEY Deferred Integration deferred per project_laravel_enrichment_deferred memory. Do NOT auto-suggest as next candidate
Midtrans Payment gateway for form purchases MIDTRANS_CLIENT_KEY, MIDTRANS_SERVER_KEY Deferred Not yet integrated. Waiting on product decision

Key environment variable reference

# Anthropic (used by apps/api + Dify)
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-haiku-4-5-20251001

# OpenAI (embeddings — used by Dify, passed through from root .env)
OPENAI_API_KEY=sk-...

# 360dialog WhatsApp
D360_API_KEY=...
D360_WEBHOOK_SECRET=...
D360_API_BASE_URL=https://waba-v2.360dialog.io

# Dify (primary AI layer)
DIFY_API_URL=http://huph-dify-api:5001          # internal URL
DIFY_APP_API_KEY=...                             # chat-messages app token
DIFY_KB_API_URL=http://huph-dify-api:5001
DIFY_KB_API_KEY=...                              # KB management token
DIFY_DATASET_ID=<uuid>                           # main KB dataset
DIFY_INTENT_DATASET_ID=<uuid>                    # optional intent dataset

# Database (Postgres)
DATABASE_URL=postgresql://huph:...@postgres:5432/huph   # internal
# Or from host: postgresql://huph:...@localhost:5433/huph
DB_USER=huph
DB_PASSWORD=...
DB_NAME=huph
DB_PORT=5433

# Valkey (Redis-compatible cache)
REDIS_URL=redis://huph-valkey:6379                # internal
# Or from host: redis://localhost:49379

# NextAuth (must be in BOTH admin AND api container env)
NEXTAUTH_SECRET=...
NEXTAUTH_URL=https://admin.huph.val.id
JWT_SECRET=...

# mem0 (optional)
MEM0_PG_URL=postgresql://mem0:...@localhost:48432/mem0
MEM0_NEO4J_URL=bolt://localhost:48687
MEM0_NEO4J_USER=neo4j
MEM0_NEO4J_PASSWORD=...

# Observability
LANGFUSE_URL=https://langfuse.huph.val.id
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...

# UPH legacy (deferred)
UPH_API_URL=https://admission.uph.edu/api/v1
UPH_API_KEY=...

# Feature flags
LEAD_CAPTURE_ENABLED=true
TEAM_OWNERSHIP_ENABLED=true
ESCALATION_ROUTING_ENABLED=true
API_AUTH_MODE=disabled   # disabled | warn | enforce

See .env.example for the full list.

Infrastructure rule: dedicated HUPH stacks

From memory feedback_dedicated_infra: HUPH must use dedicated infrastructure, never share tools with other server projects. Applies especially to:

  • mem0 instance (contains PII)
  • Langfuse instance (contains LLM conversation history)
  • Postgres (HUPH-only data)
  • Redis (HUPH-only session cache)

Do not suggest sharing these with other projects on the same server.

Gotchas (cross-integration)

  1. Docker internal URLs ≠ host URLs. Inside containers: postgres:5432, huph-valkey:6379, huph-dify-api:5001. From host: localhost:5433, localhost:49379, localhost:5001. Mixing them causes "connection refused" errors.
  2. docker-compose.yml needs explicit env passthrough. Writing to .env is not enough — the API container reads from the environment: block. Every new env var needs a ${VAR:-default} line in docker-compose.yml.
  3. 360dialog tier limitations. Current tier does not expose an App Secret → no HMAC webhook signing possible. Webhook auth relies on network isolation (port 3101 bound to 127.0.0.1) + hub.verify_token one-time subscription.
  4. Dify stack can OOM. 7 containers (dify-api, worker, web, sandbox, plugin-daemon, ssrf-proxy, beat) died at once on Apr 8 because huph-dify-beat hit 256MB limit during flask upgrade-db. Memory limits bumped: dify-beat 256m→512m, dify-worker 512m→1g, dify-plugin-daemon 2g→3g, clickhouse 2g→3g.
  5. NextAuth secret must be in both admin AND api containers. Realtime Socket.io auth uses X-Forwarded-Session JWE — if the API can't decode it, clients stuck Offline.
  6. WhatsApp is the only active channel. Telegram and Web were deleted Apr 8. Code references to them in old specs/memories are historical.
  7. Laravel integration is deferred. Do not auto-suggest UPH legacy admission API integration as a next candidate phase. See memory project_laravel_enrichment_deferred.

See also

  • API — where integrations are called from
  • RAG — Anthropic + vector DB + mem0 integration details
  • Admin — NextAuth + serverFetch pattern
  • Debugging — troubleshooting integration issues