Skip to main content
Deploy agent images with backing services, or connect them to existing endpoints. Environment overrides let you use different service arrangements locally and in production. 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:
The flag gates every provisioning interface, including previews, status, and rollback. Only true enables it; case and surrounding whitespace are ignored. Restart Studio after changing the flag. Disabling it leaves existing workloads and history intact. Local build, test, and serve commands remain available.

Configure a deployment

Create a starter from your project folder:
Edit harnest-deployment.yaml. It is separate from agent configuration and template-generated Compose files.
harnest-deployment.yaml
Supply built images; the provisioner does not build or publish them. Apply pins local tags to image IDs and Kubernetes tags to registry digests. Kubernetes resolution needs Docker Buildx and registry access, but no daemon. Digest-pinned images skip lookup. Pull or rebuild a local tag before applying an update. 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

Each command accepts --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:
Switching a service’s mode replaces its entire declaration. Image, storage, and health-check settings from the provisioned service do not carry over into connect mode. Other overlay mappings merge recursively; lists replace their previous values. The default environment is local; other environment names must be declared. Kubernetes ports are internal ClusterIP Services; use ingress or a gateway for public access. Local publish binds to loopback. Connected services must already be reachable; Harnest neither provisions nor health-checks them.

Multi-agent applications and custom images

Add each independently deployable agent under agents. 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. See the deployment component reference for environment bindings, ports, probes, persistence, resources, and replicas.

Ownership and recovery

Keep .harnest/provisioner/<environment>/revisions.sqlite3 with an active deployment. Moving the project changes its resource identity, so remove the deployment first or plan a migration. Imported legacy journals do not provide historical rollback snapshots. 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-readable release label to the manifest, such as release: "2026.09.20". The manifest’s version: 1 remains its configuration format version.
History lists revisions newest first, with outcomes, configuration and image identities, and a pagination cursor. Status separates the active successful revision from the latest attempt; failures do not advance the active revision. Rollback creates a new revision from a successful saved configuration and image set, reconciling the full agent group. It does not edit your manifest; a later Apply uses that manifest again. Preview with --revision. In Deploy → Deployment history, choose Review rollback, inspect the configuration, then Roll back to revision. Container labels and Kubernetes annotations identify revisions.
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.
Rollback does not restore database contents, revert migrations, or downgrade a persistent backing service. It rejects changes to a persistent service’s image, mount, or other declaration; reconcile database compatibility explicitly before rolling back across such a change. Volumes remain retained. Use backward-compatible database migrations when deploying agents that may need to roll back. History survives restarts and removal. Stop retains the active revision; Remove clears it but preserves history and volumes. After interruption, inspect live state before retrying or rolling back.

Deploy an existing agent with Hostlier

The optional hostlier-harnest package supplies Hostlier’s local project-plan and project-package hooks. Start in the agent directory created by harnest init. Install the package executable built for the CLI machine. Select the agent’s Linux target separately.
Use a Hostlier CLI with project hook support. From a Harnest source checkout, build the package with go build -o /tmp/hostlier-harnest ./cmd/hostlier-harnest. Put the deployment in one .hostlier file. The add command enrolls Harnest under packages.harnest. Put its build settings there. Hostlier runs the hooks of packages explicitly enrolled in the project. Replace the example digest with a compatible Linux base image digest. This example provisions Redis and connects a dedicated sandbox Docker daemon over mutually authenticated TLS.
.hostlier
On a Linux builder matching the target architecture, run harnest compile . --format executable --output .harnest/build/support-agent. Copy the embedded executable to the declared path when deploying from another platform. On matching Linux, omit artifact to compile during packaging. Older projects can still use harnest-hostlier.yaml. Inline settings take precedence. Add a stored secret reference or dependency output for each spec.secrets environment variable in the agent config. Supply model credentials and the agent’s HTTP authentication policy for the intended audience. The local plan checks explicitly required binding names without importing agent code. Keep configuration values public and place credentials in Hostlier’s secret store.
The package verifies the executable and embedded runtime for the selected platform and hands Hostlier a container context. Hostlier owns provisioning, secret injection, deployment review and rollout.

Use Redis as a KV cache

Install Harnest’s redis extra in the agent environment. Register a named store in the lifecycle.
lifecycle/cache.py
Within an invocation, use cache = context.storage("cache", RedisCache), then await cache.set("summary", b"done", ttl_seconds=300) and await cache.get("summary"). Values are bytes. A miss returns None. Keys are scoped by application and invocation user. For an existing Redis workflow that creates a prefix-restricted ACL, bind both CACHE_URL and CACHE_KEY_PREFIX to the Redis step’s url and keyPrefix outputs. Use dedicated session and checkpoint storage for resumable state.

Connect a sandbox

Install the official Docker extension into the project. Declare the execution image that is available on the dedicated daemon. Omit base_url so the extension uses the Docker connection and certificate bindings above.
sandbox/calculations.py
Assign sandboxes=["calculations"] to the agent that needs it. An authored tool can then call await context.sandboxes["calculations"].aexecute("print(6 * 7)"). The Docker provider starts an isolated execution container on the dedicated daemon and applies the declared policy. Keep the Hostlier deployment daemon separate. See named sandbox assignments and tools. Other providers can consume a private runner endpoint from bindings and its scoped token from secrets. Register the provider in the project’s named sandbox and list the required environment names in packages.harnest.requiredBindings. Hostlier checks and supplies the deployment resources. The selected provider enforces isolation and cleanup.