The local backend uses Docker Compose v2 with
up --wait support. The kubernetes backend uses kubectl against an existing context and namespace, including K3s. Configure registry access, cluster networking, TLS, and external database firewall rules in your deployment environment.
Enable deployment
Deployment is disabled by default. Set the process environment flag before starting Studio or running any provision command:provision from its normal help. All provision operations, including initialization, previews, status, history, and rollback, require the flag. Direct Python provisioning and the Go deployment pipeline require it too, including harnest-runtime dry runs. Only true enables the feature, ignoring case and surrounding whitespace; missing, false, and other values keep it off.
Restart Studio after changing the environment. Unset the flag or set it to false to disable deployment again. This does not stop existing workloads or delete deployment history. Building, testing, and serving agents locally remain available.
Configure a deployment
Create a starter from your project folder:harnest-deployment.yaml. This file is separate from the agent’s config.yaml and any template-generated docker-compose.yml. Existing template service declarations continue to generate Compose files without starting services. Provisioner declarations retain the provides environment-binding convention and explicitly declare lifecycle behavior.
harnest-deployment.yaml
docker buildx imagetools inspect), which requires registry access but not a running Docker daemon. An explicit image@sha256:<digest> needs no registry lookup by the provisioner. Pull or rebuild a local tag before Apply when you want to deploy its updated contents.
Set secret values in the provisioner’s environment, or in the environment of the Builder process when launching from Studio. {secret: DATABASE_URL} resolves that variable only when applying. A literal URL also works for non-sensitive endpoints. Use provides: {DATABASE_URL: {secret: DATABASE_URL}} instead of url and variable when a service supplies multiple bindings.
depends_on injects the selected services’ provides bindings into that container. It does not configure a Harnest storage implementation automatically. Your agent’s lifecycle must consume those environment variables using its chosen storage backend. A locally served agent outside Compose uses the loopback published port and its own environment settings.Apply and inspect
--project /path/to/agent and --environment local. A plan displays images, component ownership, dependency names, and environment variable names without displaying connection values. Apply resolves required credentials before touching infrastructure and waits for provisioned dependencies to become healthy before their consumers become ready.
In the standalone Agent Builder, click Deploy. If no manifest exists, complete Configure deployment, review the generated source proposal, and apply it. Open Deploy again to review agent images, services, and the selected environment. Resolve any missing environment variables, then choose Deploy agent or Deploy update. Building agent source does not build the container image: make that image available to Docker or your cluster first.
The deployment screen stays open while workloads start and readiness checks run. A successful plan is only a configuration review; Deployment is running means the backend has confirmed readiness. Refresh status checks the deployed workloads again. Errors appear in the deployment screen, with full command output retained in the terminal.
Under Access your agent, each agent has its own connection details. Published local ports show a loopback endpoint and a copy button; ports named http or https also have Open agent endpoint. Unpublished local ports are labelled internal with instructions to publish them. Kubernetes agents show a copyable kubectl port-forward command scoped to the configured context and namespace. Run it on your computer and keep it running before opening the local endpoint. This does not create public ingress. Routes and authentication depend on the deployed image.
Access details shown before deployment are labelled as planned. Once running, they come from the recorded deployment revision, even if you subsequently edit the manifest. The CLI plan, apply, and status results expose these details in access within their deployment summary.
Closing a browser tab does not stop deployed containers. Closing the Builder process cancels an in-progress CLI command; rerun Apply to reconcile an interrupted deployment. Expand Manage deployment for separate stop and remove actions; persistent volumes and connected external services are retained.
Status reports live readiness separately from the recorded outcome of the last operation. Backend errors omit tool output that might contain credentials; use Docker or kubectl to inspect image pulls, probes, and application logs.
Use external services in production
Add an environment overlay to the same manifest:local; other environment names must be declared.
Kubernetes ports create internal ClusterIP Services. publish applies only to local Compose and binds to loopback. Use your cluster’s ingress, gateway, or port forwarding to expose agent endpoints. External endpoints must already be reachable from the pods. connect does not create a managed-provider account, database, or firewall rule and does not run an external service health check.
Multi-agent applications and custom images
Add each independently deployable agent underagents. Agents can depend on other agents, and their environment can reference ${agents.worker.host} or ${agents.worker.ports.http}. Service references use ${services.cache.host} and ${services.cache.ports.redis}. References resolve to backend-specific internal DNS names.
Each agent image receives its own Deployment on Kubernetes. In-process SubAgents remain inside their parent image; separate images need explicit network communication, such as A2A. Set replicas for agents that use shared external state. Fixed local published ports and single-writer volumes require one replica.
Use mode: provision with any suitable image for a custom service. type is a descriptive label; Harnest does not infer an image’s ports, credentials, initialization, or storage settings. Declare an exec healthcheck.command for every provisioned component. The probe executable must exist in its image. Optional command replaces the image’s default arguments on both backends.
Ownership and recovery
Harnest stores current ownership and revision history in a privaterevisions.sqlite3 database under .harnest/provisioner/<environment>/. Keep it with the project while a deployment is active. Earlier state.json ownership journals are imported automatically; they cannot provide rollback snapshots for deployments made before revision tracking. Resource names include a project-specific identity. Moving the project changes that identity, so remove its existing deployment before moving it or manage migration explicitly.
Apply can be retried after a partial failure. A failed readiness check leaves resources in place for inspection. Stop and Remove use the recorded target and inventory even if the manifest changes or is deleted. Remove the existing deployment before changing its name, Kubernetes context, namespace, or backend within the same environment.
Remove preserves database data. Local named volumes and Kubernetes PVCs remain, along with all externally managed services and the namespace. Switching a provisioned service to connect removes its old workloads after a successful apply but retains its volume. Delete retained data through the backend explicitly when it is no longer needed. Retained volumes are not backups; configure backup and recovery separately for databases you operate.
Deployment versions and rollback
Every Apply creates a monotonically numbered revision for the selected environment. You can also add a human-readablerelease label to the manifest, such as release: "2026.09.20". The manifest’s version: 1 remains its configuration format version.
next_before cursor for the next page. The status response distinguishes the active successful revision from the most recent attempted revision. A failed attempt never advances the active pointer; partially applied workloads remain visible through live status.
Rollback deploys the saved configuration and image identities as a new revision linked to the selected successful revision. It restores the full agent group and reconciles non-persistent dependencies, including removal of workloads added since that revision. Editing or deleting the current manifest does not change a recorded snapshot. Plan with --revision previews the same rollback checks without changing infrastructure. Rollback does not rewrite your current manifest; a later Apply deploys that manifest again.
In Deploy, expand Deployment history and choose Review rollback beside a successful revision. Review its saved configuration, then select Roll back to revision to apply it. Older revisions are loaded in pages. Revision identity is also recorded in Docker container labels and Kubernetes resource annotations. Agent pods carry their deployment revision; an unchanged persistent database is not restarted merely to change this marker.
Snapshots retain authored configuration, including literal values, but never resolved values from
{secret: VARIABLE} references. Use secret references for credentials. Rollback resolves those references from the current provisioner environment, so credential rotation is preserved. History responses expose metadata rather than snapshot contents. Retain local image IDs or registry digests for as long as you need to roll back to them.