ASK Assistant Service¶
Repo: ask-assistant-service-main
Language: Python ≥ 3.12
Framework: FastAPI + Gunicorn/UvicornWorker
Helm Chart: assistant-service v0.2.2
Ports: 8000 (assistants), 8001 (tooling), 8003 (intelligence), 8080 (MCP gateway)
Architecture¶
The Assistant Service is a multi-image, multi-process service that implements the AI assistant layer of the ASK platform. It is split into four distinct containers, each serving a specific role in the assistant pipeline:
┌─────────────────────────┐
│ Assistants API │
│ (port 8000) │
│ Dockerfile │
└──────────┬──────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────┐ ┌─────────────────┐
│ Intelligence │ │ Tooling │ │ MCP Gateway │
│ (port 8003) │ │ (port 8001)│ │ (port 8080) │
│ Dockerfile- │ │ Dockerfile-│ │ Dockerfile- │
│ intelligence │ │ tooling │ │ gateway │
└─────────────────┘ └─────────────┘ └─────────────────┘
│ │
▼ ▼
PostgreSQL Redis
(external) (Bitnami subchart
or external)
Additionally, two sandbox environments are managed via Daytona:
┌──────────────────┐ ┌────────────────────┐
│ Daytona Runner │ │ Daytona Sandbox │
│ daytona/apps/ │ │ daytona/apps/ │
│ runner/ │ │ sandbox/ │
└──────────────────┘ └────────────────────┘
Container Images¶
Multi-Stage Build Pattern¶
| Stage | Base Image | Notes |
|---|---|---|
builder |
python:3.12-trixie |
Install deps via uv sync with 4 private GitLab indexes |
runtime |
python:3.12-slim-trixie |
Minimal Debian Trixie base |
The DEPENDENCY_PROXY_PREFIX ARG allows routing through a registry mirror.
Images Produced¶
| Image Name | Dockerfile | Port | Worker Config | Purpose |
|---|---|---|---|---|
assistant-service |
Dockerfile |
8000 | 1–4 Gunicorn workers, 300s timeout | Core Assistants API |
assistant-service-intelligence |
Dockerfile-intelligence |
8003 | 1 Gunicorn worker, 300s timeout | LLM orchestration (LangGraph), higher memory (10Gi limit) |
assistant-service-tooling |
Dockerfile-tooling |
8001 | 1 Gunicorn worker, 300s timeout | ToolBus — tool execution, code execution |
assistant-service-mcp-gateway |
Dockerfile-gateway |
8080 | Uvicorn | MCP Gateway — routes MCP protocol calls |
All images push to:
MCP Gateway — Additional Runtime Components¶
The gateway container installs Node.js 20 at runtime and pre-caches:
| npm Package | Version | Purpose |
|---|---|---|
supergateway |
3.4.3 | MCP protocol gateway |
@modelcontextprotocol/server-filesystem |
latest (pinned) | Filesystem MCP server |
Daytona Sandbox Image¶
The daytona/apps/sandbox/Dockerfile builds a rich execution environment:
Base: daytonaio/sandbox:0.5.0-slim
System packages added: git, curl, gnupg, python3, libreoffice, pandoc, poppler-utils, qpdf, tesseract-ocr, gcc, build-essential, Node.js 20, pnpm, docx, pptxgenjs
Key Python packages in sandbox:
- anthropic SDK — direct Claude API calls
- mcp — MCP protocol
- daytona — Daytona runtime SDK
- PDF/image processing: pypdf2, pillow, pdf2image, pytesseract
- Document: python-docx, openpyxl, markdown
- Data: pandas, numpy, matplotlib, seaborn
Daytona Runner Image¶
Base: daytonaio/daytona-runner
Adds: mount-s3 binary, FUSE kernel module support (for S3 filesystem mounts inside sandboxes)
Build Arguments¶
| ARG | Default | Description |
|---|---|---|
DEPENDENCY_PROXY_PREFIX |
"" |
Registry mirror prefix |
GITLAB_USERNAME |
— | Username for private PyPI indexes |
Build secrets required: tii_gitlab_username, tii_gitlab_password, gitlab_password
Helm Chart¶
Chart: helm/Chart.yaml
Chart Dependencies (Subcharts)¶
| Subchart | Version | Source | Condition |
|---|---|---|---|
redis |
22.0.7 | oci://registry-1.docker.io/bitnamicharts |
redis.enabled |
The Redis subchart provides an optional in-cluster Redis. In production, Redis is external (Azure Cache for Redis); the subchart is disabled and an external connection string is used.
Resource Limits (representative)¶
| Deployment | CPU Request | Memory Request | Memory Limit |
|---|---|---|---|
| Main (assistants) | 300m | 500Mi | 768Mi |
| Intelligence | 500m | 2Gi | 10Gi |
| Tooling | 300m | 500Mi | 2Gi |
| MCP Gateway | 100m | 256Mi | 512Mi |
| Generic Worker | 300m | 500Mi | 1Gi |
Environments¶
| Environment File | Environment | Cloud/DC | Notes |
|---|---|---|---|
values-ai71-uaen-dev-ask71.yaml |
Development | Azure UAE North | Primary dev cluster |
values-ai71-uaen-dev-ask71-preview.yaml |
Dev Preview | Azure UAE North | Feature branch preview envs |
values-ai71-uaen-stg-ask71.yaml |
Staging | Azure UAE North | Pre-prod |
values-ai71-uaen-prod-mufti.yaml |
Production (Mufti) | Azure UAE North | Production tenant A |
values-ai71-pp-auh1-prod-ask.yaml |
PP Production | On-prem Abu Dhabi | Gov cloud, air-gapped |
values-edge-uaen-prod-ask.yaml |
Edge Production | Edge UAE North | Edge deployment |
values-ai71-modgpt-auh1-dev-ask.yaml |
core42 Dev | On-prem RKE2 (core42) | 🔄 In progress — see below |
PP Environment — Assistant Service¶
Full PP environment details: PP Environment page
PP Images¶
| Container | PP Registry Path |
|---|---|
| Main (assistants API) | registry.pp.gov.ae/ask/ask-assistant-service |
| Redis subchart | registry.pp.gov.ae/bitnamilegacy/redis:8.2.1-debian-12-r0 |
imagePullSecrets: harbor-registry-secret
PP Non-Secret Configuration (TOML)¶
| Config Key | PP Value | Notes |
|---|---|---|
app.env |
ai71-pp-auh1-prod-ask |
|
app.base_url |
http://api.ask.pp.gov.ae |
|
app.fastapi_root_path |
/ask71/v2/astsvc |
|
logging.log_level |
INFO |
|
logging.log_sample_rate |
0.0 |
Sampling disabled |
core_service.url |
http://core-service.ask.svc.cluster.local/api/v1 |
In-cluster |
core_service.services_base_url |
http://core-service.ask.svc.cluster.local |
|
database.host |
postgresql.ask.svc.cluster.local |
Shared in-cluster PostgreSQL |
database.user |
assistant-service |
|
foundry.endpoint |
http://litellm.foundry.svc.cluster.local:4000/v1 |
In-cluster LiteLLM |
foundry.reranker.endpoint |
http://litellm.foundry.svc.cluster.local:4000/v1/rerank |
|
storage.cdn_base_url |
https://cdn.ask.pp.gov.ae/static |
|
kms.base_url |
http://knowledge-management-service.ask.svc.cluster.local |
|
hatchet.client_tls_strategy |
none |
TLS disabled for in-cluster Hatchet |
hatchet.generic_worker_slots |
5 |
|
redis.host |
assistant-service-redis-master.ask.svc.cluster.local |
|
daytona.enable_code_execution |
false |
Disabled — no Daytona in PP |
daytona.api_key |
@null |
|
tool_approval.flow_enabled |
false |
|
feature_flags.mode |
offline |
No LaunchDarkly/Unleash in PP |
feature_flags.bootstrap_file |
./config/feature-flags/pp-prod.json |
Bundled in image |
assistants.frontend_url |
https://ask.pp.gov.ae/ |
|
assistants.service_url |
https://api.ask.pp.gov.ae/ask71/v2/astsvc |
|
assistants.intelligence_base_url |
http://assistant-service-intelligence:8003 |
|
assistants.tooling_base_url |
http://assistant-service-tooling:8001 |
|
assistants.default_public_assistant_name |
mujeeb |
PP-specific default assistant |
tooling.data_analysis.*_model |
qwen/qwen3-5-122b-a10b |
OSS on-prem model (vs cloud GPT-5 elsewhere) |
postDeployJob.enabled |
false |
PP Secrets (from Vault kv/data/ask/prod/assistant-service/environment-secrets)¶
| Secret Key | Description |
|---|---|
DATABASE__PASSWORD |
PostgreSQL password |
HATCHET__CLIENT_TOKEN |
Hatchet client token |
CORE_SERVICE__JWT_SECRET |
JWT secret for Core Service |
CORE_SERVICE_ENCRYPTION_KEY |
Core Service encryption key |
AI71_FOUNDRY_KEY |
LiteLLM API key |
AI71_AUTH_STATE_SECRET |
OAuth state secret |
REDIS_PASSWORD |
Redis password |
PP Ingress¶
| Host | Path | Rewrite | Timeout |
|---|---|---|---|
api.ask.pp.gov.ae |
/ask71/v2/astsvc(/|$)(.*) |
/$2 |
proxy read/send 420s |
TLS: ask-pp-gov-ae-cert.
Key PP Differences¶
- Data analysis models: All four data analysis models use
qwen/qwen3-5-122b-a10b(on-prem OSS) instead of cloud defaultgpt-5-chat - Daytona disabled: No code execution sandbox in PP
core42 Environment — Assistant Service (ai71-modgpt-auh1-dev-ask)¶
core42 Images¶
| Container | core42 Registry Path |
|---|---|
| Main | harbor.cl1.sq4.aegis.internal/ask/assistant-service:<git-sha> |
| MCP Gateway | harbor.cl1.sq4.aegis.internal/ask/assistant-service-mcp-gateway:<git-sha> |
| Redis subchart | harbor.cl1.sq4.aegis.internal/bitnamilegacy/redis:8.2.1-debian-12-r0 |
imagePullSecrets: harbor-pull-secret
core42 TOML Config Changes vs PP¶
| Config Key | PP Value | core42 Value |
|---|---|---|
app.env |
ai71-pp-auh1-prod-ask |
ai71-modgpt-auh1-dev-ask |
app.base_url |
http://api.ask.pp.gov.ae |
https://api.cl1.sq4.aegis.internal |
storage.cdn_base_url |
https://cdn.ask.pp.gov.ae/static |
https://cdn.cl1.sq4.aegis.internal/static |
assistants.frontend_url |
https://ask.pp.gov.ae/ |
https://ask.cl1.sq4.aegis.internal/ |
assistants.service_url |
https://api.ask.pp.gov.ae/ask71/v2/astsvc |
https://api.cl1.sq4.aegis.internal/ask71/v2/astsvc |
| All other keys | — | ✅ Same as PP (in-cluster service URLs unchanged) |
configTomlFileMountPath: /app/config/ai71-modgpt-auh1-dev-ask.toml
core42 Vault Secrets¶
Vault path: secret/cl1/assistant-service
| Env Var | Vault Key | Description |
|---|---|---|
HATCHET__CLIENT_TOKEN |
hatchet_client_token |
Hatchet workflow token |
DATABASE__PASSWORD |
db_password |
PostgreSQL password |
REDIS_PASSWORD |
redis_password |
Redis password |
core42 Ingress¶
| Host | Path |
|---|---|
api.cl1.sq4.aegis.internal |
/ask71/v2/astsvc(/|$)(.*) |
- Feature flags offline: Bootstrap JSON file bundled in the image at ./config/feature-flags/pp-prod.json |
|
- Default assistant name: mujeeb (PP-specific branding) |
Configuration Variables¶
Non-Secret Config (representative, from dev values)¶
| Variable | Example (dev) | Description |
|---|---|---|
DATABASE__HOST |
ai71-uaen-dev-ask71-psql-01.postgres.database.azure.com |
PostgreSQL hostname |
REDIS_HOST |
(in-cluster) | Redis host |
CORE_SERVICES_BASE_URL |
http://core-service |
Core Service in-cluster URL |
FOUNDRY__BASE_URL |
https://foundry.core.uaen.ai71services.ai/v1 |
AI71 Foundry LLM endpoint |
STORAGE__CDN_URL |
https://cdn.ask.dev.ai71services.ai/static |
Static assets CDN |
KMS__BASE_URL |
https://api.ask.dev.ai71.ai/ask71/v2/kmsvc |
Key Management Service |
DAYTONA__BASE_URL |
https://daytona.ask.dev.ai71services.ai/api |
Daytona sandbox API |
APP_ENV |
dev |
Dynaconf environment name |
GUNICORN_WORKERS |
1 |
Number of Gunicorn workers |
PORT |
8000 |
Container listen port |
Secrets¶
Secrets are injected via Azure Key Vault + External Secrets Operator. Pattern: {release-name}--{SECTION__KEY} in Key Vault.
| Environment Variable | Description |
|---|---|
AI71_FOUNDRY_KEY |
AI71 Foundry API key |
AI71_AUTH_STATE_SECRET |
OAuth state encryption secret |
DATABASE__PASSWORD |
PostgreSQL password |
REDIS_PASSWORD |
Redis AUTH password |
CORE_SERVICE_ENCRYPTION_KEY |
Encryption key for core service tokens |
CORE_SERVICE__JWT_SECRET |
JWT signing secret for inter-service calls |
IAM__MACHINE_TOKEN |
Zitadel machine account token |
Local development uses 1Password CLI for secret injection (op://ask-assistant-service-nonprod/local/<key>). The .env.tpl file is processed by op inject to produce .env.
ExternalSecret refresh interval: 1 minute.
Key Dependencies¶
Python Packages¶
| Package | Version | Purpose |
|---|---|---|
fastapi |
0.128 | HTTP framework |
uvicorn |
0.35 | ASGI server |
gunicorn |
— | Production WSGI/ASGI process manager |
sqlalchemy |
2.0.38 | ORM (async) |
asyncpg |
— | Async PostgreSQL driver |
alembic |
1.15.1 | Database migrations |
dynaconf |
3.2.12 | Configuration management |
pydantic-settings |
2.10.1 | Settings validation |
openai |
2.32 | OpenAI-compatible client (used with Foundry) |
langchain-core |
0.3.72 | LangChain core abstractions |
langgraph |
0.6.11 | Agent workflow graphs |
fastmcp |
3.2.4 | Fast MCP framework |
mcp |
1.23 | Model Context Protocol SDK |
hatchet-sdk |
1.28 | Async job queue |
document_understanding |
0.1.88 | Document parsing (private) |
storage-lib |
— | Azure/MinIO storage SDK (private) |
ask-feature-flags |
1.1.0 | Feature flag SDK (private) |
sentry-sdk |
2.48+ | Error tracking (fastapi, langgraph, langchain, sqlalchemy, redis, httpx integrations) |
spacy |
3.8.7 | NLP pipeline |
fasttext |
0.9.3 | Language detection |
nltk |
3.9.3 | NLP toolkit |
mem0ai |
2.0 | Agent memory (NLP extras) |
fastembed |
0.8 | Local embedding models |
mlflow |
3.4 | ML experiment tracking |
tavily-python |
0.7.12 | Web search API client |
arxiv |
2.2.0 | arXiv paper search |
youtube-transcript-api |
1.2.2 | YouTube transcript fetching |
python-docx |
1.1.2 | Word document generation |
reportlab |
4.0 | PDF generation |
kubernetes |
31.0 | Kubernetes API client (Daytona integration) |
authlib |
1.6.9 | OAuth 2.0 / OIDC |
PyJWT |
2.9 | JWT encoding/decoding |
polars |
1.0 | Fast DataFrame library |
json-repair |
0.52.4 | LLM JSON output repair |
thefuzz |
0.22.1 | Fuzzy string matching |
evals-sdk |
0.8 | Evaluation pipeline SDK (private) |
arabic-reshaper |
3.0 | Arabic text rendering |
python-bidi |
0.4.2 | Bidirectional text support |
langcodes |
3.5 | Language code handling |
Private GitLab PyPI Indexes¶
| Index Name | Package Provided |
|---|---|
ask-group (TII GitLab) |
document_understanding, storage-lib, connectors-lib |
core-group (TII GitLab) |
iam-client, foundry-client, logger-sdk |
gitlab-eval |
evals-sdk |
ask-feature-flags |
ask-feature-flags |
CI/CD Pipeline¶
File: .gitlab-ci.yml
Tool: GitLab CI
| Stage | Key Jobs | Description |
|---|---|---|
validate |
pre-commit, pytest, security, migration-checks | Code quality, tests, Alembic migration validation |
build |
docker-acr-build |
Build 4 Docker images (main + intelligence + tooling + gateway) and push to ACR |
helm-release |
helm-release |
Publish chart to GitLab OCI registry |
.post |
cleanup | Remove temp resources |
Key CI variables:
| Variable | Value |
|---|---|
UV_VERSION |
0.9.21 |
PYTHON_VERSION |
3.12 |
BASE_LAYER |
bookworm |
ArgoCD dev deployment is triggered via .gitlab/ci/argocd-dev-deploy.yaml on merge to main.