Update Agent Zero, Asterisk, and Telephony K8s manifests

- Update agent-zero deployment configuration
- Update Asterisk configmap and deployment
- Update telephony service manifest

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andrew Stoltz
2026-04-13 19:12:08 -05:00
parent 53234bfcc8
commit ab7435a43a
4 changed files with 243 additions and 80 deletions

View File

@@ -2,13 +2,14 @@
# Agent Zero AI Stack — NUC Deployment (RKE2 Bare-Metal) # Agent Zero AI Stack — NUC Deployment (RKE2 Bare-Metal)
# ============================================================================= # =============================================================================
# Deploys: AgentZero (agent UI) on RKE2 cluster with Blue Jay profile # Deploys: AgentZero (agent UI) on RKE2 cluster with Blue Jay profile
# Ollama: edge1 Pi 5 at 10.0.57.17:11434 (qwen2.5-coder:7b + nomic-embed-text) # Ollama: workstation-first via BLUEJAY-WS (10.0.56.20:11434) with edge1 Pi 5
# fallback (10.0.57.17:11434)
# Target: RKE2 bare-metal cluster, namespace: agent-zero # Target: RKE2 bare-metal cluster, namespace: agent-zero
# Profile: Blue Jay (21 tools, 3 prompts, 4 extensions, theme) # Profile: Blue Jay (21 tools, 3 prompts, 4 extensions, theme)
# #
# Differences from LOCAL (WSL K3s): # Differences from LOCAL (WSL K3s):
# - Uses Longhorn StorageClass (not local-path) # - Uses Longhorn StorageClass (not local-path)
# - Connects to edge1 Pi 5 Ollama (not workstation R9700) # - Prefers workstation Ollama on the R9700, falls back to edge1 Pi 5
# - NO Anthropic API key (free/local models only) # - NO Anthropic API key (free/local models only)
# - NO Piper TTS or Kiwix (edge1 handles TTS, no Wikipedia needed) # - NO Piper TTS or Kiwix (edge1 handles TTS, no Wikipedia needed)
# - NO hostPath volumes — profile/tools/extensions loaded via ConfigMaps # - NO hostPath volumes — profile/tools/extensions loaded via ConfigMaps
@@ -90,7 +91,7 @@ subjects:
# ============================================================================= # =============================================================================
# Agent Zero — AI Agent Web UI (NUC Edition, Blue Jay Profile) # Agent Zero — AI Agent Web UI (NUC Edition, Blue Jay Profile)
# ============================================================================= # =============================================================================
# Connects to edge1 Pi 5 Ollama (free, local models only) # Connects to a local proxy that routes to workstation Ollama first and edge1 second
# Blue Jay profile with 21 tools, 3 prompts, 4 extensions # Blue Jay profile with 21 tools, 3 prompts, 4 extensions
--- ---
@@ -104,7 +105,7 @@ metadata:
annotations: annotations:
agent-zero/deployment: "nuc" agent-zero/deployment: "nuc"
agent-zero/profile: "bluejay" agent-zero/profile: "bluejay"
agent-zero/ollama: "edge1 Pi 5 (10.0.57.17:11434)" agent-zero/ollama: "BLUEJAY-WS primary (10.0.56.20:11434), edge1 fallback (10.0.57.17:11434)"
spec: spec:
replicas: 1 replicas: 1
selector: selector:
@@ -119,18 +120,19 @@ spec:
spec: spec:
serviceAccountName: agent-zero serviceAccountName: agent-zero
initContainers: initContainers:
# Wait for edge1 Pi 5 Ollama to be reachable before starting Agent Zero. # Wait for either workstation or edge1 Ollama to be reachable before starting Agent Zero.
- name: wait-for-ollama - name: wait-for-ollama
image: busybox:1.37 image: busybox:1.37
command: ["sh", "-c"] command: ["sh", "-c"]
args: args:
- | - |
echo "Waiting for Ollama at edge1 (10.0.57.17:11434)..." echo "Waiting for Ollama at BLUEJAY-WS or edge1..."
until wget -qO- --timeout=2 http://10.0.57.17:11434/api/tags >/dev/null 2>&1; do until wget -qO- --timeout=2 http://10.0.56.20:11434/api/tags >/dev/null 2>&1 || \
echo "edge1 Ollama not ready, retrying in 5s..." wget -qO- --timeout=2 http://10.0.57.17:11434/api/tags >/dev/null 2>&1; do
echo "No Ollama endpoint ready yet, retrying in 5s..."
sleep 5 sleep 5
done done
echo "edge1 Ollama is reachable!" echo "At least one Ollama endpoint is reachable."
# Assemble the Blue Jay profile directory structure from ConfigMaps. # Assemble the Blue Jay profile directory structure from ConfigMaps.
# ConfigMaps can't create nested dirs, so we copy into the workspace PVC. # ConfigMaps can't create nested dirs, so we copy into the workspace PVC.
- name: setup-bluejay - name: setup-bluejay
@@ -177,6 +179,50 @@ spec:
- name: bluejay-theme - name: bluejay-theme
mountPath: /tmp/bluejay-theme mountPath: /tmp/bluejay-theme
containers: containers:
- name: ollama-proxy
image: nginx:1.27-alpine
command: ["/bin/sh", "-c"]
args:
- |
cat > /etc/nginx/nginx.conf <<'NGINX'
worker_processes 1;
events { worker_connections 1024; }
http {
upstream ollama_upstream {
server 10.0.56.20:11434 max_fails=2 fail_timeout=10s;
server 10.0.57.17:11434 backup;
keepalive 16;
}
server {
listen 11434;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_connect_timeout 5s;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
proxy_pass http://ollama_upstream;
}
}
}
NGINX
exec nginx -g 'daemon off;'
ports:
- containerPort: 11434
readinessProbe:
httpGet:
path: /api/tags
port: 11434
initialDelaySeconds: 5
periodSeconds: 15
livenessProbe:
httpGet:
path: /api/tags
port: 11434
initialDelaySeconds: 10
periodSeconds: 30
- name: agent-zero - name: agent-zero
image: agent0ai/agent-zero:latest image: agent0ai/agent-zero:latest
command: ["/bin/bash", "-c"] command: ["/bin/bash", "-c"]
@@ -194,10 +240,11 @@ spec:
ln -sfn /a0/work/.bluejay/agents/bluejay /a0/agents/bluejay ln -sfn /a0/work/.bluejay/agents/bluejay /a0/agents/bluejay
# Write model config BEFORE initialize.sh loads it # Write model config BEFORE initialize.sh loads it
# The _model_config plugin reads config.json (NOT config.yaml) # The _model_config plugin reads config.json (NOT config.yaml)
# Default is OpenRouter; override to local Ollama on edge1 # Default is OpenRouter; override to the local proxy, which prefers
# the workstation and falls back to edge1 automatically.
mkdir -p /a0/usr/plugins/_model_config mkdir -p /a0/usr/plugins/_model_config
cat > /a0/usr/plugins/_model_config/config.json << 'MODELCFG' cat > /a0/usr/plugins/_model_config/config.json << 'MODELCFG'
{"allow_chat_override":true,"chat_model":{"provider":"ollama","name":"qwen2.5-coder:7b","api_base":"http://10.0.57.17:11434","ctx_length":8192,"ctx_history":0.7,"vision":false,"kwargs":{"temperature":0,"num_ctx":8192}},"utility_model":{"provider":"ollama","name":"qwen2.5-coder:7b","api_base":"http://10.0.57.17:11434","ctx_length":8192,"ctx_input":0.7,"kwargs":{"num_ctx":8192}},"embedding_model":{"provider":"ollama","name":"nomic-embed-text","api_base":"http://10.0.57.17:11434","kwargs":{}}} {"allow_chat_override":true,"chat_model":{"provider":"ollama","name":"gemma3:12b","api_base":"http://127.0.0.1:11434","ctx_length":8192,"ctx_history":0.7,"vision":false,"kwargs":{"temperature":0,"num_ctx":8192}},"utility_model":{"provider":"ollama","name":"qwen2.5:1.5b","api_base":"http://127.0.0.1:11434","ctx_length":8192,"ctx_input":0.7,"kwargs":{"num_ctx":8192}},"embedding_model":{"provider":"ollama","name":"nomic-embed-text","api_base":"http://127.0.0.1:11434","kwargs":{}}}
MODELCFG MODELCFG
# Strip heredoc indentation # Strip heredoc indentation
sed -i 's/^ //' /a0/usr/plugins/_model_config/config.json sed -i 's/^ //' /a0/usr/plugins/_model_config/config.json
@@ -209,42 +256,42 @@ spec:
# Agent identity # Agent identity
- name: AGENT_NAME - name: AGENT_NAME
value: "Blue Jay (NUC)" value: "Blue Jay (NUC)"
# Chat model — qwen2.5-coder:7b on edge1 Pi 5 # Chat model — workstation primary, edge1 fallback via local proxy
- name: A0_SET_chat_model_provider - name: A0_SET_chat_model_provider
value: "ollama" value: "ollama"
- name: A0_SET_chat_model_name - name: A0_SET_chat_model_name
value: "qwen2.5-coder:7b" value: "gemma3:12b"
- name: A0_SET_chat_model_api_base - name: A0_SET_chat_model_api_base
value: "http://10.0.57.17:11434" value: "http://127.0.0.1:11434"
- name: A0_SET_chat_model_ctx_length - name: A0_SET_chat_model_ctx_length
value: "8192" value: "8192"
- name: A0_SET_chat_model_kwargs - name: A0_SET_chat_model_kwargs
value: '{"temperature": 0, "num_ctx": 8192}' value: '{"temperature": 0, "num_ctx": 8192}'
# Utility model — same as chat (only one model available) # Utility model — fast small helper tier through the same proxy
- name: A0_SET_util_model_provider - name: A0_SET_util_model_provider
value: "ollama" value: "ollama"
- name: A0_SET_util_model_name - name: A0_SET_util_model_name
value: "qwen2.5-coder:7b" value: "qwen2.5:1.5b"
- name: A0_SET_util_model_api_base - name: A0_SET_util_model_api_base
value: "http://10.0.57.17:11434" value: "http://127.0.0.1:11434"
- name: A0_SET_util_model_kwargs - name: A0_SET_util_model_kwargs
value: '{"num_ctx": 2048}' value: '{"num_ctx": 2048}'
# Embedding model — nomic on edge1 # Embedding model — nomic through the same proxy
- name: A0_SET_embed_model_provider - name: A0_SET_embed_model_provider
value: "ollama" value: "ollama"
- name: A0_SET_embed_model_name - name: A0_SET_embed_model_name
value: "nomic-embed-text" value: "nomic-embed-text"
- name: A0_SET_embed_model_api_base - name: A0_SET_embed_model_api_base
value: "http://10.0.57.17:11434" value: "http://127.0.0.1:11434"
# Browser model — disabled (no vision model on Pi) # Browser model — small Gemma candidate through the same proxy
- name: A0_SET_browser_model_provider - name: A0_SET_browser_model_provider
value: "ollama" value: "ollama"
- name: A0_SET_browser_model_name - name: A0_SET_browser_model_name
value: "qwen2.5-coder:7b" value: "gemma3:4b"
- name: A0_SET_browser_model_api_base - name: A0_SET_browser_model_api_base
value: "http://10.0.57.17:11434" value: "http://127.0.0.1:11434"
- name: A0_SET_browser_model_vision - name: A0_SET_browser_model_vision
value: "false" value: "true"
# Agent profile — Blue Jay personality, tools, and system prompt # Agent profile — Blue Jay personality, tools, and system prompt
- name: A0_SET_agent_profile - name: A0_SET_agent_profile
value: "bluejay" value: "bluejay"
@@ -297,7 +344,7 @@ spec:
command: command:
- /bin/bash - /bin/bash
- -c - -c
- "curl -sf http://localhost:80/ > /dev/null && curl -sf --connect-timeout 3 http://10.0.57.17:11434/api/tags > /dev/null" - "curl -sf http://localhost:80/ > /dev/null && curl -sf --connect-timeout 3 http://127.0.0.1:11434/api/tags > /dev/null"
periodSeconds: 30 periodSeconds: 30
failureThreshold: 2 failureThreshold: 2
resources: resources:
@@ -435,7 +482,13 @@ spec:
protocol: UDP protocol: UDP
- port: 53 - port: 53
protocol: TCP protocol: TCP
# Ollama on edge1 # Ollama on BLUEJAY-WS
- to:
- ipBlock:
cidr: 10.0.56.20/32
ports:
- port: 11434
# Ollama on edge1 fallback
- to: - to:
- ipBlock: - ipBlock:
cidr: 10.0.57.17/32 cidr: 10.0.57.17/32

