Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ See [keep a changelog] for information about writing changes to this log.

## [Unreleased]

* —
* Added agentic search tool and config to enabled it

## [0.4.0] - 2026-05-20

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: search-agent
namespace: argo-cd
spec:
destinations:
- name: in-cluster
namespace: search-agent
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ''
kind: Namespace
namespaceResourceWhitelist:
- group: '*'
kind: '*'
orphanedResources:
warn: false
sourceRepos:
- https://github.com/ai-platform-infrastructure/open-webui-k8s.git # git repository
7 changes: 7 additions & 0 deletions applications/argo-cd-resources/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,10 @@ apps:
- authentik-values.yaml
- cloudnative-pg-values.yaml
- redis-replication-values.yaml

- name: search-agent
project: search-agent
namespace: search-agent
automated: true
valueFiles:
- values.yaml
26 changes: 21 additions & 5 deletions applications/openwebui/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ open-webui:
# -- Open WebUI image tags can be found here: https://github.com/open-webui/open-webui
image:
repository: ghcr.io/os2ai/open-webui
tag: "v0.8.10-4"
tag: "v0.8.12-4"
pullPolicy: "IfNotPresent"

ollama:
Expand Down Expand Up @@ -302,6 +302,13 @@ open-webui:
value: "members"

# Admin
- name: WEBUI_ADMIN_EMAIL
value: info@os2ai.os2.dk
- name: WEBUI_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: openwebui-secrets
key: WEBUI_ADMIN_PASSWORD
- name: ENABLE_ADMIN_CHAT_ACCESS
value: "False"

Expand Down Expand Up @@ -425,15 +432,20 @@ open-webui:
# name: openwebui-secrets
# key: TTS_API_KEY

# API key generation
- name: ENABLE_API_KEY
value: "False"
- name: ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS
value: "True"
- name: API_KEYS_ALLOWED_ENDPOINTS
value: "/api/v1/retrieval/,/api/v1/auths/,/api/v1/models,/api/models,/api/v1/models/base,/api/models/base,/api/chat/completions,/api/v1/chat/completions,/health"

# Disable direct connections (do not allow users to connect to new servers)
- name: ENABLE_DIRECT_CONNECTIONS
value: "False"
# User profile notification webhooks
- name: ENABLE_USER_WEBHOOKS
value: "False"
# Disable api key generation (in user profile)
- name: ENABLE_API_KEY
value: "False"
# Sharing
- name: ENABLE_COMMUNITY_SHARING
value: "False"
Expand All @@ -451,6 +463,10 @@ open-webui:
- name: ENABLE_FOLLOW_UP_GENERATION
value: "False"

# Tools configuration
- name: TOOL_SERVER_CONNECTIONS
value: '[{"type":"mcp","url":"http://search-agent.search-agent.svc.cluster.local:8001/mcp","spec_type":"url","spec":"","path":"openapi.json","auth_type":"none","key":"","config":{"enable":true},"info":{"id":"websearch","name":"websearch","description":"Search the internet"}}]'

# Default prompts
- name: TITLE_GENERATION_PROMPT_TEMPLATE
value: "### Opgave:\nGenerér en kort, 3-5 ords titel med en emoji, der opsummerer chat-historikken.\n \n### Retningslinjer:\n- Titlen skal tydeligt repræsentere hovedtemaet eller emnet for samtalen.\n- Brug emojis, der understøtter forståelsen af emnet, men undgå citationstegn eller særlig formatering.\n- Skriv titlen på samtalens primære sprog; brug dansk som standard, hvis sproget er blandet.\n- Prioritér præcision frem for overdreven kreativitet; hold det klart og enkelt.\n- Dit svar skal udelukkende bestå af JSON-objektet, uden indledende eller afsluttende tekst.\n- Output skal være ét enkelt råt JSON-objekt, uden markdown-kodeblokke eller anden indkapsling.\n- Sørg for, at der ikke kommer samtaletekst, bekræftelser eller forklaringer før eller efter JSON-outputtet, da dette vil medføre fejl i parsningen.\n \n### Output:\nJSON-format: { \"title\": \"din korte titel her\" }\n \n### Eksempler:\n- { \"title\": \"📉 Tendens i data\" }\n- { \"title\": \"🍪 Dagens kantinemenu\" }\n- { \"title\": \"Musikstreamingens udvikling\" }\n- { \"title\": \"Tips til hjemmearbejde\" }\n- { \"title\": \"Kunstig intelligens i sundhedsvæsenet\" }\n- { \"title\": \"🎮 Indblik i spiludvikling\" }\n \n### Chat-historik:\n<chat_history>\n{{MESSAGES:END:2}}\n</chat_history>"
Expand Down Expand Up @@ -535,7 +551,7 @@ open-webui:

