Deploy the analyzer worker
The analyzer worker is the instruction-hub-worker service that runs inside your infrastructure. It accepts session traces from enrolled hosts, stores them in your Postgres database and S3 bucket, and runs the Friction Analyzer.
This guide installs the worker into an existing Kubernetes cluster with Helm and verifies the connections it needs. You deploy the 0.2.0 chart with the ghcr.io/promptless/instruction-hub-worker:0.2.0 image. You supply secret material through a Kubernetes Secret you create, and route traffic to the worker on Service port 8080.
What runs where
Section titled “What runs where”| Hosted Promptless | Your infrastructure |
|---|---|
| Deployment registration, configuration sync, and host credential introspection | The worker Deployment and its Kubernetes credentials |
| Trace metadata, findings, and remediation workflow | Raw traces and canonical trace objects in your S3 bucket and Postgres database |
| Deployment and analysis status | Trace analysis through the model provider and endpoint you configure |
Hosted Promptless never receives raw trace content. Findings can contain model-authored descriptions of a session. See Trust and data model for the complete boundary.
Before you begin
Section titled “Before you begin”You need:
- A Promptless organization with Agent Instructions enabled, and a
plih_install token for this deployment. - An existing Kubernetes cluster and the 0.2.0 worker chart from Promptless.
- Helm 3 and
kubectlinstalled locally, withkubectlconnected to the target cluster. - Permission to create a namespace, Deployment, Service, ServiceAccount, Secret, migration Job, and optional ingress resources.
- A Postgres database you control for trace and host metadata.
- An S3 bucket you control for raw traces and canonical trace objects.
- An IAM role or equivalent workload identity that lets the worker read and write objects in that bucket.
- A hostname and TLS certificate that enrolled hosts can reach. The endpoint can be private if all hosts are on the same private network.
The worker and installation machine need these network paths:
| Source | Destination | Port | Purpose |
|---|---|---|---|
| Enrolled hosts | Worker hostname | 443 | Enrollment, check-ins, and trace uploads |
| Worker | Hosted Promptless Runtime | 443 | Configuration sync, credential introspection, and findings |
| Worker | Postgres | 5432 | Trace and host metadata |
| Worker | S3 | 443 | Raw and canonical trace objects |
| Worker | Your model provider | 443 | Trace analysis, once analysis is enabled |
| Cluster nodes | Promptless container registry | 443 | Worker image pull |
Confirm the target cluster before continuing:
kubectl config current-contextInstall the worker
Section titled “Install the worker”-
Create the namespace and Secret.
The worker reads its secret material from a Kubernetes Secret you create. The chart looks up fixed keys —
install-tokenandcustomer-postgres-dsn— so use those key names, not the environment-variable names:Terminal window kubectl create namespace instruction-hub \--dry-run=client -o yaml | kubectl apply -f -printf "Worker install token: "read -r -s INSTALL_TOKENprintf "\nPostgres DSN: "read -r -s CUSTOMER_POSTGRES_DSNprintf "\n"kubectl --namespace instruction-hub create secret generic instruction-hub-worker-env \--from-literal=install-token="$INSTALL_TOKEN" \--from-literal=customer-postgres-dsn="$CUSTOMER_POSTGRES_DSN" \--dry-run=client -o yaml | kubectl apply -f -unset INSTALL_TOKENunset CUSTOMER_POSTGRES_DSNKeep both values only in the Secret — the worker uses them at runtime. When you enable analysis, add the
analysis-model-api-keyandanalysis-repository-tokenkeys to the same Secret. Do not commit any of these values to source control. -
Write your values file.
Create a
values.yamlwith the settings specific to your cluster. Point the chart at your existing Secret withsecrets.existingSecretName, and note thatgateway.hostsandgateway.tlsare lists:values.yaml secrets:existingSecretName: instruction-hub-worker-env# Each *Key maps a worker secret to a key in the Secret above.installTokenKey: install-tokencustomerPostgresDsnKey: customer-postgres-dsn# Non-secret required settings live under instructionHub.*instructionHub:runtimeBaseUrl: https://runtime.gopromptless.aideploymentName: prod-us-eastdeploymentInstanceId: <deployment-instance-id>configHash: <config-hash>traceObjectS3Bucket: my-org-instruction-hub-traces# Analysis settings live under instructionHub.analysis.*analysis:activationAt: "2026-07-29T00:00:00Z"modelApi:provider: openaimodel: gpt-5.6-sol# On EKS, annotate the ServiceAccount for IRSA:serviceAccount:annotations:eks.amazonaws.com/role-arn: arn:aws:iam::<account-id>:role/instruction-hub-workergateway:enabled: trueclassName: nginxhosts:- host: traces.example.comtls:- secretName: instruction-hub-worker-tlshosts: [traces.example.com]resources:requests:cpu: 500mmemory: 1Gilimits:memory: 2GiReplace the role ARN, hostname, and TLS Secret with values for your environment. The chart exposes a typed values key for every worker setting. There is no generic
envorenvFromkey, so you cannot inject arbitrary environment variables. Each setting lives in a fixed place in the values tree:- The worker’s non-secret required configuration lives directly under
instructionHub.*:runtimeBaseUrl,deploymentName,deploymentInstanceId,configHash, andtraceObjectS3Bucket. - Analysis settings live under
instructionHub.analysis.*:quietWindowHoursandactivationAtsit directly underanalysis, the provider, authentication, base URL, and model settings underinstructionHub.analysis.modelApi.*, and the repository and mirror settings underinstructionHub.analysis.repository.*. - Observability lives under
observability.datadog.*andobservability.sentry.*.
The example above shows one required setting and one analysis setting as the pattern; see the Configuration reference for the complete variable list.
The four secret values (the install token, Postgres DSN, analysis model API key, and analysis repository token) plus the Sentry DSN never go in
values.yaml. The chart reads those four values from the Kubernetes Secret named bysecrets.existingSecretName, mapping eachsecrets.*Keyvalue to the matching Secret key. The Sentry DSN is read separately, from the Secret named byobservability.sentry.existingSecretNameusing the key set inobservability.sentry.dsnKey(defaultSENTRY_DSN); see the Observability page.The
serviceAccountannotation shown is the AWS/EKS path. On EKS, annotate the ServiceAccount for IRSA so the worker assumes the IAM role that grants bucket access. Thegatewayblock renders a standard Kubernetes Ingress (networking.k8s.io/v1Ingress), so a compatible ingress controller must already run in the cluster, andgateway.classNamesets the IngressClass. If another ingress or gateway already routes traffic to Kubernetes services, leavegateway.enabledoff and route it to the worker Service on port 8080. - The worker’s non-secret required configuration lives directly under
-
Install the chart.
Install the chart directly from the directory Promptless provided:
Terminal window helm upgrade --install instruction-hub-worker \./instruction-hub-worker \--namespace instruction-hub \--values values.yaml \--atomic \--wait \--timeout 10mThe chart runs its database migration Job as a pre-install and pre-upgrade hook, before the worker starts. With
--atomic, a failed migration or readiness check rolls the release back instead of leaving a partial installation. -
Confirm the Deployment is available.
Terminal window kubectl wait --namespace instruction-hub \--for=condition=available deployment/instruction-hub-worker \--timeout=5mThe worker exposes
/healthzliveness and readiness probes, so a pod only reports available once it has started and can reach its dependencies and hosted Promptless. -
Test the host-facing endpoint.
From a machine on the same network as your agent hosts, check the worker’s health endpoint:
Terminal window curl --fail --silent --show-error \https://traces.example.com/healthzReplace the example hostname with your worker hostname. This confirms that DNS, TLS, and routing work from the network where hosts run. If the gateway is off, target the worker Service on port 8080 from inside the cluster instead.
The worker is ready when its Deployment reports available and its host-facing /healthz endpoint responds. Next, enroll a host and confirm that its first new session appears.
Enable trace analysis
Section titled “Enable trace analysis”Installation proves that trace ingestion and storage work. To run the Friction Analyzer, add the INSTRUCTION_HUB_ANALYSIS_* settings for:
- The model provider and endpoint that receive trace-derived analysis input.
- The analysis model and its credentials.
- The Instruction Hub repository and repository-scoped token.
- The quiet window after which a session is eligible for analysis.
Add the API key under the analysis-model-api-key key and the repository token under analysis-repository-token in the existing Secret. Put the non-sensitive analysis settings in values.yaml, then rerun the same helm upgrade --install command. For a private Instruction Hub repository, set instructionHub.analysis.repository.tokenSecretEnabled: true so the chart wires the analysis-repository-token Secret key into the worker. See the Configuration reference for every setting.
Manage the deployment with GitOps
Section titled “Manage the deployment with GitOps”For a GitOps-managed cluster:
- Commit your non-sensitive
values.yamland pin the chart version rather than tracking a moving one. - Create
instruction-hub-worker-envthrough your existing External Secrets, Sealed Secrets, or equivalent controller. - Preserve Postgres and S3 independently of the Helm release, and back them up under your normal policies.
- Test an upgrade in a staging deployment before applying it to production.
Troubleshoot installation
Section titled “Troubleshoot installation”The pod fails to start
Section titled “The pod fails to start”The worker validates its configuration at boot. A missing or malformed required setting raises during startup and crashes the process uncaught, so the pod fails to start rather than degrading gracefully. Check the pod’s logs for the startup error, then confirm every required setting and Secret key is present:
kubectl logs --namespace instruction-hub \ --selector app.kubernetes.io/name=instruction-hub-worker \ --since=15mConfirm the Secret carries the install-token and customer-postgres-dsn keys and that secrets.existingSecretName names it.
The migration job fails
Section titled “The migration job fails”Review the migration logs and confirm that the database is reachable and that the Postgres DSN, credentials, network path, and database permissions are correct:
kubectl logs --namespace instruction-hub \ --selector app.kubernetes.io/component=migrationThe pod restarts after running
Section titled “The pod restarts after running”If the worker’s periodic sync with hosted Promptless stops, /healthz fails and Kubernetes replaces the pod. Confirm outbound HTTPS access to the runtime URL and that the install token is still valid. If the token was rotated, update instruction-hub-worker-env and restart the Deployment.
Hosts cannot reach the worker
Section titled “Hosts cannot reach the worker”Run the health check from a host network, then inspect the ingress or gateway address and certificate:
kubectl get service,ingress --namespace instruction-hubIf the deployment still fails, send the worker logs to help@gopromptless.ai. Do not send Secret manifests, tokens, database connection strings, or model credentials.
Remove the worker
Section titled “Remove the worker”Uninstall the Helm release:
helm uninstall instruction-hub-worker --namespace instruction-hubThe uninstall removes chart-managed Kubernetes resources. It does not delete your Postgres database, S3 objects, or hosted deployment history. Delete those separately, and only when your retention policy allows it.