View File

@@ -155,11 +155,11 @@ data:
remove_existing=yes remove_existing=yes
qualify_frequency=60 qualify_frequency=60
; Extension 103 - Office 3 ; Extension 103 - Office 3
[103](phone-template) [103](phone-template)
auth=auth103 auth=auth103
aors=103 aors=103
callerid="Office 3" <103> callerid="Office 3" <103>
[auth103] [auth103]
type=auth type=auth
@@ -167,13 +167,90 @@ data:
username=103 username=103
password=bluejay-ext-103 password=bluejay-ext-103
[103] [103]
type=aor type=aor
max_contacts=1 max_contacts=1
remove_existing=yes remove_existing=yes
qualify_frequency=60 qualify_frequency=60
extensions.conf: | ; Test endpoints 901-904 for softphone proof
[test-endpoint](!)
type=endpoint
context=from-internal
transport=transport-udp
disallow=all
allow=ulaw
allow=alaw
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
[901](test-endpoint)
auth=auth901
aors=901
callerid="Proof Caller" <901>
[auth901]
type=auth
auth_type=userpass
username=901
password=test-sip-secret-901
[901]
type=aor
max_contacts=1
remove_existing=yes
[902](test-endpoint)
auth=auth902
aors=902
callerid="Proof Callee" <902>
[auth902]
type=auth
auth_type=userpass
username=902
password=test-sip-secret-901
[902]
type=aor
max_contacts=1
remove_existing=yes
[903](test-endpoint)
auth=auth903
aors=903
callerid="Proof Endpoint 3" <903>
[auth903]
type=auth
auth_type=userpass
username=903
password=test-sip-secret-901
[903]
type=aor
max_contacts=1
remove_existing=yes
[904](test-endpoint)
auth=auth904
aors=904
callerid="Proof Endpoint 4" <904>
[auth904]
type=auth
auth_type=userpass
username=904
password=test-sip-secret-901
[904]
type=aor
max_contacts=1
remove_existing=yes
extensions.conf: |
[general] [general]
static=yes static=yes
writeprotect=no writeprotect=no
@@ -191,11 +268,37 @@ data:
same => n,Hangup() same => n,Hangup()
[from-internal] [from-internal]
; Internal extension-to-extension dialing ; Internal extension-to-extension dialing
exten => _1XX,1,Dial(PJSIP/${EXTEN},30) exten => _1XX,1,Dial(PJSIP/${EXTEN},30)
same => n,Hangup() same => n,Hangup()
; Outbound via Twilio SIP trunk (11-digit US) ; Softphone proof endpoints and utility extensions
exten => _9XX,1,NoOp(Proof call to ${EXTEN})
same => n,Dial(PJSIP/${EXTEN},30)
same => n,Hangup()
exten => 999,1,Answer()
same => n,Playback(demo-echotest)
same => n,Echo()
same => n,Hangup()
exten => 998,1,Answer()
same => n,Milliwatt()
same => n,Hangup()
exten => 997,1,Answer()
same => n,Wait(0.5)
same => n,Playback(hello-world)
same => n,Wait(1)
same => n,Hangup()
exten => 996,1,Answer()
same => n,Wait(0.5)
same => n,Read(DIGITS,,4,,,5)
same => n,SayDigits(${DIGITS})
same => n,Hangup()
; Outbound via Twilio SIP trunk (11-digit US)
exten => _1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529) exten => _1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529)
same => n,Dial(PJSIP/+${EXTEN}@twilio-trunk,60) same => n,Dial(PJSIP/+${EXTEN}@twilio-trunk,60)
same => n,Hangup() same => n,Hangup()