# Web-search
- name: ENABLE_WEB_SEARCH
value: "True"
value: "False"
- name: WEB_SEARCH_ENGINE
value: "searxng"
- name: WEB_SEARCH_RESULT_COUNT
Expand Down
3 changes: 3 additions & 0 deletions applications/search-agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
charts
Chart.lock
local-secrets
3 changes: 3 additions & 0 deletions applications/search-agent/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
apiVersion: v2
name: search-agent
version: 0.0.1
39 changes: 39 additions & 0 deletions applications/search-agent/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: search-agent-env
namespace: {{ .Release.Namespace }}
data:
SEARCH_AGENT_LLM_MODEL: {{ .Values.env.llmModel | quote }}
SEARCH_AGENT_LLM_BASE_URL: {{ .Values.env.llmBaseUrl | quote }}
SEARCH_AGENT_LLM_TIMEOUT: {{ .Values.env.llmTimeout | quote }}

SEARCH_AGENT_SEARXNG_URL: {{ .Values.env.searxngUrl | quote }}
SEARCH_AGENT_SEARXNG_TIMEOUT: {{ .Values.env.searxngTimeout | quote }}

SEARCH_AGENT_DATETIME_TIMEZONE: {{ .Values.env.datetimeTimezone | quote }}
SEARCH_AGENT_DATETIME_FORMAT: {{ .Values.env.datetimeFormat | quote }}
SEARCH_AGENT_MCP_ALLOWED_HOSTS: {{ .Values.env.mcpAllowedHosts | quote }}

SEARCH_AGENT_SEARCH_QUERY_PLANNER_PROMPT: {{ .Values.env.searchQueryPlannerPrompt | quote }}
SEARCH_AGENT_SEARCH_ANALYZE_SYNTHESIZE_PROMPT: {{ .Values.env.searchAnalyzeSynthesizePrompt | quote }}
SEARCH_AGENT_SEARCH_PIPELINE_TIMEOUT: {{ .Values.env.searchPipelineTimeout | quote }}
SEARCH_AGENT_SEARCH_SKIP_PLANNER_FOR_SIMPLE_QUERIES: {{ .Values.env.searchSkipPlannerForSimpleQueries | quote }}
SEARCH_AGENT_SEARCH_MAX_QUERIES: {{ .Values.env.searchMaxQueries | quote }}
SEARCH_AGENT_SEARCH_MAX_RESULTS: {{ .Values.env.searchMaxResults | quote }}
SEARCH_AGENT_SEARCH_SIMPLE_QUERY_MAX_WORDS: {{ .Values.env.searchSimpleQueryMaxWords | quote }}
SEARCH_AGENT_SEARCH_SIMPLE_QUERY_MAX_QUESTIONS: {{ .Values.env.searchSimpleQueryMaxQuestions | quote }}
SEARCH_AGENT_SEARCH_FETCH_PAGE_CONTENT: {{ .Values.env.searchFetchPageContent | quote }}
SEARCH_AGENT_SEARCH_FETCH_MAX_PAGES: {{ .Values.env.searchFetchMaxPages | quote }}
SEARCH_AGENT_SEARCH_FETCH_TIMEOUT: {{ .Values.env.searchFetchTimeout | quote }}
SEARCH_AGENT_SEARCH_FETCH_MAX_CHARS: {{ .Values.env.searchFetchMaxChars | quote }}
SEARCH_AGENT_SEARCH_FETCH_MAX_BYTES: {{ .Values.env.searchFetchMaxBytes | quote }}

SEARCH_AGENT_CACHE_BACKEND: {{ .Values.env.cacheBackend | quote }}
SEARCH_AGENT_CACHE_REDIS_URL: {{ .Values.env.cacheRedisUrl | quote }}
SEARCH_AGENT_CACHE_FETCH_TTL: {{ .Values.env.cacheFetchTtl | quote }}
SEARCH_AGENT_CACHE_FETCH_NEGATIVE_TTL: {{ .Values.env.cacheFetchNegativeTtl | quote }}
SEARCH_AGENT_CACHE_SEARXNG_TTL: {{ .Values.env.cacheSearxngTtl | quote }}
SEARCH_AGENT_CACHE_PLANNER_TTL: {{ .Values.env.cachePlannerTtl | quote }}

