Skip to content

For the complete documentation index, see llms.txt.

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.

Hosted PromptlessYour infrastructure
Deployment registration, configuration sync, and host credential introspectionThe worker Deployment and its Kubernetes credentials
Trace metadata, findings, and remediation workflowRaw traces and canonical trace objects in your S3 bucket and Postgres database
Deployment and analysis statusTrace 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.

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 kubectl installed locally, with kubectl connected 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:

SourceDestinationPortPurpose
Enrolled hostsWorker hostname443Enrollment, check-ins, and trace uploads
WorkerHosted Promptless Runtime443Configuration sync, credential introspection, and findings
WorkerPostgres5432Trace and host metadata
WorkerS3443Raw and canonical trace objects
WorkerYour model provider443Trace analysis, once analysis is enabled
Cluster nodesPromptless container registry443Worker image pull

Confirm the target cluster before continuing:

Terminal window
kubectl config current-context
  1. Create the namespace and Secret.

    The worker reads its secret material from a Kubernetes Secret you create. The chart looks up fixed keys — install-token and customer-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_TOKEN
    printf "\nPostgres DSN: "
    read -r -s CUSTOMER_POSTGRES_DSN
    printf "\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_TOKEN
    unset CUSTOMER_POSTGRES_DSN

    Keep both values only in the Secret — the worker uses them at runtime. When you enable analysis, add the analysis-model-api-key and analysis-repository-token keys to the same Secret. Do not commit any of these values to source control.

  2. Write your values file.

    Create a values.yaml with the settings specific to your cluster. Point the chart at your existing Secret with secrets.existingSecretName, and note that gateway.hosts and gateway.tls are lists:

    values.yaml
    secrets:
    existingSecretName: instruction-hub-worker-env
    # Each *Key maps a worker secret to a key in the Secret above.
    installTokenKey: install-token
    customerPostgresDsnKey: customer-postgres-dsn
    # Non-secret required settings live under instructionHub.*
    instructionHub:
    runtimeBaseUrl: https://runtime.gopromptless.ai
    deploymentName: prod-us-east
    deploymentInstanceId: <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: openai
    model: 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-worker
    gateway:
    enabled: true
    className: nginx
    hosts:
    - host: traces.example.com
    tls:
    - secretName: instruction-hub-worker-tls
    hosts: [traces.example.com]
    resources:
    requests:
    cpu: 500m
    memory: 1Gi
    limits:
    memory: 2Gi

    Replace 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 env or envFrom key, 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, and traceObjectS3Bucket.
    • Analysis settings live under instructionHub.analysis.*: quietWindowHours and activationAt sit directly under analysis, the provider, authentication, base URL, and model settings under instructionHub.analysis.modelApi.*, and the repository and mirror settings under instructionHub.analysis.repository.*.
    • Observability lives under observability.datadog.* and observability.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 by secrets.existingSecretName, mapping each secrets.*Key value to the matching Secret key. The Sentry DSN is read separately, from the Secret named by observability.sentry.existingSecretName using the key set in observability.sentry.dsnKey (default SENTRY_DSN); see the Observability page.

    The serviceAccount annotation shown is the AWS/EKS path. On EKS, annotate the ServiceAccount for IRSA so the worker assumes the IAM role that grants bucket access. The gateway block renders a standard Kubernetes Ingress (networking.k8s.io/v1 Ingress), so a compatible ingress controller must already run in the cluster, and gateway.className sets the IngressClass. If another ingress or gateway already routes traffic to Kubernetes services, leave gateway.enabled off and route it to the worker Service on port 8080.

  3. 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 10m

    The 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.

  4. Confirm the Deployment is available.

    Terminal window
    kubectl wait --namespace instruction-hub \
    --for=condition=available deployment/instruction-hub-worker \
    --timeout=5m

    The worker exposes /healthz liveness and readiness probes, so a pod only reports available once it has started and can reach its dependencies and hosted Promptless.

  5. 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/healthz

    Replace 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.

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.

For a GitOps-managed cluster:

  • Commit your non-sensitive values.yaml and pin the chart version rather than tracking a moving one.
  • Create instruction-hub-worker-env through 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.

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:

Terminal window
kubectl logs --namespace instruction-hub \
--selector app.kubernetes.io/name=instruction-hub-worker \
--since=15m

Confirm the Secret carries the install-token and customer-postgres-dsn keys and that secrets.existingSecretName names it.

Review the migration logs and confirm that the database is reachable and that the Postgres DSN, credentials, network path, and database permissions are correct:

Terminal window
kubectl logs --namespace instruction-hub \
--selector app.kubernetes.io/component=migration

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.

Run the health check from a host network, then inspect the ingress or gateway address and certificate:

Terminal window
kubectl get service,ingress --namespace instruction-hub

If the deployment still fails, send the worker logs to help@gopromptless.ai. Do not send Secret manifests, tokens, database connection strings, or model credentials.

Uninstall the Helm release:

Terminal window
helm uninstall instruction-hub-worker --namespace instruction-hub

The 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.