Skip to content
Merged
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
18 changes: 18 additions & 0 deletions hosting/kubernetes/ee/values.ee.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,24 @@ global:
# snapshot: daytona-small
# target: eu

# ================================================================== #
# === agentRunner ===
# sandbox-agent runner used by agent workflows. The services pod gets
# AGENTA_AGENT_RUNNER_URL from this component.
# ================================================================== #
# agentRunner:
# enabled: true
# port: 8765
# provider: local
# enableMcp: false
# daytona:
# apiKey:
# apiUrl: https://app.daytona.io/api
# target: eu
# snapshot:
# image:
# installPi: false

# ================================================================== #
# docker (compose-only — no-op on Kubernetes, kept commented so this
# file mirrors the compose env surface without affecting K8s behavior).
Expand Down
1 change: 1 addition & 0 deletions hosting/kubernetes/helm/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Ensure it contains the following keys:
- NEWRELIC_LICENSE_KEY
- LOOPS_API_KEY
- DAYTONA_API_KEY
- SANDBOX_AGENT_DAYTONA_API_KEY
- AGENTA_AI_SERVICES_API_KEY
- AGENTA_AI_SERVICES_REFINE_PROMPT_KEY
- <PROVIDER>_API_KEY # llm providers (openai, anthropic, …)
Expand Down
45 changes: 45 additions & 0 deletions hosting/kubernetes/helm/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- $v := (default dict .Values.services).enabled -}}
{{- if kindIs "invalid" $v }}true{{- else }}{{- $v -}}{{- end }}
{{- end }}
{{- define "agenta.agentRunner.enabled" -}}
{{- $v := (default dict .Values.agentRunner).enabled -}}
{{- if kindIs "invalid" $v }}true{{- else }}{{- $v -}}{{- end }}
{{- end }}
{{- define "agenta.supertokens.enabled" -}}
{{- $v := (default dict (include "agenta.values" . | fromYaml).supertokens).enabled -}}
{{- if kindIs "invalid" $v }}true{{- else }}{{- $v -}}{{- end }}
Expand Down Expand Up @@ -112,6 +116,7 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- define "agenta.api.replicas" -}}{{ default 1 (default dict .Values.api).replicas }}{{- end }}
{{- define "agenta.web.replicas" -}}{{ default 1 (default dict .Values.web).replicas }}{{- end }}
{{- define "agenta.services.replicas" -}}{{ default 1 (default dict .Values.services).replicas }}{{- end }}
{{- define "agenta.agentRunner.replicas" -}}{{ default 1 (default dict .Values.agentRunner).replicas }}{{- end }}
{{- define "agenta.supertokens.replicas" -}}{{ default 1 (default dict (include "agenta.values" . | fromYaml).supertokens).replicas }}{{- end }}
{{- /* cron runs supercronic, which doesn't coordinate across replicas:
N replicas = every scheduled job fires N times. Hard-set to 1.
Expand All @@ -134,6 +139,7 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- define "agenta.api.port" -}}{{ default 8000 (default dict .Values.api).port }}{{- end }}
{{- define "agenta.web.port" -}}{{ default 3000 (default dict .Values.web).port }}{{- end }}
{{- define "agenta.services.port" -}}{{ default 80 (default dict .Values.services).port }}{{- end }}
{{- define "agenta.agentRunner.port" -}}{{ default 8765 (default dict .Values.agentRunner).port }}{{- end }}
{{- define "agenta.supertokens.port" -}}{{ default 3567 (default dict (include "agenta.values" . | fromYaml).supertokens).port }}{{- end }}
{{- define "agenta.redisVolatile.port" -}}{{ default 6379 (default dict .Values.redisVolatile).port }}{{- end }}
{{- define "agenta.redisDurable.port" -}}{{ default 6381 (default dict .Values.redisDurable).port }}{{- end }}
Expand All @@ -144,6 +150,7 @@ app.kubernetes.io/instance: {{ .Release.Name }}
{{- define "agenta.api.pullPolicy" -}}{{ default "IfNotPresent" (default dict (default dict .Values.api).image).pullPolicy }}{{- end }}
{{- define "agenta.web.pullPolicy" -}}{{ default "IfNotPresent" (default dict (default dict .Values.web).image).pullPolicy }}{{- end }}
{{- define "agenta.services.pullPolicy" -}}{{ default "IfNotPresent" (default dict (default dict .Values.services).image).pullPolicy }}{{- end }}
{{- define "agenta.agentRunner.pullPolicy" -}}{{ default "IfNotPresent" (default dict (default dict .Values.agentRunner).image).pullPolicy }}{{- end }}
{{- define "agenta.supertokens.pullPolicy" -}}{{ default "IfNotPresent" (default dict (default dict (include "agenta.values" . | fromYaml).supertokens).image).pullPolicy }}{{- end }}
{{- define "agenta.redisVolatile.pullPolicy" -}}{{ default "IfNotPresent" (default dict (default dict .Values.redisVolatile).image).pullPolicy }}{{- end }}
{{- define "agenta.redisDurable.pullPolicy" -}}{{ default "IfNotPresent" (default dict (default dict .Values.redisDurable).image).pullPolicy }}{{- end }}
Expand Down Expand Up @@ -277,6 +284,44 @@ ghcr.io/agenta-ai/agenta-services
{{ include "agenta.servicesImageRepository" . }}:{{ $img.tag | default .Chart.AppVersion }}
{{- end }}

{{- define "agenta.agentRunnerImageRepository" -}}
{{- $img := default dict (default dict .Values.agentRunner).image -}}
{{- if $img.repository -}}
{{- $img.repository -}}
{{- else -}}
ghcr.io/agenta-ai/agenta-sandbox-agent
{{- end -}}
{{- end }}

{{- define "agenta.agentRunnerImage" -}}
{{- $img := default dict (default dict .Values.agentRunner).image -}}
{{ include "agenta.agentRunnerImageRepository" . }}:{{ $img.tag | default .Chart.AppVersion }}
{{- end }}

{{- define "agenta.agentRunner.serviceName" -}}
{{ include "agenta.fullname" . }}-sandbox-agent
{{- end }}

{{- define "agenta.agentRunner.url" -}}
{{- $runner := default dict .Values.agentRunner -}}
{{- if $runner.externalUrl -}}
{{- $runner.externalUrl -}}
{{- else if eq (include "agenta.agentRunner.enabled" .) "true" -}}
http://{{ include "agenta.agentRunner.serviceName" . }}:{{ include "agenta.agentRunner.port" . }}
{{- end -}}
{{- end }}

{{- define "agenta.agentRunner.servicesEnv" -}}
{{- $runner := default dict .Values.agentRunner -}}
{{- $url := include "agenta.agentRunner.url" . -}}
{{- if $url }}
- name: AGENTA_AGENT_RUNNER_URL
value: {{ $url | quote }}
{{- end }}
- name: AGENTA_AGENT_ENABLE_MCP
value: {{ default false $runner.enableMcp | quote }}
{{- end }}

{{/* ================================================================
Supertokens image (default repo and tag).
================================================================ */}}
Expand Down
120 changes: 120 additions & 0 deletions hosting/kubernetes/helm/templates/sandbox-agent-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{{- $runner := default dict .Values.agentRunner -}}
{{- $daytona := default dict $runner.daytona -}}
{{- if eq (include "agenta.agentRunner.enabled" .) "true" }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "agenta.agentRunner.serviceName" . }}
labels:
{{- include "agenta.labels" . | nindent 4 }}
app.kubernetes.io/component: sandbox-agent
spec:
replicas: {{ include "agenta.agentRunner.replicas" . }}
selector:
matchLabels:
{{- include "agenta.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: sandbox-agent
template:
metadata:
labels:
{{- include "agenta.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: sandbox-agent
spec:
{{- include "agenta.imagePullSecrets" . | nindent 6 }}
serviceAccountName: {{ include "agenta.serviceAccountName" . }}
{{- with $runner.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: sandbox-agent
image: {{ include "agenta.agentRunnerImage" . }}
imagePullPolicy: {{ include "agenta.agentRunner.pullPolicy" . }}
{{- with $runner.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
ports:
- name: http
containerPort: {{ include "agenta.agentRunner.port" . }}
protocol: TCP
env:
- name: PORT
value: {{ include "agenta.agentRunner.port" . | quote }}
- name: SANDBOX_AGENT_PROVIDER
value: {{ default "local" $runner.provider | quote }}
{{- if $runner.logLevel }}
- name: SANDBOX_AGENT_LOG_LEVEL
value: {{ $runner.logLevel | quote }}
{{- end }}
{{- if $daytona.apiUrl }}
- name: SANDBOX_AGENT_DAYTONA_API_URL
value: {{ $daytona.apiUrl | quote }}
{{- end }}
{{- if $daytona.target }}
- name: SANDBOX_AGENT_DAYTONA_TARGET
value: {{ $daytona.target | quote }}
{{- end }}
{{- if $daytona.snapshot }}
- name: SANDBOX_AGENT_DAYTONA_SNAPSHOT
value: {{ $daytona.snapshot | quote }}
{{- end }}
{{- if $daytona.image }}
- name: SANDBOX_AGENT_DAYTONA_IMAGE
value: {{ $daytona.image | quote }}
{{- end }}
{{- if hasKey $daytona "installPi" }}
- name: SANDBOX_AGENT_DAYTONA_INSTALL_PI
value: {{ $daytona.installPi | quote }}
{{- end }}
{{- if or $daytona.apiKey (eq (default "local" $runner.provider) "daytona") }}
- name: SANDBOX_AGENT_DAYTONA_API_KEY
valueFrom:
secretKeyRef:
name: {{ include "agenta.secretName" . }}
key: SANDBOX_AGENT_DAYTONA_API_KEY
optional: true
{{- end }}
{{- range $key, $val := $runner.env }}
- name: {{ $key }}
value: {{ $val | quote }}
{{- end }}
startupProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 30
livenessProbe:
httpGet:
path: /health
port: http
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: http
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
{{- with $runner.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with $runner.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $runner.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $runner.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
19 changes: 19 additions & 0 deletions hosting/kubernetes/helm/templates/sandbox-agent-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{{- if eq (include "agenta.agentRunner.enabled" .) "true" }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "agenta.agentRunner.serviceName" . }}
labels:
{{- include "agenta.labels" . | nindent 4 }}
app.kubernetes.io/component: sandbox-agent
spec:
type: ClusterIP
selector:
{{- include "agenta.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: sandbox-agent
ports:
- name: http
port: {{ include "agenta.agentRunner.port" . }}
targetPort: http
protocol: TCP
{{- end }}
5 changes: 5 additions & 0 deletions hosting/kubernetes/helm/templates/secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
{{- $aiServices := default dict $agenta.aiServices -}}
{{- $loops := default dict $values.loops -}}
{{- $daytona := default dict $values.daytona -}}
{{- $agentRunner := default dict $values.agentRunner -}}
{{- $agentRunnerDaytona := default dict $agentRunner.daytona -}}
{{- if not $secrets.existingSecret }}
apiVersion: v1
kind: Secret
Expand Down Expand Up @@ -254,4 +256,7 @@ stringData:
{{- if $daytona.apiKey }}
DAYTONA_API_KEY: {{ $daytona.apiKey | quote }}
{{- end }}
{{- if $agentRunnerDaytona.apiKey }}
SANDBOX_AGENT_DAYTONA_API_KEY: {{ $agentRunnerDaytona.apiKey | quote }}
{{- end }}
{{- end }}
1 change: 1 addition & 0 deletions hosting/kubernetes/helm/templates/services-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ spec:
{{- include "agenta.commonEnv" . | nindent 12 }}
- name: SCRIPT_NAME
value: "/services"
{{- include "agenta.agentRunner.servicesEnv" . | nindent 12 }}
{{- range $key, $val := $services.env }}
- name: {{ $key }}
value: {{ $val | quote }}
Expand Down
40 changes: 40 additions & 0 deletions hosting/kubernetes/helm/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@
"api": { "$ref": "#/$defs/component" },
"web": { "$ref": "#/$defs/component" },
"services": { "$ref": "#/$defs/component" },
"agentRunner": { "$ref": "#/$defs/agentRunner" },
"workerEvaluations": { "$ref": "#/$defs/component" },
"workerTracing": { "$ref": "#/$defs/component" },
"workerWebhooks": { "$ref": "#/$defs/component" },
Expand Down Expand Up @@ -382,6 +383,45 @@
"labels": { "type": "object", "additionalProperties": { "type": "string" } }
}
},
"agentRunner": {
"type": "object",
"additionalProperties": true,
"description": "sandbox-agent runner deployment. Services receive AGENTA_AGENT_RUNNER_URL from this component unless externalUrl is set.",
"properties": {
"enabled": { "type": "boolean" },
"replicas": { "type": "integer", "minimum": 0 },
"port": { "type": ["integer", "string"] },
"externalUrl": { "type": "string", "description": "External runner URL. Emitted as AGENTA_AGENT_RUNNER_URL when set." },
"provider": { "type": "string", "enum": ["local", "daytona"], "description": "SANDBOX_AGENT_PROVIDER." },
"enableMcp": { "type": ["boolean", "string"], "description": "AGENTA_AGENT_ENABLE_MCP on the services pod." },
"logLevel": { "type": "string", "description": "SANDBOX_AGENT_LOG_LEVEL." },
"image": {
"type": "object",
"additionalProperties": true,
"properties": {
"repository": { "type": "string" },
"tag": { "type": "string" },
"pullPolicy": { "type": "string", "enum": ["Always", "IfNotPresent", "Never"] }
}
},
"daytona": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiKey": { "type": "string", "description": "SANDBOX_AGENT_DAYTONA_API_KEY via Secret." },
"apiUrl": { "type": "string", "description": "SANDBOX_AGENT_DAYTONA_API_URL." },
"target": { "type": "string", "description": "SANDBOX_AGENT_DAYTONA_TARGET." },
"snapshot": { "type": "string", "description": "SANDBOX_AGENT_DAYTONA_SNAPSHOT." },
"image": { "type": "string", "description": "SANDBOX_AGENT_DAYTONA_IMAGE." },
"installPi": { "type": ["boolean", "string"], "description": "SANDBOX_AGENT_DAYTONA_INSTALL_PI." }
}
},
"resources": { "type": "object", "additionalProperties": true },
"env": { "type": "object", "additionalProperties": { "type": ["string", "number", "boolean"] } },
"annotations": { "type": "object", "additionalProperties": { "type": "string" } },
"labels": { "type": "object", "additionalProperties": { "type": "string" } }
}
},
"bundledRedis": {
"type": "object",
"additionalProperties": true,
Expand Down
11 changes: 11 additions & 0 deletions hosting/kubernetes/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,14 @@ global:
redisDurable:
persistence:
size: "5Gi"

# ================================================================== #
# agentRunner — sandbox-agent-backed agent workflow runner.
# The services pod calls this over AGENTA_AGENT_RUNNER_URL. Keep provider
# credentials scoped here instead of putting them in every Agenta container.
# ================================================================== #
agentRunner:
enabled: true
port: 8765
provider: "local"
enableMcp: false
Comment on lines +112 to +116

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

agentRunner is enabled by default — confirm upgrade impact.

With enabled: true here (and the agenta.agentRunner.enabled helper also defaulting to true when unset), every existing release that upgrades to this chart version will automatically get a new sandbox-agent Deployment + Service, and the services pod will start receiving AGENTA_AGENT_RUNNER_URL. If this should be opt-in for existing installs, consider defaulting to false and enabling it in the example values instead.

18 changes: 18 additions & 0 deletions hosting/kubernetes/oss/values.oss.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,24 @@ agenta:
# snapshot: daytona-small
# target: eu

# ================================================================== #
# === agentRunner ===
# sandbox-agent runner used by agent workflows. The services pod gets
# AGENTA_AGENT_RUNNER_URL from this component.
# ================================================================== #
# agentRunner:
# enabled: true
# port: 8765
# provider: local
# enableMcp: false
# daytona:
# apiKey:
# apiUrl: https://app.daytona.io/api
# target: eu
# snapshot:
# image:
# installPi: false

# ================================================================== #
# docker (compose-only — no-op on Kubernetes, kept commented so this
# file mirrors the compose env surface without affecting K8s behavior).
Expand Down
Loading