SEARCH_AGENT_DEBUG: {{ .Values.env.debug | quote }}
62 changes: 62 additions & 0 deletions applications/search-agent/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: search-agent
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: search-agent
app.kubernetes.io/instance: search-agent
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: search-agent
app.kubernetes.io/instance: search-agent
template:
metadata:
labels:
app.kubernetes.io/name: search-agent
app.kubernetes.io/instance: search-agent
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: search-agent
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8001
protocol: TCP
envFrom:
- configMapRef:
name: search-agent-env
- secretRef:
name: search-agent-secrets
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
resources:
{{- toYaml .Values.resources | nindent 12 }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
capabilities:
drop:
- ALL
60 changes: 60 additions & 0 deletions applications/search-agent/templates/redis-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/instance: search-agent-redis
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: redis
app.kubernetes.io/instance: search-agent-redis
template:
metadata:
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/instance: search-agent-redis
spec:
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 1000
fsGroup: 1000
containers:
- name: redis
image: {{ .Values.redis.image }}
imagePullPolicy: IfNotPresent
args: ["--save", "", "--appendonly", "no"]
ports:
- name: redis
containerPort: 6379
protocol: TCP
readinessProbe:
tcpSocket:
port: redis
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: redis
initialDelaySeconds: 15
periodSeconds: 20
resources:
{{- toYaml .Values.redis.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /data
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumes:
- name: data
emptyDir: {}
18 changes: 18 additions & 0 deletions applications/search-agent/templates/redis-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: redis
app.kubernetes.io/instance: search-agent-redis
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: redis
app.kubernetes.io/instance: search-agent-redis
ports:
- name: redis
port: 6379
targetPort: redis
protocol: TCP
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: search-agent-secrets
namespace: search-agent
spec:
encryptedData:
SEARCH_AGENT_LLM_API_KEY: AgAXhEjapZnuh6WOgE8uSntHlA8OJ6zbiviwsZPz5/gRDpIQFJNxy6wjbX7sVr2GaFjNKLuUTz9aTXaRqDH633w2Y0uy0gk6OPbMmh5efqMdaZknzpnvq0S//gs4pHih7JtH1pGdrJbrNqMB08xg2kKo1VFMllXKIJ8jmN9GO6MRx5kqCsoigkqbjRl7+7Ypk5gVt0GMJbs56Xn5dYuf1dwYFB6XWCMPHBklGe2UjhvpZ11A0ZYR9/UKFkFEmYDZflayrvQPIaCJaaUdvfnf1c3UCiuLKuozAjMiw13jhOSTHTzDl/Bt/rZH90+sf75fRG9V6DRA0vtuxPVdGQto1FQQYhViHJLVz0jiBjmhi89m+CrYb2PRNqX4B2+Rd0evHilOl50qGoGpynYcjAypZ3aRdWiMPiUMTCcXcghZjO2ePCHXdEfZcxr6xdzaDPkDfvSPSYVJvjS/L5+FzHf//ycKxIRAM6K1HotDMB+uiIIOfayOtgL5neQkWoV0R8NUc7TgKRwnk9IyYTohj1FjV6WwUU/bYfeR5XBAWepuscS1o7LnCC2EAcyK2J989yIyGwu4G3QgqD/wESlL9cANdyc7fhX692oxXT/SgtCRlez6Emh3lG8fUywm4CR7fjXwrH2M1ZCbrDg+8WNsLhtd8l/zL2qD87jUlvd/Gt9yeOYkBGn5ibp5Bv7hXExi2v9inrw3IcTHjfFjnPhlRLCflFYXgtUoJDRW8bs+
template:
metadata:
creationTimestamp: null
name: search-agent-secrets
namespace: search-agent
type: Opaque
18 changes: 18 additions & 0 deletions applications/search-agent/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
name: search-agent
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: search-agent
app.kubernetes.io/instance: search-agent
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: search-agent
app.kubernetes.io/instance: search-agent
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
61 changes: 61 additions & 0 deletions applications/search-agent/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
image:
repository: ghcr.io/aarhusai/search-agent
tag: 0.0.1
pullPolicy: Always

replicaCount: 1

service:
port: 8001

resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1500m
memory: 2Gi

redis:
image: redis:7.4.2-alpine3.21
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 512Mi

env:
llmModel: "AarhusAI-default"
llmBaseUrl: "http://litellm.litellm.svc.cluster.local:4000/v1"
llmTimeout: "60"

searxngUrl: "http://searxng.searxng.svc.cluster.local:8080"
searxngTimeout: "15"

datetimeTimezone: "Europe/Copenhagen"
datetimeFormat: "%A, %B %-d, %Y, %H:%M %Z"
mcpAllowedHosts: '["search-agent.search-agent.svc.cluster.local:8001","search-agent:8001","localhost:8001"]'
searchQueryPlannerPrompt: ""
searchAnalyzeSynthesizePrompt: ""
searchPipelineTimeout: "90"
searchSkipPlannerForSimpleQueries: "true"
searchMaxQueries: "3"
searchMaxResults: "6"
searchSimpleQueryMaxWords: "15"
searchSimpleQueryMaxQuestions: "1"
searchFetchPageContent: "true"
searchFetchMaxPages: "5"
searchFetchTimeout: "10"
searchFetchMaxChars: "5000"
searchFetchMaxBytes: "2000000"

cacheBackend: "redis"
cacheRedisUrl: "redis://redis:6379/0"
cacheFetchTtl: "3600"
cacheFetchNegativeTtl: "300"
cacheSearxngTtl: "300"
cachePlannerTtl: "21600"

debug: "false"
Loading
Loading