View File

@@ -16,22 +16,22 @@ spec:
metadata: metadata:
labels: labels:
app: asterisk app: asterisk
spec: spec:
hostNetwork: true nodeSelector:
dnsPolicy: ClusterFirstWithHostNet kubernetes.io/hostname: rke2-agent1
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
securityContext: securityContext:
fsGroup: 0 fsGroup: 0
initContainers: initContainers:
- name: install-sounds - name: install-sounds
image: busybox:latest image: busybox:latest
command: command:
- sh - sh
- -c - -c
- | - |
mkdir -p /sounds/en && mkdir -p /sounds/en &&
wget -qO- http://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-en-ulaw-current.tar.gz | tar xz -C /sounds/en/ && echo "Leaving /var/lib/asterisk/sounds/en empty until the sound bootstrap lane is fixed."
wget -qO- http://downloads.asterisk.org/pub/telephony/sounds/asterisk-extra-sounds-en-ulaw-current.tar.gz | tar xz -C /sounds/en/ &&
echo "Sound files installed: $(find /sounds/en -type f | wc -l) files"
volumeMounts: volumeMounts:
- name: sounds - name: sounds
mountPath: /sounds/en mountPath: /sounds/en

View File

@@ -46,26 +46,31 @@ data:
"Twilio": { "Twilio": {
"VoiceUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/incoming", "VoiceUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/incoming",
"StatusCallbackUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/status" "StatusCallbackUrl": "https://telephony.flowercore.io/api/twilio/webhooks/voice/status"
}, },
"Asterisk": { "Asterisk": {
"BaseUrl": "http://localhost:8088", "BaseUrl": "http://10.0.56.12:8088",
"Username": "flowercore", "Username": "flowercore",
"Password": "bluejay-asterisk-ari", "Password": "bluejay-asterisk-ari",
"Application": "flowercore-pbx", "Application": "flowercore-pbx",
"ReconnectDelaySeconds": 5, "ReconnectDelaySeconds": 5,
"MaxReconnectDelaySeconds": 60 "MaxReconnectDelaySeconds": 60
} }
}, },
"Ari": { "Ari": {
"BaseUrl": "http://localhost:8088", "BaseUrl": "http://10.0.56.12:8088",
"Username": "flowercore", "Username": "flowercore",
"Password": "bluejay-asterisk-ari", "Password": "bluejay-asterisk-ari",
"Application": "flowercore-pbx", "Application": "flowercore-pbx",
"ReconnectDelaySeconds": 5, "ReconnectDelaySeconds": 5,
"MaxReconnectDelaySeconds": 60 "MaxReconnectDelaySeconds": 60
}, },
"Tts": { "Sip": {
"PiperUrl": "http://10.0.57.15:8500", "Domain": "10.0.56.207",
"Port": 5060,
"Transport": "udp"
},
"Tts": {
"PiperUrl": "http://10.0.57.15:8500",
"DefaultEngine": "piper", "DefaultEngine": "piper",
"SampleRate": 8000 "SampleRate": 8000
}, },
@@ -112,10 +117,12 @@ spec:
labels: labels:
app: telephony-web app: telephony-web
spec: spec:
securityContext: securityContext:
fsGroup: 1654 fsGroup: 1654
initContainers: nodeSelector:
- name: fix-data-perms kubernetes.io/hostname: rke2-agent1
initContainers:
- name: fix-data-perms
image: busybox:latest image: busybox:latest
command: ["sh", "-c", "chown -R 1654:1654 /data"] command: ["sh", "-c", "chown -R 1654:1654 /data"]
volumeMounts: volumeMounts: