# CLAUDE Source: https://docs.usechamber.io/CLAUDE # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is the documentation repository for Chamber, a GPU capacity control plane for enterprise AI infrastructure. It uses Mintlify as the documentation framework with MDX formatting. * **Product**: Chamber ([https://usechamber.com](https://usechamber.com)) * **Dashboard**: [https://app.usechamber.io](https://app.usechamber.io) * **Framework**: Mintlify (MDX-based documentation) ## Development Commands ```bash theme={null} # Install Mintlify CLI (one-time setup) npm i -g mintlify # Start local development server with hot reload mintlify dev # View at http://localhost:3000 ``` ## Deployment Changes pushed to `main` are automatically deployed via Mintlify's GitHub integration. No manual build step required. ## Architecture ### Content Organization * `concepts/` - Core concepts (teams, capacity pools, reservations, workload classes, scheduling) * `platform/` - Platform UI guides (dashboard, team management, capacity management, workloads) * `agent/` - Kubernetes agent documentation (installation, troubleshooting, upgrading) * `api-reference/` - API documentation * `cli/` - CLI documentation ### Configuration * `docs.json` - Main Mintlify config (navigation structure, theme, colors, navbar) * Navigation is defined in `docs.json` under `navigation.tabs` ### Adding New Pages 1. Create `.mdx` file in appropriate directory 2. Add frontmatter with `title` and `description` 3. Add page path to `docs.json` navigation section ## MDX Components Available Mintlify components for documentation pages: ```mdx theme={null} Content ... Content Content Hidden content Tip text Info text Warning text Note text ``` ## Frontmatter Format Every `.mdx` page requires: ```mdx theme={null} --- title: "Page Title" description: "Brief description of the page content" --- ``` # Installation Source: https://docs.usechamber.io/agent/installation Install the Chamber agent in your Kubernetes cluster This guide covers installing the Chamber agent using Helm. For a guided setup experience, use the [installation wizard](https://app.usechamber.io/pools/new) in the Chamber dashboard. This guide installs only the Chamber agent on an **existing** Kubernetes cluster. To deploy a complete GPU-ready cluster (VPC, Kubernetes, GPU autoscaling, GPU drivers, and the Chamber agent), see [Cluster Deployment](/cluster-deployment/overview). ## Prerequisites Before installing, ensure you have: Verify with `kubectl version`. The agent supports Kubernetes 1.24 and later. Verify with `helm version`. Install from [helm.sh](https://helm.sh/docs/intro/install/) if needed. Nodes must have NVIDIA drivers installed. Verify with `nvidia-smi` on GPU nodes. The [NVIDIA device plugin](https://github.com/NVIDIA/k8s-device-plugin) must be deployed. Verify: ```bash theme={null} kubectl get pods -n kube-system -l name=nvidia-device-plugin-ds ``` [DCGM-Exporter](https://github.com/NVIDIA/dcgm-exporter) is required for GPU metrics collection. Verify: ```bash theme={null} kubectl get pods -n gpu-operator -l app=nvidia-dcgm-exporter ``` If not installed, deploy via the [NVIDIA GPU Operator](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/index.html) or standalone: ```bash theme={null} helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm install dcgm-exporter nvidia/dcgm-exporter -n gpu-operator --create-namespace ``` For the GPU Usage metric, DCGM profiling metrics must be enabled. See [GPU Usage Metric Not Available](/agent/troubleshooting#gpu-usage-metric-not-available) for configuration steps. Get this from the Chamber dashboard (see below). ## Quick Install ```bash theme={null} # Install the agent (OCI registry - no helm repo add needed) helm install chamber-agent oci://public.ecr.aws/chamber/chamber-agent-chart \ --version 0.8.96 \ --namespace chamber-system \ --create-namespace \ --set saas.url="wss://controlplane-api.usechamber.io/agent" \ --set saas.token="" \ --set saas.clusterId="your-gpu-cluster" ``` Your cluster will appear in the Chamber dashboard within **30 seconds**. Always specify `--version` to ensure reproducible deployments. Check the [releases page](https://github.com/ChamberOrg/chamber-agent/releases) for the latest version. ## Getting a Cluster Token Go to [app.usechamber.io](https://app.usechamber.io) and sign in. Click **Settings** in the sidebar, then **Security** tab. Click **New Token**, give it a name, and copy immediately. Store your token securely. It's only shown once and cannot be retrieved later. ## Verifying Installation ### Check Pod Status ```bash theme={null} kubectl get pods -n chamber-system -l app.kubernetes.io/name=chamber-agent ``` Expected output: ``` NAME READY STATUS RESTARTS AGE chamber-agent-5d4f6b7c8d-abc12 1/1 Running 0 30s ``` ### Check Logs ```bash theme={null} kubectl logs -n chamber-system -l app.kubernetes.io/name=chamber-agent --tail=20 ``` Look for: ``` INFO WebSocket connected successfully INFO Metadata collected: 4 nodes, 32 GPUs ``` ### Check Version ```bash theme={null} helm list -n chamber-system ``` Shows the installed chart version and app version. ### Verify in Dashboard Within 30 seconds of installation: 1. Go to [app.usechamber.io](https://app.usechamber.io) 2. Navigate to **Capacity Pools** 3. Your cluster should appear with the correct GPU count If GPUs show as 0, verify the NVIDIA device plugin is running and nodes have `nvidia.com/gpu` resources. ## Network Requirements The agent requires outbound HTTPS access to: | Host | Port | Purpose | | -------------------------------- | ---- | --------------------------- | | `controlplane-api.usechamber.io` | 443 | Control plane communication | The agent only makes **outbound** connections. No inbound firewall rules are required. ## Uninstalling ```bash theme={null} helm uninstall chamber-agent -n chamber-system ``` Uninstalling disconnects your cluster from Chamber. Running workloads will continue to completion but won't be tracked. ## Next Steps Common issues and solutions Upgrade to the latest version # Agent Overview Source: https://docs.usechamber.io/agent/overview Understanding the Chamber Kubernetes agent The Chamber agent is a lightweight Kubernetes controller that connects your GPU clusters to Chamber. ## What the Agent Does The agent runs in your Kubernetes cluster and: Discovers GPU nodes and reports capacity to Chamber Creates and monitors GPU workloads on your cluster Gathers GPU utilization for dashboards Implements scheduling decisions from Chamber ## Architecture ```mermaid theme={null} flowchart LR subgraph cluster["Your Kubernetes Cluster"] Agent["Chamber Agent"] GPU1["GPU Nodes"] end Agent -->|Secure connection\n outbound only| Chamber["Chamber"] Agent --> GPU1 ``` The agent maintains a secure connection to Chamber and executes scheduling decisions locally. ## Resilience **Workloads continue running even if Chamber is temporarily unavailable.** The agent operates independently once workloads are scheduled. If the connection is lost, running workloads are unaffected and the agent automatically reconnects. ## Communication ### Outbound Only The agent only makes **outbound** connections: * No inbound ports required * Works behind corporate firewalls * Encrypted with TLS ### Network Requirements | Host | Port | Purpose | | ----------------- | ---- | --------------------- | | `*.usechamber.io` | 443 | Chamber communication | ## Resource Requirements | Resource | Requirement | | -------- | -------------------------- | | CPU | 100m request, 200m limit | | Memory | 128Mi request, 256Mi limit | The agent has a minimal footprint. These defaults work for most clusters. ## Security ### Permissions The agent requires these Kubernetes permissions: ```yaml theme={null} rules: # Core resources - read cluster state - apiGroups: [""] resources: ["nodes", "pods", "namespaces", "events"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["services", "endpoints"] # DCGM-Exporter discovery verbs: ["get", "list"] # Workload management - apiGroups: ["batch"] resources: ["jobs"] verbs: ["create", "delete", "get", "list", "watch"] # Metrics - apiGroups: ["metrics.k8s.io"] resources: ["pods", "nodes"] verbs: ["get", "list"] - apiGroups: ["scheduling.run.ai"] resources: ["queues", "podgroups"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] ``` The agent does **not** require cluster-admin. Permissions are scoped to GPU workload management. ### Data Sent to Chamber | Data | Purpose | | --------------------------------------------- | ------------------------ | | Node inventory (GPU count, type) | Capacity tracking | | Workload metadata (name, status, GPU request) | Workload management | | GPU utilization metrics | Dashboards and reporting | The agent does **not** send container logs, environment variables, or secrets. ## Next Steps Install the agent via Helm Common issues and solutions Deploy a full GPU cluster with Terraform # Configuration Source: https://docs.usechamber.io/agent/standalone/configuration Environment variables, workload labels, upgrading, and uninstalling the Standalone Agent The Standalone Agent is in **beta**. Configuration options may change. The agent is configured via environment variables in `/etc/chamber/agent.env`. After making changes, restart the agent: ```bash theme={null} sudo vi /etc/chamber/agent.env sudo systemctl restart chamber-agent-standalone ``` ## Required Settings | Variable | Description | | ----------------------- | ---------------------------------------------------------------------------------------------------- | | `CHAMBER_CLUSTER_TOKEN` | API token for authenticating with the Chamber control plane. Generated in **Settings > API Tokens**. | The `CHAMBER_SAAS_URL` is set automatically by the installer and should not need to be changed. ## Common Settings | Variable | Default | Description | | -------------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `CHAMBER_CLUSTER_ID` | hostname | Identifier for this host in the Chamber dashboard. Set this to a human-readable name if the hostname is opaque (e.g., `ip-10-0-1-42`). | | `CHAMBER_HOSTNAME` | hostname | Override the reported hostname. | | `CHAMBER_DCGM_URL` | `http://localhost:9400/metrics` | DCGM Exporter endpoint. Change if running DCGM Exporter on a non-default port. | ## Metrics Settings | Variable | Default | Description | | ------------------------------------- | -------- | --------------------------------------------------- | | `CHAMBER_METRICS_ENABLED` | `true` | Enable or disable all metric collection. | | `CHAMBER_METRICS_COLLECTION_INTERVAL` | `30` | Seconds between metric collection cycles. | | `CHAMBER_METRICS_BATCH_INTERVAL` | `60` | Seconds between batch uploads to Chamber. | | `CHAMBER_METRICS_BUFFER_SIZE` | `100000` | Maximum metrics buffered before oldest are dropped. | ## GPU Usage Settings | Variable | Default | Description | | ----------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | `CHAMBER_GPU_USAGE_ENABLED` | `true` | Enable or disable the composite GPU Usage metric. | | `CHAMBER_GPU_USAGE_POWER_THRESHOLD` | `0.1` | Power ratio (0.0–1.0) below which GPU is considered idle. At the default, GPUs drawing less than 10% of their power limit report GPU Usage as 0. | ## Discovery Settings | Variable | Default | Description | | --------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------- | | `CHAMBER_DISCOVERY_ENABLED` | `true` | Enable or disable automatic GPU workload discovery. | | `CHAMBER_DISCOVERY_SCAN_INTERVAL` | `15` | Seconds between GPU process scans. | | `CHAMBER_DISCOVERY_STABILIZATION_DELAY` | `5` | Seconds to wait before classifying a newly detected process. Prevents transient processes from appearing as workloads. | | `CHAMBER_DISCOVERY_EVENT_BUFFER_SIZE` | `500` | Maximum discovery events buffered. | ## OTLP Settings | Variable | Default | Description | | --------------------------------- | --------- | ----------------------------------------- | | `CHAMBER_OTLP_GRPC_ENABLED` | `true` | Enable or disable the OTLP gRPC receiver. | | `CHAMBER_OTLP_GRPC_PORT` | `4317` | gRPC server port. | | `CHAMBER_OTLP_GRPC_HOST` | `0.0.0.0` | gRPC server bind address. | | `CHAMBER_OTLP_METRICS_QUEUE_SIZE` | `10000` | Maximum queued metric batches. | ## Connection Settings | Variable | Default | Description | | ------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------- | | `CHAMBER_HEARTBEAT_INTERVAL` | `30` | Seconds between WebSocket heartbeats. | | `CHAMBER_METADATA_INTERVAL` | `60` | Seconds between host metadata reports. | | `CHAMBER_RECONNECT_BACKOFF` | `5` | Initial reconnection delay (seconds) after a dropped WebSocket connection. | | `CHAMBER_MAX_RECONNECT_BACKOFF` | `30` | Maximum reconnection delay (seconds). The agent uses exponential backoff with jitter between these bounds. | ## Workload Labels Add environment variables to your training jobs to enrich workload metadata in the dashboard: ```bash theme={null} CHAMBER_JOB_NAME="llama2-finetune-v3" \ CHAMBER_TEAM_NAME="ml-platform" \ torchrun --nproc_per_node=4 train.py ``` | Variable | Description | | ------------------- | ------------------------------------------------------------------------------------------ | | `CHAMBER_JOB_NAME` | Override the auto-detected workload name. Useful when the process command line is generic. | | `CHAMBER_TEAM_NAME` | Set a team label for workload attribution. Groups workloads by team in the dashboard. | These environment variables are read from the process environment at discovery time. They are not part of `/etc/chamber/agent.env` — set them on your training process directly. ## Upgrading Re-run the installer to upgrade to the latest version. Your configuration in `/etc/chamber/agent.env` is preserved: ```bash theme={null} curl -fsSL https://chamber-agent-releases.s3.amazonaws.com/install.sh | sudo bash ``` To pin to a specific version (e.g., for reproducibility): ```bash theme={null} curl -fsSL https://chamber-agent-releases.s3.amazonaws.com/install.sh \ | sudo bash -s -- --version ``` ## Uninstalling ```bash theme={null} sudo systemctl stop chamber-agent-standalone sudo systemctl disable chamber-agent-standalone sudo rm /etc/systemd/system/chamber-agent-standalone.service sudo systemctl daemon-reload sudo rm -rf /opt/chamber-standalone sudo rm -rf /etc/chamber sudo userdel chamber-agent ``` This removes the agent, its configuration, and the system user. It does not remove Docker, Python, or DCGM Exporter. ## Next Steps Common issues and solutions Full list of metrics collected # Installation Source: https://docs.usechamber.io/agent/standalone/installation Install the Chamber Standalone Agent on a GPU host The Standalone Agent is in **beta**. Features and configuration may change. This guide covers installing the Chamber Standalone Agent on a Linux GPU host (bare metal, cloud VM, or on-prem server). ## Prerequisites | Requirement | Details | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Chamber account** | Sign up at [app.usechamber.io/signup](https://app.usechamber.io/signup) and contact the Chamber team to enable standalone agent access. Then create an API token from **Settings > API Tokens**. | | **GPU host** | Linux host with one or more NVIDIA GPUs (GCP, AWS, Azure, or bare metal) | | **NVIDIA driver** | Pre-installed on most cloud GPU images. Verify with `nvidia-smi`. | | **Root access** | The installer requires `sudo` | Python 3.11+, Docker, and DCGM Exporter are installed automatically by the installer if not already present. ## Step 1: Get Your Cluster Token Go to [app.usechamber.io](https://app.usechamber.io) and navigate to **Settings**. Click **New Token**, give it a name, and copy the generated token immediately. Store your token securely. It is only shown once and cannot be retrieved later. ## Step 2: Install the Agent SSH into your GPU host and run: ```bash theme={null} curl -fsSL https://chamber-agent-releases.s3.amazonaws.com/install.sh \ | sudo CHAMBER_CLUSTER_TOKEN= bash ``` Replace `` with the token from Step 1. The installer will: * Install Python 3.11+, Docker, and NVIDIA Container Toolkit (if not already present) * Set up DCGM Exporter for GPU profiling metrics * Install and configure the Chamber Standalone Agent * Start the agent as a `systemd` service The full process takes 2–5 minutes depending on what is already installed. ## Step 3: Verify Your host should appear in the Chamber dashboard within 60 seconds. You can also verify locally: ```bash theme={null} # Check service status sudo systemctl status chamber-agent-standalone # View recent logs sudo journalctl -u chamber-agent-standalone --no-pager -n 20 ``` You should see log lines indicating a successful WebSocket connection to the control plane. ### Verify in Dashboard 1. Go to [app.usechamber.io/dashboard?tab=services](https://app.usechamber.io/dashboard?tab=services) 2. Your host should appear with GPU count and metrics flowing If the host doesn't appear within 60 seconds, see [Troubleshooting](/agent/standalone/troubleshooting). ## Common Operations ```bash theme={null} # View live logs sudo journalctl -u chamber-agent-standalone -f # Restart the agent sudo systemctl restart chamber-agent-standalone # Stop the agent sudo systemctl stop chamber-agent-standalone # Check agent version /opt/chamber-standalone/venv/bin/chamber-standalone version # View detected GPU and host info /opt/chamber-standalone/venv/bin/chamber-standalone host-info ``` ## Network Requirements The agent requires outbound HTTPS/WSS access only. No inbound ports need to be opened. | Host | Port | Purpose | | -------------------------------- | ---- | --------------------------------------- | | `controlplane-api.usechamber.io` | 443 | Control plane communication (WebSocket) | If you are running behind a corporate firewall, ensure outbound WebSocket connections to port 443 are allowed. ## Next Steps Understand the metrics collected and what they mean Customize agent behavior with environment variables Send your application metrics to Chamber Common issues and solutions # Metrics Reference Source: https://docs.usechamber.io/agent/standalone/metrics GPU, host, and workload metrics collected by the Standalone Agent and how to use them The Standalone Agent is in **beta**. Metric names and labels may change. The Standalone Agent collects GPU metrics (via DCGM Exporter), host metrics (via psutil), per-process GPU metrics (via NVML), and application-level service metrics (via the built-in OTLP receiver). All metrics are viewable on the **Dashboard > Services** page at [app.usechamber.io/dashboard?tab=services](https://app.usechamber.io/dashboard?tab=services). ## GPU Metrics These metrics are scraped from DCGM Exporter every 30 seconds. ### Core GPU Metrics | Metric | Unit | Description | What to look for | | ---------------------------------------- | ----- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `chamber_gpu_utilization_percent` | % | Percentage of time the GPU had at least one kernel running. | Sustained 0% may indicate idle GPUs wasting capacity. Sustained 100% is normal for training workloads. | | `chamber_gpu_memory_used_bytes` | bytes | GPU memory (VRAM) in use. | Approaching total memory indicates risk of OOM errors. | | `chamber_gpu_memory_utilization_percent` | % | GPU memory in use as a percentage of total. | Above 90% for extended periods suggests memory pressure. | | `chamber_gpu_temperature_celsius` | °C | GPU die temperature. | Consistently above 80°C may indicate thermal throttling. Check airflow and cooling. | | `chamber_gpu_power_usage_watts` | watts | Current power draw. | At or near the power limit can cause power throttling, reducing clock speeds and throughput. | ### GPU Usage (Composite Metric) | Metric | Unit | Description | | ------------------- | ---- | ------------------------------------------------------------ | | `chamber_gpu_usage` | % | A composite metric reflecting actual GPU compute efficiency. | Standard GPU utilization (`chamber_gpu_utilization_percent`) can be misleading — a single-threaded kernel running on 1 of 132 streaming multiprocessors (SMs) still reports 100% utilization. GPU Usage provides a more accurate picture. **How it's calculated:** ``` GPU Usage = max(SM Active, Tensor Active, DRAM Active) × 100 ``` | Input | DCGM Source | What it measures | | ------------- | --------------------------------- | ------------------------------------------------------------- | | SM Active | `DCGM_FI_PROF_SM_ACTIVE` | Fraction of SMs that are actively executing a warp (0.0–1.0) | | Tensor Active | `DCGM_FI_PROF_PIPE_TENSOR_ACTIVE` | Fraction of time the tensor cores are active (0.0–1.0) | | DRAM Active | `DCGM_FI_PROF_DRAM_ACTIVE` | Fraction of time GPU memory (HBM) is being accessed (0.0–1.0) | **Power gate:** If the GPU's power draw is below 10% of its power limit, GPU Usage is reported as 0 regardless of the profiling metrics. This filters out noise from idle GPUs. **Why it matters:** GPU Usage tells you whether your workload is actually keeping the GPU busy. A training job might show 100% standard utilization but only 30% GPU Usage, meaning most SMs are idle and you could optimize kernel launch, batch size, or parallelism. GPU Usage requires DCGM profiling metrics to be enabled. See [Ensuring DCGM Profiling Metrics](#ensuring-dcgm-profiling-metrics-are-collected) below. ### Profiling Metrics These are the raw profiling metrics behind the GPU Usage composite. They are useful for advanced debugging. | Metric | Unit | Description | | ------------------- | --------------- | -------------------------------------------------------------------------------- | | `gpu_sm_active` | ratio (0.0–1.0) | Streaming Multiprocessor activity — fraction of SMs executing at least one warp | | `gpu_tensor_active` | ratio (0.0–1.0) | Tensor core pipeline activity — high during mixed-precision training (FP16/BF16) | | `gpu_dram_active` | ratio (0.0–1.0) | GPU memory (HBM) bus activity — high during data-loading-bound workloads | ## Host Metrics Collected via psutil every 30 seconds. | Metric | Unit | Description | What to look for | | ------------------------------------ | ----- | ---------------------------------- | --------------------------------------------------------------------- | | `chamber_node_cpu_usage_percent` | % | Host CPU utilization | High CPU can bottleneck data loading pipelines, starving GPUs of data | | `chamber_node_cpu_usage_cores` | cores | Number of CPU cores in use (float) | Compare against total cores to gauge headroom | | `chamber_node_cpu_capacity_cores` | cores | Total logical CPU count | — | | `chamber_node_memory_usage_bytes` | bytes | Host memory (RAM) in use | Near capacity can cause OOM kills by the Linux kernel | | `chamber_node_memory_capacity_bytes` | bytes | Total host memory | — | | `chamber_node_memory_usage_percent` | % | Host memory utilization | Above 90% sustained warrants investigation | ## Per-Process GPU Metrics Collected via NVML for each process using a GPU. These are attributed to discovered workloads in the dashboard. | Metric | Unit | Description | | ------------------------------------------------ | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `chamber_gpu_process_memory_bytes` | bytes | GPU memory allocated by a specific process | | `chamber_gpu_process_memory_utilization_percent` | % | Process GPU memory as a percentage of total GPU memory | | `chamber_gpu_process_sm_utilization_percent` | % | Process-level SM utilization (requires NVIDIA driver 450+ and Volta or newer GPUs; the agent skips this metric gracefully on unsupported hardware) | ## Service-Level Metrics In addition to infrastructure metrics, the Standalone Agent tracks **services** — applications running on your GPU hosts that are identified by the `service_name` label. This is what powers the **Services** tab on the dashboard, giving you a per-service view of resource consumption and application health. ### How Services Are Identified The agent associates a `service_name` with metrics through three mechanisms, in priority order: 1. **`OTEL_SERVICE_NAME` environment variable** — If your GPU process has `OTEL_SERVICE_NAME` set, the agent reads it directly and uses it to tag all GPU and per-process metrics for that workload. This is the most reliable method. For Docker containers where the process environment may not be directly readable, the agent automatically falls back to querying the Docker Engine API via `/var/run/docker.sock` to read container environment variables — no configuration needed beyond ensuring the agent user has Docker socket access (the installer handles this by default). 2. **OTLP `service.name` resource attribute** — If your application exports OpenTelemetry metrics to the agent's OTLP receiver (port 4317), the `service.name` resource attribute is extracted and attached to every metric in that export. When exactly one service is actively sending OTLP metrics, the agent also uses it to label GPU infrastructure metrics for the running workload. 3. **Workload discovery** — The agent classifies GPU processes by inspecting command lines and environment variables to identify ML frameworks (PyTorch, TensorFlow, vLLM, etc.) and launchers (torchrun, deepspeed, accelerate). This provides `job_name` and `workload_type` labels even without `OTEL_SERVICE_NAME`. ```bash theme={null} # Option 1: Set on your training process OTEL_SERVICE_NAME="llama2-finetune" torchrun --nproc_per_node=4 train.py # Option 2: Set in your OTel SDK resource (see OTLP Integration page) Resource.create({"service.name": "llama2-finetune"}) ``` ### Application Metrics via OTLP Any metrics your application exports over OpenTelemetry are forwarded to the Chamber dashboard with the `service_name` label. These appear alongside GPU and host metrics on the Services tab, letting you correlate application behavior with infrastructure state. Common examples of application metrics you can send: | Metric | What it tells you | | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------- | | `training_loss` | Whether the model is converging — a sudden spike may indicate a data issue or corrupted checkpoint | | `training_throughput_samples_total` | Samples processed over time — a drop signals a bottleneck (data loading, GPU contention, network) | | `inference_request_duration_seconds` | End-to-end latency per request — rising latency under stable load may point to memory pressure or thermal throttling | | `inference_requests_total` | Request volume — correlate with GPU utilization to understand per-request cost | | `model_load_time_seconds` | Time to load model weights — useful for tracking cold-start performance across deployments | | `batch_queue_depth` | Pending items in your processing queue — growing depth means your GPUs can't keep up with inbound work | These are examples — you can send any metric your application produces. See [OTLP Integration](/agent/standalone/otel-integration) for setup instructions. ### What You See on the Services Dashboard The **Services** tab ([app.usechamber.io/dashboard?tab=services](https://app.usechamber.io/dashboard?tab=services)) groups metrics by `service_name`, giving you a unified view per service: * **GPU utilization and GPU Usage** attributed to each service — see which services are efficiently using their GPUs and which are underutilizing * **GPU memory per service** — identify which service is consuming the most VRAM and whether it's at risk of OOM * **Per-process breakdowns** — drill into individual worker processes within a service (e.g., each rank in a distributed training job) * **Application metrics** — any custom OTLP metrics your service exports, displayed alongside the infrastructure data * **Host CPU and memory** — spot cases where a service is bottlenecked on CPU or host memory rather than GPU This per-service view makes it straightforward to answer questions like: *"Is my training job actually using the GPUs I allocated?"* or *"Why did inference latency spike at 2 PM?"* — without having to cross-reference multiple monitoring systems. For the best experience on the Services dashboard, set `OTEL_SERVICE_NAME` on every GPU process. This ensures GPU metrics are correctly attributed even when multiple services share a host. ## Workload Discovery The agent automatically discovers GPU-using processes and classifies them by framework: * **PyTorch** (including torchrun, torch.distributed) * **DeepSpeed** * **vLLM** * **Other GPU processes** Discovered workloads appear in the dashboard with: * Process name and command line * Framework type * GPU memory usage per process * Lifecycle state (running, terminated) * Duration For distributed training (e.g., `torchrun --nproc_per_node=4`), the agent groups worker processes under a single workload entry. You can enrich workload metadata with environment variables. See [Workload Labels](/agent/standalone/configuration#workload-labels). ## Ensuring DCGM Profiling Metrics Are Collected The GPU Usage metric and profiling metrics (`gpu_sm_active`, `gpu_tensor_active`, `gpu_dram_active`) require DCGM Exporter to expose profiling-level fields. The installer sets this up automatically, but if you are running DCGM Exporter manually or troubleshooting missing metrics, verify the following: ### 1. DCGM Exporter Must Be Running ```bash theme={null} # Check if DCGM Exporter is serving metrics curl -s http://localhost:9400/metrics | head -20 ``` You should see Prometheus-formatted metrics including lines starting with `DCGM_FI_`. If this returns nothing, DCGM Exporter is not running or not reachable. ### 2. Profiling Fields Must Be Enabled DCGM Exporter is configured by a CSV file that lists which fields to export. The profiling fields required are: | DCGM Field ID | Field Name | Required For | | ------------- | --------------------------------- | ------------------------- | | 1001 | `DCGM_FI_PROF_SM_ACTIVE` | GPU Usage (SM Active) | | 1004 | `DCGM_FI_PROF_PIPE_TENSOR_ACTIVE` | GPU Usage (Tensor Active) | | 1005 | `DCGM_FI_PROF_DRAM_ACTIVE` | GPU Usage (DRAM Active) | Verify these fields are in the DCGM Exporter counters file (commonly `/etc/dcgm-exporter/default-counters.csv` or passed via the `-f` flag): ```bash theme={null} # Check if profiling fields are configured grep -E "DCGM_FI_PROF_SM_ACTIVE|DCGM_FI_PROF_PIPE_TENSOR_ACTIVE|DCGM_FI_PROF_DRAM_ACTIVE" \ /etc/dcgm-exporter/default-counters.csv ``` If these entries are missing, add them: ```csv theme={null} DCGM_FI_PROF_SM_ACTIVE, gauge DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge DCGM_FI_PROF_DRAM_ACTIVE, gauge ``` Then restart DCGM Exporter. ### 3. Profiling Must Be Supported by Your GPU DCGM profiling metrics require: * NVIDIA driver 450+ (most modern drivers) * A GPU that supports profiling (Volta, Turing, Ampere, Hopper, Blackwell — i.e., V100, T4, A100, H100, B200, etc.) * No other profiling tool (e.g., Nsight Systems) actively holding a profiling session If profiling metrics are unavailable, the core GPU metrics (utilization, memory, temperature, power) still collect normally. Only the GPU Usage composite metric will be missing. ### 4. Verify Profiling Metrics Are Flowing ```bash theme={null} curl -s http://localhost:9400/metrics | grep DCGM_FI_PROF ``` You should see lines like: ``` DCGM_FI_PROF_SM_ACTIVE{gpu="0",...} 0.45 DCGM_FI_PROF_PIPE_TENSOR_ACTIVE{gpu="0",...} 0.38 DCGM_FI_PROF_DRAM_ACTIVE{gpu="0",...} 0.22 ``` If these lines are absent or all values are 0 while a workload is running, check the troubleshooting steps above. ## Metric Labels All metrics include these standard labels: | Label | Description | | ----------------- | ------------------------------------------------------------- | | `cluster_id` | Identifier for this host (defaults to hostname, configurable) | | `node_name` | Hostname of the machine | | `organization_id` | Your Chamber organization ID | | `managed_by` | Always `external` for standalone agents | GPU metrics additionally include: | Label | Description | | ----------- | ---------------------------------------------- | | `gpu_index` | GPU index (0, 1, 2, ...) | | `gpu_type` | GPU model name (e.g., `NVIDIA A100-SXM4-80GB`) | Process and service metrics additionally include: | Label | Description | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `job_id` | Unique workload identifier | | `job_name` | Workload name (auto-detected or from `CHAMBER_JOB_NAME`) | | `pod_name` | Process identifier (`process:pid-`) | | `team_name` | Team label (from `CHAMBER_TEAM_NAME` or default) | | `service_name` | Service identifier (from `OTEL_SERVICE_NAME` env var or OTLP `service.name` resource attribute). Used to group metrics on the Services dashboard. | ## What to Look For on the Dashboard The **Services** tab ([app.usechamber.io/dashboard?tab=services](https://app.usechamber.io/dashboard?tab=services)) gives you a per-host and per-GPU breakdown. Here are common patterns to watch for: | Pattern | What it means | Action | | -------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | | High utilization but low GPU Usage | Kernels are running but underutilizing the GPU's compute capacity | Profile with Nsight, increase batch size, or check for serialization bottlenecks | | GPU memory near 100% | Risk of OOM errors that crash training | Reduce batch size, enable gradient checkpointing, or use a larger GPU | | High CPU, low GPU utilization | Data loading is the bottleneck — GPUs are starved | Add more DataLoader workers, use faster storage, or pre-process data | | Temperature consistently above 80°C | Thermal throttling may be reducing clock speeds | Check cooling, airflow, or ambient temperature | | Power at limit | Power throttling is reducing clock speeds | Expected under heavy load, but sustained power capping may indicate undersized infrastructure | | GPU idle (0% utilization, 0 GPU Usage) | GPU is allocated but not in use | Check for crashed jobs, queued-but-not-started workloads, or misconfigured resource requests | ## Next Steps Send your own application metrics to Chamber Tune collection intervals and other settings # OTel Integration Source: https://docs.usechamber.io/agent/standalone/otel-integration Send OpenTelemetry metrics from your applications to Chamber via the Standalone Agent The Standalone Agent is in **beta**. OTLP integration behavior may change. The Standalone Agent includes a built-in OpenTelemetry (OTLP) gRPC receiver. Any application instrumented with the OpenTelemetry SDK can send metrics directly to the agent, which forwards them to the Chamber dashboard alongside GPU and host metrics. This lets you correlate application-level metrics (training loss, throughput, queue depth, request latency) with infrastructure metrics in a single view. ## How It Works ```mermaid theme={null} flowchart LR App["Your App
(OTel SDK)"] -->|"gRPC :4317"| Agent["Chamber
Standalone Agent"] Agent -->|batch upload| Chamber["Chamber
Dashboard"] ``` 1. Your application exports OTLP metrics over gRPC to `localhost:4317` 2. The agent receives, transforms, and buffers the metrics 3. Metrics are uploaded to Chamber in batches every 60 seconds 4. They appear on the **Services** dashboard alongside infrastructure metrics ## Configuration The OTLP receiver is **enabled by default** on port 4317. No additional configuration is required for most setups. | Variable | Default | Description | | --------------------------------- | --------- | --------------------------------------------- | | `CHAMBER_OTLP_GRPC_ENABLED` | `true` | Enable or disable the OTLP gRPC receiver | | `CHAMBER_OTLP_GRPC_PORT` | `4317` | Port the gRPC server listens on | | `CHAMBER_OTLP_GRPC_HOST` | `0.0.0.0` | Bind address for the gRPC server | | `CHAMBER_OTLP_METRICS_QUEUE_SIZE` | `10000` | Maximum queued metric batches before dropping | To disable the receiver, set `CHAMBER_OTLP_GRPC_ENABLED=false` in `/etc/chamber/agent.env` and restart the agent. ## Sending Metrics from Your Application Point your application's OTLP exporter to the agent's gRPC endpoint. Here is an example using the Python OpenTelemetry SDK: ```python theme={null} from opentelemetry import metrics from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter from opentelemetry.sdk.resources import Resource # Configure exporter to send to the local Chamber agent exporter = OTLPMetricExporter( endpoint="localhost:4317", insecure=True, # Local connection, no TLS needed ) reader = PeriodicExportingMetricReader(exporter, export_interval_millis=30000) provider = MeterProvider( resource=Resource.create({"service.name": "my-training-job"}), metric_readers=[reader], ) metrics.set_meter_provider(provider) meter = metrics.get_meter("my-training-job") # Create metrics loss_gauge = meter.create_gauge("training.loss", description="Current training loss") throughput_counter = meter.create_counter( "training.samples.processed", unit="1", description="Total training samples processed", ) # Record metrics in your training loop loss_gauge.set(0.42) throughput_counter.add(batch_size) ``` Set `service.name` in your resource attributes — it appears as the service name label on all metrics in the Chamber dashboard. ## Metric Name Transformation The agent transforms OTLP metric names to a Prometheus-compatible format before uploading: | Transformation | Example | | ------------------------------------- | ---------------------------------------------------------------- | | Dots and hyphens become underscores | `training.loss` → `training_loss` | | Unit suffixes are appended | `request_duration` (unit: `s`) → `request_duration_seconds` | | Monotonic sums get `_total` suffix | `samples.processed` (sum, monotonic) → `samples_processed_total` | | Consecutive underscores are collapsed | `my__metric` → `my_metric` | ### Unit Suffix Mapping | OTel Unit | Suffix | | --------- | --------------- | | `s` | `_seconds` | | `ms` | `_milliseconds` | | `By` | `_bytes` | | `KBy` | `_kilobytes` | | `MBy` | `_megabytes` | | `GBy` | `_gigabytes` | | `1` | `_ratio` | ## Histogram Support OTLP histograms are decomposed into Prometheus-style metrics: | Generated Metric | Description | | ---------------- | -------------------------------------------------------------- | | `{name}_bucket` | Cumulative bucket counts with `le` (less-than-or-equal) labels | | `{name}_count` | Total number of observations | | `{name}_sum` | Sum of all observed values | ## Supported Metric Types | OTel Type | Supported | | --------------------------------- | --------- | | Gauge | Yes | | Sum (monotonic and non-monotonic) | Yes | | Histogram | Yes | | ExponentialHistogram | No | | Summary | No | ## Verifying Metrics Are Flowing After configuring your application, check the agent logs: ```bash theme={null} sudo journalctl -u chamber-agent-standalone -f | grep -i otlp ``` You should see log lines indicating metrics received. Then check the **Services** tab in the dashboard — your application metrics will appear with the `service_name` label you configured. ## Next Steps Full list of infrastructure metrics collected All environment variables and settings # Standalone Agent Source: https://docs.usechamber.io/agent/standalone/overview Monitor GPU utilization and workloads on bare-metal or VM-based GPU hosts without Kubernetes The Standalone Agent is currently in **beta** and supports **metric collection only**. Features and configuration may change. The Chamber Standalone Agent runs on individual GPU hosts (bare metal, cloud VMs, or on-prem servers) and reports GPU, host, and application-level metrics to the Chamber dashboard. It is designed for environments where GPUs are not managed by Kubernetes. ## When to Use the Standalone Agent | Environment | Agent | | --------------------------------- | ----------------------------------- | | Kubernetes cluster with GPU nodes | [Kubernetes Agent](/agent/overview) | | Bare-metal GPU servers | **Standalone Agent** | | Cloud GPU VMs (GCP, AWS, Azure) | **Standalone Agent** | | On-prem GPU workstations | **Standalone Agent** | ## What It Does Collects utilization, memory, temperature, power draw, and profiling-level metrics from every GPU on the host via DCGM Exporter Reports CPU usage, memory usage, and capacity so you can see the full picture alongside GPU data Automatically detects GPU processes (PyTorch, DeepSpeed, vLLM, etc.), groups distributed training workers, and tracks their lifecycle Accepts OpenTelemetry metrics from your applications over gRPC, forwarding them to the Chamber dashboard alongside infrastructure metrics ## Architecture ```mermaid theme={null} flowchart LR subgraph host["Your GPU Host"] Agent["Chamber
Standalone Agent"] DCGM["DCGM Exporter"] GPU["NVIDIA GPUs"] App["Your App
(OTLP)"] end DCGM -->|scrape metrics| Agent GPU --> DCGM App -->|"gRPC :4317"| Agent Agent -->|"WSS :443
outbound only"| Chamber["Chamber
Control Plane"] ``` The agent connects outbound to Chamber over a secure WebSocket. No inbound ports or firewall rules are required for Chamber communication. ## What You'll See in the Dashboard Once the agent is running, navigate to **Dashboard > Services** ([app.usechamber.io/dashboard?tab=services](https://app.usechamber.io/dashboard?tab=services)) to see: * **GPU utilization and GPU Usage** per host and per GPU — identify underutilized or overloaded GPUs * **GPU memory consumption** — track memory pressure across your fleet * **Temperature and power draw** — spot thermal throttling or power-capped GPUs before they impact training * **Host CPU and memory** — correlate host-level bottlenecks with GPU performance * **Active workloads** — see which processes are running on each GPU, how long they've been active, and how much GPU memory they're consuming * **Application metrics** — if you instrument your app with OpenTelemetry, custom metrics appear alongside infrastructure data Metrics are collected every 30 seconds and uploaded in batches every 60 seconds. Your host should appear in the dashboard within 60 seconds of the agent starting. ## Beta Limitations * **Metric collection only** — the standalone agent does not support scheduling, capacity pool management, or workload orchestration * **No auto-remediation** — unlike the Kubernetes agent, the standalone agent does not restart or reschedule failed workloads * **Features may change** — configuration, metric names, and dashboard views are subject to change during the beta period ## Next Steps Install the agent on a GPU host Understand the metrics collected and what they mean Send application-level OpenTelemetry metrics to Chamber Environment variables, workload labels, upgrading, and uninstalling # Troubleshooting Source: https://docs.usechamber.io/agent/standalone/troubleshooting Common issues and solutions for the Chamber Standalone Agent The Standalone Agent is in **beta**. If you encounter issues not covered here, contact [support@usechamber.io](mailto:support@usechamber.io). ## Agent Fails to Start Check the logs for error details: ```bash theme={null} sudo journalctl -u chamber-agent-standalone -n 50 --no-pager ``` **Common causes:** | Symptom | Cause | Fix | | -------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | `Authentication failed` or `403` | Invalid or expired cluster token | Verify `CHAMBER_CLUSTER_TOKEN` in `/etc/chamber/agent.env`. Generate a new token in **Settings > API Tokens** if needed. | | `Connection refused` or timeout | Firewall blocking outbound WebSocket on port 443 | Ensure outbound connections to `controlplane-api.usechamber.io:443` are allowed. | | `Organization deactivated` | Your Chamber organization has been deactivated | Contact [support@usechamber.io](mailto:support@usechamber.io). | | `Superseded by new instance` | Another agent instance connected with the same token | Only one agent instance should run per host. Check for duplicate services. | ## Host Not Appearing in Dashboard 1. Verify the agent is running: ```bash theme={null} sudo systemctl status chamber-agent-standalone ``` 2. Check for a successful WebSocket connection in the logs: ```bash theme={null} sudo journalctl -u chamber-agent-standalone --no-pager -n 20 | grep -i websocket ``` 3. Verify the token is correct: ```bash theme={null} grep CHAMBER_CLUSTER_TOKEN /etc/chamber/agent.env ``` Ensure it matches a valid token from **Settings > API Tokens** in the Chamber dashboard. 4. Check network connectivity: ```bash theme={null} curl -s -o /dev/null -w "%{http_code}" https://controlplane-api.usechamber.io/health ``` A `200` response confirms network access. ## No GPU Metrics ### NVIDIA Driver Not Detected ```bash theme={null} nvidia-smi ``` If this fails, the NVIDIA driver is not installed or not loaded. Install the driver appropriate for your GPU and OS. ### DCGM Exporter Not Running ```bash theme={null} curl -s http://localhost:9400/metrics | head -20 ``` If this returns nothing or errors, DCGM Exporter is not running. Check its status: ```bash theme={null} # If running as a Docker container docker ps | grep dcgm # If running as a systemd service sudo systemctl status nvidia-dcgm-exporter ``` Restart if needed, or re-run the installer which will set up DCGM Exporter automatically. ### DCGM Exporter on a Non-Default Port If DCGM Exporter is running on a port other than 9400, update the agent configuration: ```bash theme={null} # In /etc/chamber/agent.env CHAMBER_DCGM_URL=http://localhost:/metrics ``` Then restart the agent: `sudo systemctl restart chamber-agent-standalone` ## GPU Usage Metric Not Available The GPU Usage metric requires DCGM profiling metrics. If it's missing: 1. **Check profiling metrics are exported:** ```bash theme={null} curl -s http://localhost:9400/metrics | grep DCGM_FI_PROF ``` You should see `DCGM_FI_PROF_SM_ACTIVE`, `DCGM_FI_PROF_PIPE_TENSOR_ACTIVE`, and `DCGM_FI_PROF_DRAM_ACTIVE`. 2. **If absent, add profiling fields** to your DCGM Exporter counters file. See [Ensuring DCGM Profiling Metrics Are Collected](/agent/standalone/metrics#ensuring-dcgm-profiling-metrics-are-collected). 3. **Check GPU compatibility:** Profiling requires Volta-generation GPUs or newer (V100, T4, A100, H100, B200, etc.). 4. **Check for conflicting profiling sessions:** Another tool (e.g., Nsight Systems, Nsight Compute) holding a profiling session prevents DCGM from collecting profiling metrics. Close the conflicting tool and restart DCGM Exporter. ## OTLP Receiver Issues ### Application Can't Connect to Port 4317 1. Verify the OTLP receiver is enabled: ```bash theme={null} grep CHAMBER_OTLP_GRPC_ENABLED /etc/chamber/agent.env ``` It should be `true` (or absent, since `true` is the default). 2. Check the agent is listening: ```bash theme={null} ss -tlnp | grep 4317 ``` 3. If another process is using port 4317, change the agent's OTLP port: ```bash theme={null} # In /etc/chamber/agent.env CHAMBER_OTLP_GRPC_PORT=4318 ``` Then restart the agent and update your application's exporter endpoint. ### Metrics Sent but Not Appearing in Dashboard * Metrics are batched and uploaded every 60 seconds. Wait at least 2 minutes after sending. * Check agent logs for OTLP-related errors: ```bash theme={null} sudo journalctl -u chamber-agent-standalone -f | grep -i otlp ``` * Verify your application sets `service.name` in its resource attributes. Metrics without a service name may be harder to find in the dashboard. ## Agent Keeps Restarting Check for repeated crash logs: ```bash theme={null} sudo journalctl -u chamber-agent-standalone --no-pager -n 100 ``` Common causes: * **Python version too old:** The agent requires Python 3.11+. Check with `/opt/chamber-standalone/venv/bin/python --version`. * **Corrupted installation:** Re-run the installer to repair: `curl -fsSL https://chamber-agent-releases.s3.amazonaws.com/install.sh | sudo bash` ## Health and Liveness Probes The agent provides CLI commands for health and liveness checks, useful for container orchestration or custom monitoring: ```bash theme={null} # Readiness: succeeds when the agent is connected and healthy chamber-standalone health # Liveness: succeeds when the agent process is alive and responsive chamber-standalone liveness ``` Both commands check for a recent heartbeat file (within the last 120 seconds) and exit with code 0 (healthy) or 1 (unhealthy). The systemd service uses the liveness probe as a watchdog automatically. If you're running the agent in a container, configure probes like: ```yaml theme={null} livenessProbe: exec: command: ["chamber-standalone", "liveness"] periodSeconds: 30 readinessProbe: exec: command: ["chamber-standalone", "health"] periodSeconds: 30 ``` ## Support If these steps don't resolve your issue, contact [support@usechamber.io](mailto:support@usechamber.io) with: * Agent logs: `sudo journalctl -u chamber-agent-standalone --no-pager -n 200` * Agent version: `/opt/chamber-standalone/venv/bin/chamber-standalone version` * Host info: `/opt/chamber-standalone/venv/bin/chamber-standalone host-info` * GPU info: `nvidia-smi` # Troubleshooting Source: https://docs.usechamber.io/agent/troubleshooting Common issues and solutions for the Chamber agent This guide covers common issues with the Chamber agent and how to resolve them. ## Quick Checks ```bash theme={null} # Check agent pod status kubectl get pods -n chamber-system -l app.kubernetes.io/name=chamber-agent # View recent logs kubectl logs -n chamber-system -l app.kubernetes.io/name=chamber-agent --tail=50 # Check installed version helm list -n chamber-system ``` ## Cluster Not Appearing in Dashboard **Symptoms**: Agent pod is running but cluster doesn't appear in Chamber Verify the token is correct and not expired: ```bash theme={null} kubectl logs -l app.kubernetes.io/name=chamber-agent | grep -i "token\|auth" ``` If you see authentication errors, generate a new token from **Settings > Security > API Tokens -> New Token** in the Chamber dashboard. The agent needs outbound HTTPS access to Chamber: ```bash theme={null} kubectl logs -l app.kubernetes.io/name=chamber-agent | grep -i "connect\|websocket" ``` If behind a corporate firewall, you may need to configure proxy settings. Verify the cluster name was set correctly during installation: ```bash theme={null} kubectl logs -l app.kubernetes.io/name=chamber-agent | grep -i "cluster" ``` ## GPUs Not Detected **Symptoms**: Cluster appears but shows 0 GPUs The NVIDIA device plugin must be running: ```bash theme={null} kubectl get pods -n kube-system -l name=nvidia-device-plugin-ds ``` If not running, install it from [NVIDIA's documentation](https://github.com/NVIDIA/k8s-device-plugin). Check that nodes report GPU resources: ```bash theme={null} kubectl get nodes -o custom-columns=NAME:.metadata.name,GPUS:.status.allocatable.nvidia\\.com/gpu ``` Nodes should show a GPU count. If showing ``, the NVIDIA drivers or device plugin may not be configured correctly. ## Workloads Not Tracked **Symptoms**: Workloads run but don't appear in Chamber Workloads must have the team label to be tracked: ```yaml theme={null} metadata: labels: chamber.io/team: your-team-slug ``` If you configured `watchNamespaces`, verify your workload's namespace is included. By default, the agent watches all namespaces. ## Agent Not Starting **Symptoms**: Pod in CrashLoopBackOff or Error state ```bash theme={null} # Check logs from crashed pod kubectl logs -l app.kubernetes.io/name=chamber-agent --previous ``` | Error | Solution | | ----------------- | ----------------------------------------- | | Token/auth errors | Generate new token from Chamber dashboard | | Connection errors | Check firewall allows outbound HTTPS | | Permission errors | Reinstall agent to fix RBAC | ## GPU Metrics Not Appearing **Symptoms**: Dashboard shows no GPU utilization data The agent discovers GPU metrics via DCGM-Exporter: ```bash theme={null} kubectl logs -n chamber-system -l app.kubernetes.io/name=chamber-agent | grep -i dcgm ``` Look for "DCGM-Exporter detected" messages. Check that metrics are being sent: ```bash theme={null} kubectl logs -n chamber-system -l app.kubernetes.io/name=chamber-agent | grep -i "metrics" ``` Look for "Sent X metrics to Control Plane" messages. If DCGM-Exporter is not installed, the agent can't collect GPU metrics. Install via NVIDIA GPU Operator or standalone: ```bash theme={null} helm repo add nvidia https://helm.ngc.nvidia.com/nvidia helm install dcgm-exporter nvidia/dcgm-exporter -n gpu-operator ``` ## GPU Usage Metric Not Available **Symptoms**: Basic GPU metrics (utilization, memory, temperature) appear in the dashboard, but the GPU Usage metric is missing. Chamber's GPU Usage metric requires the following five DCGM metrics to be collected: * **Profiling metrics**: `DCGM_FI_PROF_SM_ACTIVE`, `DCGM_FI_PROF_PIPE_TENSOR_ACTIVE`, `DCGM_FI_PROF_DRAM_ACTIVE` — not enabled in the default DCGM-Exporter configuration and must be added explicitly. * **Power metrics**: `DCGM_FI_DEV_POWER_USAGE`, `DCGM_FI_DEV_POWER_MGMT_LIMIT` — included in the default DCGM-Exporter configuration but may be missing if your cluster uses a custom metrics configuration. All five metrics must be present for GPU Usage to be computed. If any are missing, the agent logs a warning indicating which metrics are unavailable. If you already have a custom DCGM-Exporter metrics ConfigMap, ensure all five metrics above are included in your existing configuration. A common issue is that custom configurations may omit `DCGM_FI_DEV_POWER_MGMT_LIMIT`, which is required for the power gate calculation. Create a ConfigMap that includes both standard and profiling metrics: ```bash theme={null} kubectl apply -f - < If DCGM-Exporter was installed via the NVIDIA GPU Operator, upgrade with the ConfigMap reference: ```bash theme={null} helm upgrade gpu-operator nvidia/gpu-operator \ -n gpu-operator \ --reuse-values \ --set dcgmExporter.config.name=dcgm-exporter-metrics ``` The GPU Operator automatically restarts DCGM-Exporter pods and handles the volume mount configuration. This approach is persistent across future upgrades. Alternatively, patch the DCGM-Exporter daemonset directly: ```bash theme={null} kubectl patch daemonset nvidia-dcgm-exporter -n gpu-operator --type='json' -p='[ { "op": "replace", "path": "/spec/template/spec/containers/0/env/2/value", "value": "/etc/dcgm-exporter/dcgm-metrics.csv" }, { "op": "add", "path": "/spec/template/spec/containers/0/volumeMounts/-", "value": { "name": "metrics-config", "mountPath": "/etc/dcgm-exporter", "readOnly": true } }, { "op": "add", "path": "/spec/template/spec/volumes/-", "value": { "name": "metrics-config", "configMap": { "name": "dcgm-exporter-metrics" } } } ]' ``` Wait for the rollout to complete: ```bash theme={null} kubectl rollout status daemonset/nvidia-dcgm-exporter -n gpu-operator --timeout=120s ``` The patch command uses a hardcoded path that assumes `DCGM_EXPORTER_COLLECTORS` is at env var index 2. If the patch fails with "path not found", check the actual index: ```bash theme={null} kubectl get daemonset nvidia-dcgm-exporter -n gpu-operator \ -o jsonpath='{.spec.template.spec.containers[0].env}' | jq . ``` Find the index of `DCGM_EXPORTER_COLLECTORS` and adjust the patch path accordingly. This patch may also be overwritten if the GPU Operator is upgraded later. Confirm the profiling metrics are being collected: ```bash theme={null} # Get a DCGM-Exporter pod name DCGM_POD=$(kubectl get pods -n gpu-operator -l app=nvidia-dcgm-exporter \ -o jsonpath='{.items[0].metadata.name}') # Port-forward and check metrics kubectl port-forward -n gpu-operator pod/$DCGM_POD 9400:9400 & PF_PID=$! sleep 3 curl -s localhost:9400/metrics | grep -E "DCGM_FI_PROF_(SM|PIPE_TENSOR|DRAM)_ACTIVE|DCGM_FI_DEV_POWER_MGMT_LIMIT" kill $PF_PID 2>/dev/null ``` You should see all four metrics in the output: * `DCGM_FI_PROF_SM_ACTIVE` * `DCGM_FI_PROF_PIPE_TENSOR_ACTIVE` * `DCGM_FI_PROF_DRAM_ACTIVE` * `DCGM_FI_DEV_POWER_MGMT_LIMIT` If any are missing, update your DCGM-Exporter metrics ConfigMap to include them. The GPU Usage metric will appear in the Chamber dashboard shortly after all required metrics are available. Profiling metrics require NVIDIA Turing architecture or newer GPUs (T4, V100, A100, H100, etc.). Consumer GPUs (GeForce series) may not support profiling metrics. ## Proxy Configuration If your cluster uses an HTTP proxy: ```yaml theme={null} # values.yaml env: - name: HTTPS_PROXY value: "http://proxy.example.com:8080" - name: NO_PROXY value: "10.0.0.0/8,172.16.0.0/12,.cluster.local" ``` Then upgrade the agent: ```bash theme={null} helm upgrade chamber-agent oci://public.ecr.aws/chamber/chamber-agent-chart \ -n chamber-system -f values.yaml ``` ## Getting Help If you're still having issues: 1. Collect logs: `kubectl logs -l app.kubernetes.io/name=chamber-agent > agent-logs.txt` 2. Contact support with logs and your agent version ## Related Pages Install the agent via Helm Upgrade to the latest version # Upgrading Source: https://docs.usechamber.io/agent/upgrading Upgrade the Chamber agent to newer versions This guide covers upgrading the Chamber agent to newer versions. ## Check Current Version ```bash theme={null} helm list -n chamber-system ``` ## Check Available Versions Visit the [releases page](https://github.com/ChamberOrg/chamber-agent/releases) for the latest version and changelog. ## Upgrade to Latest ```bash theme={null} helm upgrade chamber-agent oci://public.ecr.aws/chamber/chamber-agent-chart \ -n chamber-system \ --reuse-values ``` `--reuse-values` preserves your existing configuration (token, cluster ID, etc.). ## Upgrade to Specific Version ```bash theme={null} helm upgrade chamber-agent oci://public.ecr.aws/chamber/chamber-agent-chart \ -n chamber-system \ --version 0.8.96 \ --reuse-values ``` Pinning to a specific version ensures reproducible deployments across environments. ## Verify Upgrade ```bash theme={null} # Check rollout status kubectl rollout status deployment/chamber-agent -n chamber-system # Check the new version helm list -n chamber-system # Check logs for errors kubectl logs -n chamber-system -l app.kubernetes.io/name=chamber-agent --tail=50 ``` Look for successful connection messages: ``` INFO WebSocket connected successfully INFO Metadata collected: X nodes, Y GPUs ``` ## Rollback If issues occur after upgrade: ```bash theme={null} # View upgrade history helm history chamber-agent -n chamber-system # Rollback to previous version helm rollback chamber-agent -n chamber-system # Or rollback to specific revision helm rollback chamber-agent 2 -n chamber-system ``` ## Related Pages Fresh installation guide Fix post-upgrade issues # Supported Scenarios Source: https://docs.usechamber.io/ai-ops/capabilities The GPU workload failures and operational scenarios the AI Ops Agent detects and resolves The Chamber AI Ops Agent handles over 200 GPU infrastructure scenarios across training failures, hardware faults, scheduling issues, distributed computing problems, and capacity planning. This page covers the major categories and how the agent addresses each one. ## Scenario Overview | Category | What It Covers | Agent Response | | ------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------- | | [GPU Memory (OOM)](#gpu-memory-oom) | Out-of-memory errors during training | Auto-fix configuration, resubmit | | [Distributed Training](#distributed-training) | NCCL timeouts, rank failures, communication errors | Diagnose network/config issues, resubmit with fixes | | [Hardware Faults](#hardware-faults) | ECC errors, PCIe failures, thermal throttling | Isolate faulty hardware, migrate jobs, escalate for repair | | [Scheduling & Preemption](#scheduling-and-preemption) | Capacity exhaustion, spot reclamation, taint mismatches | Resubmit, adjust priority, or wait for capacity | | [Ray Workloads](#ray-workloads) | Ray Train, Serve, Data, and cluster-level failures | Framework-aware diagnosis and remediation | | [Stuck and Cascading Failures](#stuck-and-cascading-failures) | Hanging jobs, multi-step failures, dependency chains | Multi-turn investigation, correlated diagnosis | | [Capacity Planning](#capacity-planning) | Oversubscription, demand forecasting, utilization gaps | Analysis and recommendations for team leads | ## GPU Memory (OOM) Out-of-memory errors are the most common GPU training failure. The agent doesn't just detect them — it identifies the specific cause and applies the right fix. **Signal:** Job fails with `CUDA out of memory` during forward pass. GPU memory at 98%+ utilization. **Diagnosis:** Batch size too large for model size and available GPU memory. **Action:** Reduce batch size, enable gradient checkpointing, resubmit with corrected configuration. **Example:** LLaMA 7B fine-tuning on A100-80GB with batch\_size=64 fails. Agent reduces to batch\_size=16 with gradient checkpointing enabled and resubmits. **Signal:** OOM occurs during data loading, not model forward pass. Container memory limit hit. **Diagnosis:** Too many DataLoader workers consuming host memory. **Action:** Reduce `num_workers`, resubmit. **Example:** 16 DataLoader workers on a node with limited host memory. Agent reduces to 4 workers and resubmits. **Signal:** `RuntimeError: DataLoader worker is killed` with shared memory errors. **Diagnosis:** Default `/dev/shm` size (64MB) insufficient for multi-worker data loading. **Action:** Add `emptyDir` volume mount for `/dev/shm` with adequate size, resubmit. **Signal:** OOM during backward pass with large sequence lengths. **Diagnosis:** Activation memory exceeds GPU capacity without checkpointing. **Action:** Enable gradient checkpointing and mixed precision training (`--fp16`), resubmit. ## Distributed Training Multi-GPU and multi-node training introduces communication complexity. The agent diagnoses network, synchronization, and hardware issues across distributed training setups. **Signal:** NCCL AllReduce timeout. Training hangs after initialization. **Diagnosis:** NCCL defaulting to loopback interface instead of the cluster network. **Action:** Set `NCCL_SOCKET_IFNAME=eth0` environment variable, enable NCCL debug logging, resubmit. **Signal:** Training hangs at a specific step. Some ranks complete while others wait. **Diagnosis:** Conditional code paths causing rank divergence in DDP training — not all ranks execute the same collective operations. **Action:** Identify the divergent code path, recommend fix, escalate to developer if code change required. **Signal:** NCCL falls back to TCP with 100x slower communication. Training continues but at unacceptable speed. **Diagnosis:** InfiniBand link failure on a specific node. **Action:** Cancel job, resubmit with node exclusion, escalate for IB hardware repair. **Signal:** Distributed training slows progressively. NCCL timeouts occur after hours of training. **Diagnosis:** GPU on one node throttling due to overheating (92C+), creating a straggler that slows all ranks. **Action:** Cancel job, resubmit excluding the overheating node, escalate for cooling system inspection. ## Hardware Faults GPU hardware issues require quick detection and isolation to prevent cascading failures. **Signal:** CUDA errors during computation. Xid errors in kernel logs. **Diagnosis:** ECC uncorrectable memory errors indicating GPU memory degradation. **Action:** Cancel affected jobs, migrate to healthy GPUs, mark node for maintenance, escalate for hardware replacement. **Signal:** `Xid 79: GPU has fallen off the bus` in system logs. **Diagnosis:** PCIe link failure — GPU is no longer communicating with the host. **Action:** Drain node, resubmit affected jobs to other nodes, escalate for hardware inspection. **Signal:** Degraded GPU-to-GPU communication bandwidth on multi-GPU nodes. **Diagnosis:** NVLink bridge errors causing fallback to PCIe for inter-GPU communication. **Action:** Migrate multi-GPU workloads to healthy nodes, schedule node maintenance. ## Scheduling and Preemption The agent handles the full lifecycle of workload scheduling issues. **Signal:** Job stuck in PENDING state. No available GPUs matching the request. **Diagnosis:** All matching GPUs allocated. Checks elastic workloads that could be preempted. **Action:** If reserved workload: preempt eligible elastic workloads. If elastic: queue with estimated wait time, notify team. **Signal:** Job preempted due to cloud provider spot instance reclamation. **Diagnosis:** Spot interruption notice followed by pod termination. **Action:** Resubmit job with same configuration. If frequent reclamation: recommend switching to reserved capacity. **Signal:** Pod unschedulable despite available GPU resources. **Diagnosis:** Node taints don't match pod tolerations in the workload manifest. **Action:** Add correct tolerations to manifest, resubmit. **Signal:** `ImagePullBackOff` or `ErrImagePull` in Kubernetes events. **Diagnosis:** Registry authentication expired or image tag not found. **Action:** If auth issue: escalate (requires credential update). If tag issue: recommend correct tag. ## Ray Workloads First-class support for the Ray distributed computing framework, covering Ray Train, Ray Serve, Ray Data, and cluster management. **Signal:** Ray worker killed by memory monitor during distributed training. **Diagnosis:** Worker memory limit too low for model size, or missing memory optimization (DeepSpeed ZeRO, gradient checkpointing). **Action:** Increase worker memory allocation or enable memory optimization, resubmit RayJob. **Signal:** Ray Serve replica fails to start. Model loading exceeds replica memory. **Diagnosis:** Model too large for configured replica resources. **Action:** Increase replica GPU memory, or configure model parallelism across replicas. **Signal:** RayJob CR created but Ray cluster never reaches running state. **Diagnosis:** nodeSelector targeting wrong level (e.g., pod-level instead of node-level) or autoscaler deadlock. **Action:** Fix YAML structure, resubmit. For autoscaler issues: diagnose scaling constraints and recommend configuration changes. **Signal:** All Ray workers disconnect. Cluster becomes unresponsive. **Diagnosis:** Global Control Store (GCS) crash on head node, typically from head node OOM. **Action:** If GCS fault tolerance enabled: wait for recovery. If not: cancel and resubmit with GCS FT configuration and larger head node memory. **Signal:** GPU utilization drops to near zero despite data pipeline running. **Diagnosis:** Ray Data operator producing data faster than GPU training can consume, filling object store. **Action:** Configure backpressure limits, adjust data pipeline parallelism to match GPU throughput. ## Stuck and Cascading Failures Some failures require multi-step investigation across multiple data sources and time windows. **Signal:** Job status is RUNNING but loss metrics haven't updated in 30+ minutes. **Diagnosis:** Agent checks GPU utilization (if near 0%, likely deadlock or I/O stall), network metrics (if communication stalled), and recent log entries to pinpoint where the job is stuck. **Action:** Based on diagnosis — may fix I/O bottleneck, restart communication, or cancel and resubmit with corrected config. **Signal:** Multiple jobs fail simultaneously with different error messages. **Diagnosis:** Agent correlates the failures to a single node going offline, rather than treating each as an independent issue. **Action:** Identify the root cause (node crash), resubmit all affected jobs with node exclusion, escalate for node repair. **Signal:** Training job blocked, but the error traces back through preprocessing to an expired credential. **Diagnosis:** Multi-hop investigation: training blocked by preprocessing failure, preprocessing blocked by expired S3 credentials. **Action:** Escalate credential refresh, then resubmit the full pipeline. **Signal:** Same job fails repeatedly with different error messages at roughly the same training step. **Diagnosis:** Agent correlates across attempts — discovers the underlying cause (e.g., thermal throttling causing GPU clock reduction) is the same despite different surface errors. **Action:** Address the root cause rather than chasing individual error messages. ## Capacity Planning Beyond reactive incident handling, the agent provides proactive capacity intelligence. **Signal:** Team consistently hitting queue limits during peak hours. **Diagnosis:** Analyzes submission patterns over time — identifies peak demand windows, utilization gaps, and oversubscription trends. **Recommendations:** GPU allocation adjustments, time-slot scheduling for peak hours, priority queuing for short-duration jobs. Escalates to team leads for capacity decisions. **Signal:** Heartbeat detects GPUs sitting idle while jobs are queued in other teams. **Diagnosis:** Identifies underutilized allocations and teams that could benefit from elastic burst capacity. **Recommendations:** Rebalancing suggestions, elastic capacity sharing policies, right-sizing team allocations. ## Next Steps How the agent keeps your infrastructure safe with five layers of guardrails Enable AI Ops for your organization # Getting Started Source: https://docs.usechamber.io/ai-ops/getting-started Enable the AI Ops Agent for your organization and configure it for your team's workflow **Private Beta** — The AI Ops Agent is currently in private beta and available to select customers. To request access, [contact us](mailto:support@usechamber.io) or reach out to your account representative. Get the Chamber AI Ops Agent running for your organization in minutes. The agent connects to your existing Chamber deployment — no additional cluster-side components required. ## Prerequisites * A Chamber account with admin access * At least one Kubernetes cluster with the [Chamber agent installed](/agent/installation) * A Slack workspace for your team ## Setup Navigate to **Settings > AI Ops Agent** in the [Chamber dashboard](https://app.usechamber.io). Toggle **Enable AI Ops Agent** to on. Click **Add to Slack** to authorize the AI Ops Agent in your workspace. This creates the `@chambie-ops` bot in your Slack — separate from any existing Chamber integrations. Select the channels where the agent should post: * **Alerts channel** — real-time incident notifications (e.g., `#ml-ops-alerts`) * **Daily reports channel** — scheduled summaries (e.g., `#ml-ops-daily`) * **Approvals channel** — approval requests for high-risk actions (e.g., `#ml-ops-approvals`) * **Escalation channel** — unresolved issues that need human attention (e.g., `#ml-ops-escalation`) Set the operational boundaries for the agent. The default policy allows read-only operations and requires approval for all write actions — a safe starting point. You can customize: | Setting | Default | Description | | ---------------------------- | ---------- | --------------------------------------------------- | | **Heartbeat interval** | 5 minutes | How often the agent checks your infrastructure | | **Daily budget limit** | \$500 | Maximum GPU spend the agent can authorize per day | | **Monthly budget limit** | \$10,000 | Maximum GPU spend per month | | **Max GPUs per auto-submit** | 4 | Jobs up to this size can be auto-submitted (Tier 2) | | **Tier 3 approval channel** | — | Slack channel for high-risk approval requests | | **Tier 4 approvers** | — | Specific users who can approve destructive actions | | **Approval timeout** | 30 minutes | How long before unanswered approvals escalate | Once enabled, the agent starts its first heartbeat check within 5 minutes. You'll see a message in your alerts channel: ``` @chambie-ops connected Monitoring: 3 capacity pools, 48 GPUs, 12 active workloads Policy: Tier 0-2 auto, Tier 3+ approval required Heartbeat: every 5 minutes Daily report: 9:00 AM to #ml-ops-daily All systems healthy. HEARTBEAT_OK ``` If everything is healthy, the agent will be silent until something needs attention. Start with the default policy (read-only auto, approval for writes) and gradually expand autonomous permissions as you build confidence in the agent's behavior. ## What Happens Next Once running, the AI Ops Agent immediately begins: 1. **Monitoring** your active workloads, GPU health, and capacity utilization 2. **Posting daily cost reports** to your configured channel 3. **Responding to failures** as they occur — diagnosing, recommending, and acting within your policy 4. **Building its knowledge base** — learning the patterns specific to your infrastructure The AI Ops Agent is a separate Slack bot (`@chambie-ops`) from Chamber's conversational assistant (`@chambie`). The conversational assistant handles ad-hoc questions and manual tasks. The AI Ops Agent handles autonomous monitoring and remediation. ## Adjusting the Policy Over Time As the agent proves itself, you can gradually expand its autonomous capabilities: | Phase | Recommended Policy | What Changes | | ------------ | ------------------------------------------------------- | ------------------------------------------------------- | | **Week 1** | Read-only auto, all writes need approval | Observe how the agent diagnoses issues | | **Week 2-4** | Auto-submit small elastic jobs (up to 4 GPUs) | Agent handles routine OOM resubmissions automatically | | **Month 2+** | Auto-submit up to 16 GPUs, auto-resubmit preempted jobs | Agent handles the majority of routine incidents | | **Ongoing** | Tune based on your comfort level | Review the audit trail and expand or restrict as needed | ## Next Steps Learn what the AI Ops Agent does and why it matters See the full range of failures the agent can handle Deep dive into the five-layer safety model Configure your existing Slack integration # How It Works Source: https://docs.usechamber.io/ai-ops/how-it-works Three-trigger proactivity, intelligent diagnosis, and a learning system that compounds expertise over time The Chamber AI Ops Agent combines proactive monitoring, intelligent diagnosis, and safe remediation into a continuous operational loop. This page explains the architecture behind it. ## Three-Trigger Proactivity Model Most monitoring tools are reactive — they wait for an alert, then notify you. The AI Ops Agent is proactive. It uses three complementary trigger mechanisms to ensure nothing slips through the cracks. ```mermaid theme={null} flowchart TD HB["Heartbeat
(every 5 min)"] CR["Scheduled Tasks
(cron)"] EV["Event-Driven
(real-time)"] HB -->|"Anything wrong?"| Agent["AI Ops Agent"] CR -->|"Generate report"| Agent EV -->|"Job failed"| Agent Agent --> Diagnose["Diagnose"] Diagnose --> Act["Act or Escalate"] Act --> Verify["Verify"] Verify --> Learn["Learn"] ``` ### Heartbeat — Catching What Alerts Miss Every 5 minutes, the agent checks in on your infrastructure and asks: *Is anything wrong?* This catches the failures that don't produce alerts — GPUs sitting idle, training jobs running slower than expected, costs drifting above budget, or utilization gradually degrading. If everything is healthy, the heartbeat is silent. No noise, no unnecessary messages. The heartbeat interval is configurable per organization. 5 minutes is the default — you can set it anywhere from 1 to 30 minutes. ### Scheduled Tasks — Reports and Reviews on Your Schedule Recurring operational tasks run on a schedule you define: | Task | Default Schedule | What It Does | | ---------------------- | ---------------- | ----------------------------------------------------------------- | | Daily cost report | 9:00 AM | GPU spend breakdown, trends, anomalies | | Weekly capacity review | Monday 10:00 AM | Utilization trends, demand forecast, optimization recommendations | | Training loop check | Every 5 minutes | Monitors active training jobs for failures or stalls | Each scheduled task runs in an isolated session — they don't interfere with each other or with real-time incident handling. ### Event-Driven — Real-Time Response When something happens in your cluster, the agent responds immediately: | Event | Response Time | Agent Action | | ---------------------- | ------------- | --------------------------------------------------------------- | | Job failure | \< 30 seconds | Diagnose root cause, attempt auto-fix or escalate | | GPU hardware fault | \< 30 seconds | Assess blast radius, migrate affected jobs, request maintenance | | Budget threshold (80%) | \< 1 minute | Summarize spending, alert team, recommend adjustments | | Pod eviction | \< 30 seconds | Determine cause, resubmit if appropriate | ## Diagnosis Flow When the agent detects an issue — whether from a heartbeat, scheduled check, or real-time event — it follows a structured diagnosis flow. ```mermaid theme={null} flowchart LR O["Observe
(collect evidence)"] --> D["Diagnose
(root cause)"] D --> R["Recommend
(choose action)"] R --> A["Act
(execute safely)"] A --> V["Verify
(confirm fix)"] V --> L["Learn
(bank pattern)"] ``` ### Observe The agent collects evidence before making any decisions: * **Workload details** — job configuration, GPU type, resource requests * **Logs** — recent error messages and stack traces * **Metrics** — GPU memory, utilization, temperature over time * **Kubernetes events** — pod status, node conditions, scheduling events ### Diagnose Using the collected evidence, the agent performs root-cause analysis — not just pattern matching on error strings. It correlates across data sources to identify the actual cause. For example, an "NCCL timeout" error might be caused by: * A network interface misconfiguration (fix: set `NCCL_SOCKET_IFNAME`) * An InfiniBand hardware failure (fix: migrate to healthy nodes) * A thermal-throttled GPU creating a straggler (fix: exclude overheating node) The agent distinguishes between these by checking network metrics, hardware status, and thermal data — then applies the right fix. ### Recommend, Act, Verify Based on the diagnosis and the action's [risk tier](/ai-ops/safety), the agent either: * **Auto-executes** low-risk fixes (e.g., resubmit with corrected batch size) * **Requests approval** for high-risk actions (e.g., cancel a running job) * **Escalates** when human judgment is needed (e.g., hardware replacement) After acting, the agent monitors the fix to verify it worked — and notifies your team of the outcome. ## Tiered Intelligence The agent uses different AI model tiers depending on the complexity of the task, optimizing for both speed and cost: | Tier | Used For | Examples | | ------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | | **Fast** | Heartbeat checks, event triage, status queries | "Are all jobs healthy?" — answered in milliseconds | | **Reasoning** | Root-cause analysis, pattern matching, planning | "Why did this distributed training job fail?" — deep multi-source analysis | | **Critical** | Destructive decisions, novel failures, complex multi-step remediation | "Should we cancel this 64-GPU job and reallocate?" — careful reasoning with full context | Fast-tier checks keep the agent's operating cost low during quiet periods. The agent only escalates to more powerful reasoning when the situation demands it. ## Memory and Learning The AI Ops Agent doesn't just fix problems — it learns from them. Over time, it builds a knowledge base specific to your infrastructure. ### Pattern Bank Every resolved incident becomes a reusable pattern: ``` Signal: Job fails with "CUDA out of memory" on A100 80GB, batch_size > 32 Cause: Mixed precision not enabled, gradient accumulation not configured Fix: Enable --fp16, set gradient_accumulation_steps = batch_size / 8 Trap: Don't just halve batch_size — throughput drops 50%. Fix root cause. ``` When the agent encounters a matching signal in the future, it applies the known fix immediately — no re-diagnosis needed. ### Failure Journal When a fix doesn't work, the agent records what went wrong and adds a prevention rule: ``` What happened: Resubmitted OOM job but didn't verify node selector. Job landed on T4 instead of A100, failed with different error. Prevention: Always verify GPU type matches original job before resubmission. ``` ### How Expertise Compounds ```mermaid theme={null} flowchart LR E["Encounter
(new failure)"] --> D["Diagnose"] D --> F["Fix"] F --> O["Outcome"] O -->|Success| B["Bank Pattern"] O -->|Failure| J["Journal + Escalate"] B --> E J --> E ``` After several months of operation, the pattern bank becomes a comprehensive runbook specific to your infrastructure — covering the failure modes, GPU types, and workload patterns unique to your environment. The agent's memory is human-readable and auditable. Your team can review, edit, and version-control the pattern bank alongside your infrastructure code. ## Notification Philosophy The agent communicates through Slack with a clear philosophy: **inform without overwhelming**. * **3-5 messages per incident**, not dozens * **Batched updates** — status changes are grouped, not streamed * **Silent when healthy** — heartbeats produce no output when everything is fine * **Structured reports** — daily and weekly summaries go to designated channels * **Approval requests** — interactive Slack buttons for actions that need human sign-off ## Next Steps See the full range of failures the agent detects and resolves Learn about the five-layer safety model and risk-tiered actions # AI Ops Agent Source: https://docs.usechamber.io/ai-ops/overview Your always-on AI operations teammate that monitors, diagnoses, and resolves GPU workload issues Chamber's AI Ops Agent is an autonomous operations teammate that watches over your GPU infrastructure 24/7. It detects failures in seconds, diagnoses root causes, and resolves routine issues automatically — so your ML engineers can focus on building models, not firefighting infrastructure. Proactive heartbeat checks every 5 minutes catch silent failures, idle GPUs, and drifting costs — without waiting for alerts Root-cause analysis powered by AI that correlates logs, metrics, and Kubernetes events to pinpoint exactly what went wrong Resolves routine issues like OOM errors, preempted jobs, and scheduling conflicts automatically with safe, verified fixes Builds a knowledge base specific to your infrastructure — getting faster and more accurate with every incident it handles ## How Chamber AI Ops Fits In The AI Ops Agent extends Chamber's control plane with autonomous operational intelligence. It works alongside the Kubernetes agent you already have deployed — no additional cluster-side components required. ```mermaid theme={null} flowchart LR subgraph cluster["Your GPU Cluster"] KAgent["Chamber
Kubernetes Agent"] GPUs["GPU Nodes"] end subgraph chamber["Chamber Platform"] CP["Control Plane"] AI["AI Ops Agent"] end subgraph team["Your Team"] Slack["Slack"] end KAgent -->|metrics, events| CP CP -->|real-time events| AI AI -->|diagnose, remediate| CP CP -->|schedule, manage| KAgent KAgent --> GPUs AI -->|"alerts, approvals,
reports"| Slack ``` ## What Makes It Different Doesn't wait for alerts. Continuously checks your infrastructure and catches issues before they escalate — including silent failures that don't produce events. Purpose-built for ML infrastructure. Knows the difference between an OOM from a large batch size and an OOM from a memory leak. Fixes the root cause, not just the symptom. Five layers of safety guardrails. Risk-tiered actions. Human approval for anything destructive. Full audit trail. Your infrastructure, your rules. ## A Day in the Life Here's what the AI Ops Agent does for your team on a typical day: | Time | What Happens | How You See It | | ----------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------------- | | **6:02 AM** | Heartbeat detects a training job stuck for 45 minutes | Slack alert with diagnosis and recommended fix | | **6:03 AM** | Identifies OOM error, reduces batch size, resubmits job | Slack notification: "Resubmitted job with fix. Monitoring." | | **6:18 AM** | Verifies resubmitted job is training successfully | Slack update: "Job progressing normally. Loss decreasing." | | **9:00 AM** | Daily cost report generated | Posted to #ml-ops-daily with spend breakdown and trends | | **2:15 PM** | GPU hardware fault detected on a node | Slack alert: "ECC errors on node-gpu-07. Migrated affected jobs. Requesting maintenance." | | **2:16 PM** | Sends approval request for node isolation | Slack approval buttons — your team decides | The AI Ops Agent sends 3-5 messages per incident, not dozens. It batches updates and only notifies on meaningful state changes. ## Next Steps Deep dive into the three-trigger proactivity model, diagnosis flow, and learning system Explore the 200+ failure scenarios the agent can detect and resolve Understand the five-layer safety model and enterprise governance controls Enable AI Ops for your organization # Safety & Governance Source: https://docs.usechamber.io/ai-ops/safety Five-layer defense-in-depth safety model, risk-tiered actions, and enterprise governance controls Autonomous agents operating on GPU infrastructure must be safe by design. The Chamber AI Ops Agent uses a five-layer defense-in-depth model — every action passes through multiple independent safety checks before execution. No single layer's failure can result in an unauthorized action. ## Five-Layer Defense-in-Depth ```mermaid theme={null} flowchart TB L5["Layer 5: Server Guardrails
(Chamber API — ultimate safety net)"] L4["Layer 4: Human Approval
(Slack approval for high-risk actions)"] L3["Layer 3: CLI Guardrails
(budget checks, scope validation)"] L2["Layer 2: Tenant Policy
(deny-by-default YAML policy)"] L1["Layer 1: Credential Isolation
(per-org scoped credentials)"] L1 --> L2 --> L3 --> L4 --> L5 ``` | Layer | What It Does | Cannot Be Bypassed By | | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | | **Layer 1: Credential Isolation** | Each organization's agent runs with its own scoped credentials. No cross-tenant access is possible at the infrastructure level. | Any client-side code | | **Layer 2: Tenant Policy** | A deny-by-default policy defines exactly which actions the agent can take for your organization. Anything not explicitly allowed is blocked. | Agent reasoning or prompts | | **Layer 3: CLI Guardrails** | Budget checks, scope validation, and rate limits built into the Chamber CLI. Every write action is validated before execution. | Policy misconfiguration | | **Layer 4: Human Approval** | High-risk actions require explicit human approval via Slack before execution. Approvals are cryptographically bound and single-use. | Automated processes | | **Layer 5: Server Guardrails** | Chamber's API server enforces final budget limits, scope validation, and rate limits. This is the ultimate safety net — even if all client-side layers fail, the server rejects unauthorized actions. | Nothing — this is the final gate | Layers 1, 2, and 5 are always active and cannot be disabled. Layers 3 and 4 provide additional defense for write operations. ## Risk-Tiered Action Model Every action the agent can take is classified into a risk tier. Higher tiers require progressively more safety checks. | Tier | Category | Examples | Policy | | ------------------- | --------------------- | -------------------------------------------------------------------------- | --------------------------------------------- | | **0 — Observe** | Read-only queries | List workloads, get metrics, check GPU status, read logs | Auto-execute | | **1 — Inform** | Analysis and insights | Explain failures, analyze capacity trends, generate reports | Auto-execute, notify team | | **2 — Low Write** | Safe mutations | Submit small jobs (up to 4 GPUs), create allocations (up to 8 instances) | **Dry-run first**, then execute | | **3 — High Write** | Significant mutations | Submit large jobs (over 4 GPUs), transfer allocations, create reservations | **Human approval required** | | **4 — Destructive** | Irreversible actions | Cancel running jobs, release allocations | **Dual approval required**, mandatory audit | | **5 — Prohibited** | Dangerous operations | Delete pools, destroy infrastructure | **Hard blocked** — not available to the agent | ### Dry-Run Enforcement For Tier 2 actions, the agent always performs a dry-run first. The dry-run shows exactly what will happen — resources consumed, configuration applied, estimated cost — before any mutation occurs. Only after the dry-run passes validation does the agent execute. ### Human Approval Workflow For Tier 3 and Tier 4 actions, the agent sends an approval request to your team via Slack: ``` @chambie-ops requests approval: Action: Cancel job llama-finetune-v3 (job-a1b2c3d4) Reason: GPU ECC errors detected on assigned node. Job producing corrupted gradients. Recommend cancel and resubmit on healthy hardware. Risk Tier: 4 (Destructive) Evidence: 12 uncorrectable ECC errors in last 10 minutes. Loss spiked to NaN at step 4,521. [Approve] [Deny] Expires in 30 minutes. If no response, escalates to #ml-ops-escalation. ``` **Approval security:** * Approval buttons are **cryptographically signed** — they cannot be forged or replayed * Each approval is **single-use** — clicking Approve twice has no effect * Approvals **expire** after 30 minutes (configurable) — unresolved requests escalate automatically * **Approver identity is verified** — only authorized team members can approve Tier 4 actions ## Deny-by-Default Tenant Policy Your organization's tenant policy defines exactly what the agent is allowed to do. Everything else is denied. ```yaml theme={null} # Example tenant policy version: "1.0" allowed_tools: # Read-only operations — always allowed tier_0: - workloads.list - workloads.get - metrics.get - failure_analysis.diagnose - gpus.status - logs.get # Analysis — allowed with notification tier_1: - workloads.explain - insights.analyze - capacity.plan # Low-risk writes — allowed with constraints tier_2: - workloads.submit: max_gpus: 4 job_type: [elastic] - allocations.create: max_instances: 8 # High-risk writes — require approval tier_3: - workloads.submit: max_gpus: 64 - allocations.transfer - reservations.create # Destructive — require dual approval tier_4: - workloads.cancel - allocations.release budget: daily_limit_usd: 500 monthly_limit_usd: 10000 approval: tier_3_channel: "#ml-ops-approvals" tier_4_approvers: ["@alice", "@bob"] timeout_minutes: 30 escalation_channel: "#ml-ops-escalation" ``` The tenant policy is version-controlled and auditable. Changes to the policy require manual configuration — the agent cannot modify its own permissions. ## Audit Trail Every action the agent takes is logged with full context: | Field | Description | | ------------- | -------------------------------------------------------- | | **Action** | What the agent did (e.g., `workloads.submit`) | | **Risk Tier** | The action's risk classification | | **Reason** | Why the agent took this action (root-cause description) | | **Evidence** | The logs, metrics, and events that informed the decision | | **Approver** | Who approved the action (for Tier 3+) | | **Outcome** | Whether the action succeeded and its effect | | **Timestamp** | When the action occurred | Audit records are retained for compliance review and can be exported for integration with your existing governance tools. ## Incident Deduplication When multiple signals detect the same issue — for example, a real-time event and the next heartbeat both notice a failed job — the agent deduplicates them. Only one remediation runs per incident. If two team members try to address the same issue from different Slack threads, the second is told the issue is already being handled and is offered updates on the resolution. ## Guardrail Enforcement Examples A resubmission would exceed the daily budget limit. The agent blocks the action, notifies the team, and suggests waiting until the next budget cycle or requesting a budget increase. A job requests 128 GPUs but the tenant policy caps individual jobs at 64. The agent blocks the request locally — it never reaches the API. Releasing an allocation that has running workloads is a Tier 4 action. The agent sends a dual-approval request showing which workloads would be affected. Both designated approvers must approve before execution. The agent encounters a failure it hasn't seen before and cannot confidently diagnose. Rather than guessing, it escalates to your team with the evidence it has collected — logs, metrics, and its best hypothesis — for human review. ## Next Steps Enable AI Ops and configure your tenant policy Learn about the three-trigger proactivity model and diagnosis flow # Capacity Source: https://docs.usechamber.io/api-reference/capacity Check budget allocations and remaining GPU hours ## Get Capacity Retrieve capacity budget and allocation information for your organization. ```bash theme={null} GET /v1/capacity ``` ### Query Parameters | Parameter | Type | Description | | --------------- | ------ | -------------------------------- | | `initiative_id` | string | Filter to specific team | | `pool_id` | string | Filter to specific capacity pool | ### Example Request ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/capacity" \ -H "Authorization: Bearer " \ -H "X-Organization-Id: " ``` ### Example Response ```json theme={null} { "data": { "organization_id": "org_abc123", "summary": { "total_allocated_gpu_hours": 10000, "total_used_gpu_hours": 6500, "total_remaining_gpu_hours": 3500, "current_active_gpus": 24 }, "pools": [ { "pool_id": "pool_prod", "name": "Production Pool", "allocated_gpu_hours": 6000, "used_gpu_hours": 4200, "remaining_gpu_hours": 1800, "instance_types": ["p4d.24xlarge", "p5.48xlarge"] }, { "pool_id": "pool_dev", "name": "Development Pool", "allocated_gpu_hours": 4000, "used_gpu_hours": 2300, "remaining_gpu_hours": 1700, "instance_types": ["g5.xlarge", "g5.2xlarge"] } ], "initiatives": [ { "initiative_id": "init_ml_team", "name": "ML Platform Team", "allocated_gpu_hours": 5000, "used_gpu_hours": 3200, "remaining_gpu_hours": 1800 }, { "initiative_id": "init_research", "name": "Research Team", "allocated_gpu_hours": 5000, "used_gpu_hours": 3300, "remaining_gpu_hours": 1700 } ] }, "request_id": "req_abc123" } ``` ### Response Fields | Field | Description | | --------------------------- | --------------------------------------------- | | `total_allocated_gpu_hours` | Total GPU hours allocated to the organization | | `total_used_gpu_hours` | GPU hours consumed across all workloads | | `total_remaining_gpu_hours` | Available GPU hours remaining | | `current_active_gpus` | Number of GPUs currently in use | | `pools` | Breakdown by capacity pool | | `initiatives` | Breakdown by team | # Health Source: https://docs.usechamber.io/api-reference/health Service health check endpoint ## Health Check Check the health status of the Chamber API service. This endpoint does not require authentication and can be used for monitoring and load balancer health checks. ```bash theme={null} GET /v1/health ``` ### Example Request ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/health" ``` ### Example Response ```json theme={null} { "data": { "status": "healthy", "version": "1.0.0", "timestamp": "2024-01-15T10:30:00Z" } } ``` ### Response Fields | Field | Description | | ----------- | ----------------------------------------------- | | `status` | Service health status: `healthy` or `unhealthy` | | `version` | API version number | | `timestamp` | Current server timestamp (ISO 8601) | # API Reference Source: https://docs.usechamber.io/api-reference/introduction Chamber REST API for programmatic access to GPU capacity and workload management The Chamber API provides programmatic access to manage GPU capacity, monitor workloads, and query metrics across your organization. ## Base URL ``` https://api.usechamber.io/v1 ``` ## Authentication All API requests (except `/v1/health`) require authentication using a Bearer token. ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/workloads" \ -H "Authorization: Bearer " \ -H "X-Organization-Id: " ``` ### Required Headers | Header | Required | Description | | ------------------- | -------- | ------------------------------------------------------ | | `Authorization` | Yes | Bearer token (JWT from Cognito or API token) | | `X-Organization-Id` | Yes\* | Your organization ID (\*not required for `/v1/health`) | | `X-Request-Id` | No | Optional request ID for tracing | Contact [support@usechamber.io](mailto:support@usechamber.io) to obtain API credentials for your organization. ## Response Format All successful responses follow a consistent structure: ```json theme={null} { "data": { // Response content }, "metadata": { "next_token": "...", "total_count": 100 }, "request_id": "req_abc123" } ``` ### Error Responses Errors return an appropriate HTTP status code with details: ```json theme={null} { "error": { "code": "VALIDATION_ERROR", "message": "Invalid parameter value", "details": [...] }, "request_id": "req_abc123" } ``` ## Authorization Model Access to resources is controlled by your role within the organization: | Role | Access Level | | ----------- | ------------------------------------------------- | | `ORG_ADMIN` | Full organization access | | `TEAM_LEAD` | Team-specific access with management capabilities | | `MEMBER` | Team-specific read access | ## Endpoints List, retrieve, and get statistics for GPU workloads Query GPU utilization, memory, temperature, and power metrics Check budget allocations and remaining GPU hours Service health check endpoint # Metrics Source: https://docs.usechamber.io/api-reference/metrics Query GPU utilization, memory, temperature, and power metrics ## Get Workload Metrics Retrieve GPU metrics for a specific workload. ```bash theme={null} GET /v1/workloads/{workload_id}/metrics ``` ### Path Parameters | Parameter | Type | Description | | ------------- | ------ | ------------------------------ | | `workload_id` | string | The unique workload identifier | ### Query Parameters | Parameter | Type | Description | | ------------ | ------ | --------------------------------------------------------------------------------- | | `time_range` | string | Time range: `last_1h`, `last_6h`, `last_24h`, `job_lifetime` (default: `last_1h`) | | `metrics` | string | Comma-separated list of metrics to include | ### Available Metrics | Metric | Description | | -------------------- | ---------------------------------- | | `gpu_utilization` | GPU compute utilization percentage | | `memory_utilization` | GPU memory utilization percentage | | `temperature` | GPU temperature in Celsius | | `power_usage` | Power consumption in Watts | | `gpu_usage` | Overall GPU usage metric | ### Example Request ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/workloads/wl_abc123/metrics?time_range=last_6h&metrics=gpu_utilization,memory_utilization" \ -H "Authorization: Bearer " \ -H "X-Organization-Id: " ``` ### Example Response ```json theme={null} { "data": { "workload_id": "wl_abc123", "time_range": "last_6h", "metrics": { "gpu_utilization": { "avg": 85.2, "min": 45.0, "max": 99.8, "current": 92.1 }, "memory_utilization": { "avg": 78.5, "min": 60.2, "max": 89.4, "current": 82.0 } } }, "request_id": "req_abc123" } ``` *** ## Get Ranked Workload Metrics Retrieve metrics across workloads, ranked by utilization or consumption. ```bash theme={null} GET /v1/workloads/metrics ``` ### Query Parameters | Parameter | Type | Description | | --------------- | ------- | -------------------------------------------------------------------------------- | | `sort_by` | string | Sort metric: `gpu_utilization`, `memory_utilization`, `power_usage`, `gpu_hours` | | `order` | string | Sort order: `asc`, `desc` (default: `desc`) | | `limit` | integer | Number of results (1-100, default: 10) | | `initiative_id` | string | Filter to specific team | | `status` | string | Filter by workload status | ### Example Request ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/workloads/metrics?sort_by=gpu_utilization&order=desc&limit=5" \ -H "Authorization: Bearer " \ -H "X-Organization-Id: " ``` ### Example Response ```json theme={null} { "data": { "workloads": [ { "workload_id": "wl_abc123", "name": "training-large-model", "gpu_utilization": { "avg": 95.2, "current": 97.1 }, "initiative_id": "init_ml_team" }, { "workload_id": "wl_def456", "name": "inference-batch", "gpu_utilization": { "avg": 88.7, "current": 91.0 }, "initiative_id": "init_research" } ], "scope_average": { "gpu_utilization": 72.5 } }, "metadata": { "total_count": 45 }, "request_id": "req_abc123" } ``` # Workloads Source: https://docs.usechamber.io/api-reference/workloads List, retrieve, and get statistics for GPU workloads ## List Workloads Retrieve a paginated list of workloads with optional filtering. Results are automatically filtered based on your role and team access. ```bash theme={null} GET /v1/workloads ``` ### Query Parameters | Parameter | Type | Description | | ----------------- | ------- | -------------------------------------------------------------------------- | | `organization_id` | string | Filter by organization | | `initiative_id` | string | Filter by team | | `status` | string | Filter by status: `pending`, `running`, `completed`, `failed`, `cancelled` | | `submitted_by` | string | Filter by user who submitted the workload | | `is_managed` | boolean | Filter managed vs unmanaged workloads | | `start_date` | string | Filter workloads submitted after this date (ISO 8601) | | `end_date` | string | Filter workloads submitted before this date (ISO 8601) | | `limit` | integer | Number of results per page (1-100, default: 20) | | `next_token` | string | Pagination cursor from previous response | ### Example Request ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/workloads?status=running&limit=10" \ -H "Authorization: Bearer " \ -H "X-Organization-Id: " ``` ### Example Response ```json theme={null} { "data": { "workloads": [ { "workload_id": "wl_abc123", "name": "training-job-001", "status": "running", "submitted_by": "user@example.com", "initiative_id": "init_xyz", "instance_type": "p4d.24xlarge", "gpu_count": 8, "submitted_at": "2024-01-15T10:30:00Z", "started_at": "2024-01-15T10:32:00Z" } ] }, "metadata": { "next_token": "eyJ...", "total_count": 45 }, "request_id": "req_abc123" } ``` *** ## Get Workload Retrieve details for a specific workload. ```bash theme={null} GET /v1/workloads/{workload_id} ``` ### Path Parameters | Parameter | Type | Description | | ------------- | ------ | ------------------------------ | | `workload_id` | string | The unique workload identifier | ### Example Request ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/workloads/wl_abc123" \ -H "Authorization: Bearer " \ -H "X-Organization-Id: " ``` ### Example Response ```json theme={null} { "data": { "workload_id": "wl_abc123", "name": "training-job-001", "status": "running", "submitted_by": "user@example.com", "initiative_id": "init_xyz", "instance_type": "p4d.24xlarge", "gpu_count": 8, "submitted_at": "2024-01-15T10:30:00Z", "started_at": "2024-01-15T10:32:00Z", "completed_at": null, "duration_seconds": 3600, "gpu_hours_used": 8.0, "exit_code": null, "is_managed": true, "cluster_id": "cluster_prod1", "namespace": "ml-training" }, "request_id": "req_abc123" } ``` *** ## Get Workload Statistics Retrieve aggregated statistics across workloads. ```bash theme={null} GET /v1/workloads/stats ``` ### Query Parameters | Parameter | Type | Description | | --------------- | ------ | --------------------------------------------------------------------------------------------- | | `time_range` | string | Predefined range: `today`, `this_week`, `this_month`, `last_7_days`, `last_30_days`, `custom` | | `start_date` | string | Start date for custom range (ISO 8601) | | `end_date` | string | End date for custom range (ISO 8601) | | `group_by` | string | Group results by: `submitted_by`, `initiative_id`, `instance_type` | | `initiative_id` | string | Filter to specific team | ### Example Request ```bash theme={null} curl -X GET "https://api.usechamber.io/v1/workloads/stats?time_range=last_7_days&group_by=initiative_id" \ -H "Authorization: Bearer " \ -H "X-Organization-Id: " ``` ### Example Response ```json theme={null} { "data": { "summary": { "total_workloads": 156, "total_gpu_hours": 2450.5, "average_duration_seconds": 7200, "success_rate": 0.94 }, "grouped": [ { "initiative_id": "init_ml_team", "workload_count": 89, "gpu_hours": 1200.0, "success_rate": 0.96 }, { "initiative_id": "init_research", "workload_count": 67, "gpu_hours": 1250.5, "success_rate": 0.91 } ] }, "request_id": "req_abc123" } ``` # AI Assistant Source: https://docs.usechamber.io/cli/chat Ask questions about your GPU infrastructure, workloads, and capacity directly from the terminal # AI Assistant **Get answers without leaving your terminal.** The `chamber chat` command connects you to Chamber's AI assistant — ask about workload status, GPU utilization, capacity planning, and more in natural language. ```bash theme={null} chamber chat "how many GPUs are running right now?" ``` AI Chat requires browser-based authentication. Run `chamber login` (without `--token`) to authenticate. API tokens are not supported for chat. ## Modes ### Quick Question Pass your question as an argument for a single response: ```bash theme={null} chamber chat "what's the status of my latest training job?" ``` ```bash theme={null} chamber chat "which teams have the highest GPU utilization this week?" ``` ### Interactive Conversation Run `chamber chat` without arguments to start a multi-turn conversation: ```bash theme={null} $ chamber chat Chamber AI Assistant Type /help for commands, /quit to exit > what jobs are currently running? You have 3 jobs running: • gpt-finetune-v2 — 8x H100, running for 2h 15m • embedding-train — 4x A100, running for 45m • llm-eval — 2x H100, running for 12m > how much capacity is left in the H100 pool? The us-west-h100 pool has 16 of 64 GPUs available (75% utilized). Your team has 12 GPU-hours remaining in this billing period. > /quit ``` Interactive commands: | Command | Action | | ------------------ | --------------------------- | | `/quit` or `/exit` | End the session | | `/new` | Start a new conversation | | `/help` | Show available commands | | `Esc` or `Ctrl+C` | Cancel the current response | ### Named Conversations Use `-c` to name a conversation and resume it later: ```bash theme={null} # Start a named conversation chamber chat -c debug-job "my training job failed, can you help?" # Come back later and continue where you left off chamber chat -c debug-job "I tried your suggestion, still seeing OOM errors" ``` ### Pipe Input Pipe logs, config files, or other data into chat for analysis: ```bash theme={null} # Analyze logs kubectl logs my-training-pod | chamber chat "what errors are in these logs?" # Review a config cat .chamber.yaml | chamber chat "is this config optimized for distributed training?" ``` When stdout is piped (e.g., `chamber chat "question" | pbcopy`), streaming is automatically disabled and the full response is buffered before output. ### Image Attachments Attach an image for visual analysis: ```bash theme={null} chamber chat -i screenshot.png "what does this GPU utilization graph tell me?" ``` Supported formats: PNG, JPG, GIF, WebP. ### List Conversations View your recent chat history: ```bash theme={null} chamber chat --list ``` ## What You Can Ask The AI assistant has access to your organization's live infrastructure data. Example questions: * "What jobs are running right now?" * "Why did my training job fail?" * "Show me jobs submitted by my team this week" * "What's the average queue wait time?" * "How much GPU capacity is available?" * "When does our H100 reservation expire?" * "Which pools have spare capacity?" * "Are we at risk of hitting our budget?" * "What's our GPU utilization this week?" * "Which teams are underutilizing their allocations?" * "Show me utilization trends for the last 30 days" * "Are there any idle GPUs I can use?" * "How can I improve my training job's GPU efficiency?" * "Should I use reserved or elastic for this workload?" * "What's the best GPU type for my use case?" * "Help me right-size my resource requests" The assistant also understands Chamber CLI commands and can suggest the right command for what you're trying to do — and execute it for you with a single confirmation. ## Command Execution When the AI assistant determines that a CLI command can fulfill your request, it will suggest the command and ask for confirmation before running it locally: ```bash theme={null} $ chamber chat "run my training script in ./demo on 4 H100s" Chambie AI Assistant Thinking... ✓ I'll set that up for you. ┌ Suggested command: │ chamber run ./demo --gpus 4 --gpu-type H100 --team abc123 │ │ Run training in ./demo on 4x H100 GPUs └ Execute this command? [Y/n]: ``` Press **Enter** or type **y** to execute the command. Type **n** to skip it. This works in all modes — quick questions, interactive conversations, and piped input. A few things to know: * **Confirmation required** — The assistant always asks before executing. You stay in control. * **Local execution** — Commands run on your machine using the same `chamber` binary you're already using. * **Non-TTY mode** — When input is piped (non-interactive), suggested commands are displayed but not executed, so scripts remain safe. * **Ctrl+C** — You can cancel a running command at any time. Try asking the assistant to perform actions: "cancel workload abc123", "submit a job with 8 H100s", or "list my team's running jobs". It will translate your request into the right CLI command. ## Command Reference ```bash theme={null} chamber chat [message] [flags] ``` | Flag | Description | | -------------------- | ----------------------------------------------------------- | | `-c, --conversation` | Named conversation thread (resume later with the same name) | | `-m, --model` | AI model selection | | `-i, --image` | Attach an image file (PNG, JPG, GIF, WebP) | | `--no-stream` | Disable streaming (buffer full response before output) | | `--raw` | Disable markdown rendering in terminal | | `-l, --list` | List recent conversations | ## Output When running in a terminal, responses are rendered with formatted markdown including syntax highlighting, bold/italic text, and clickable links. Use `--raw` to disable formatting if needed. When piped to another command, streaming is disabled automatically and raw text is output: ```bash theme={null} # Copy response to clipboard chamber chat "list my running jobs" | pbcopy # Save to file chamber chat "summarize this week's utilization" > report.txt ``` # Commands Reference Source: https://docs.usechamber.io/cli/commands Complete reference for all Chamber CLI commands # Commands Reference This page documents all available Chamber CLI commands and their options. ## Global Flags These flags are available on all commands: | Flag | Description | | -------------- | ------------------------------------------------ | | `-o, --output` | Output format: `table` (default), `json`, `yaml` | | `-h, --help` | Show help for any command | ## AI Chat ### `chamber chat` Ask questions about your GPU infrastructure using natural language. The assistant can also suggest and execute CLI commands on your behalf with confirmation. See [AI Assistant](/cli/chat) for the complete guide. ```bash theme={null} # Quick question chamber chat "what jobs are running right now?" # Interactive conversation chamber chat # Named conversation (resume later) chamber chat -c my-thread "help me debug this failure" # Pipe input for analysis kubectl logs my-pod | chamber chat "what errors are in these logs?" # Attach an image chamber chat -i gpu-metrics.png "what does this graph show?" # List recent conversations chamber chat --list ``` | Flag | Description | | -------------------- | ---------------------------------------------------------------------------- | | `-c, --conversation` | Named conversation thread (alphanumeric, hyphens, underscores, max 64 chars) | | `-m, --model` | AI model selection | | `-i, --image` | Attach image file (PNG, JPG, GIF, WebP) — single-shot and piped modes only | | `--no-stream` | Buffer full response (auto-enabled when stdout is piped) | | `--raw` | Disable markdown rendering | | `-l, --list` | List recent conversations | Chat requires browser-based login (`chamber login`). API tokens (`--token`) are not supported for chat. *** ## Authentication ### `chamber login` Authenticate with Chamber. ```bash theme={null} # Browser-based login (interactive) chamber login # Token-based login (headless/scripted) chamber login --token ch.your-api-token ``` | Flag | Description | | ------------- | ---------------------------- | | `-t, --token` | API token for authentication | ### `chamber logout` Remove stored credentials. ```bash theme={null} chamber logout ``` ### `chamber whoami` Display current user information. ```bash theme={null} chamber whoami ``` Example output: ``` Email: user@example.com User ID: 550e8400-e29b-41d4-a716-446655440000 Token expires: 2024-01-15T10:30:00Z Organization: my-org-id ``` *** ## Run (Auto-Containerize) The `run` command automatically containerizes and submits your training code. See [Auto-Containerize with Run](/cli/run) for complete documentation. ### `chamber run` Auto-containerize and submit a GPU workload. ```bash theme={null} # Preview what will be generated chamber run ./my-project --gpus 4 --gpu-type H100 --team --dry-run # Build, push, and submit chamber run ./my-project --gpus 4 --gpu-type H100 --team # With custom entrypoint chamber run ./my-project \ --gpus 8 \ --gpu-type H100 \ --team \ --entrypoint train.py \ --entrypoint-args "--config config.yaml" # Use reserved capacity chamber run ./my-project --gpus 4 --gpu-type H100 --team --class RESERVED ``` | Flag | Description | | ------------------- | --------------------------------------- | | `--team, -t` | Team ID (required) | | `--gpus, -g` | Number of GPUs | | `--gpu-type` | GPU type: `H100`, `A100`, `L40S`, etc. | | `--class, -c` | Workload class: `RESERVED` or `ELASTIC` | | `--name, -n` | Workload name | | `--entrypoint` | Override detected Python entrypoint | | `--entrypoint-args` | Arguments for the entrypoint | | `--registry` | Container registry URL | | `--dockerfile` | Use existing Dockerfile | | `--dry-run` | Preview without building/submitting | | `--save-dockerfile` | Save generated Dockerfile | | `--save-manifest` | Save generated K8s manifest | | `--no-cache` | Force Docker rebuild | Use `--dry-run` to preview the generated Dockerfile and manifest before submitting. **Prerequisites:** Docker, AWS CLI (for ECR). See [Auto-Containerize with Run](/cli/run) for setup instructions. *** ## Workloads Manage GPU workloads. Aliases: `wl`, `jobs` ### `chamber workloads list` List workloads with optional filters. ```bash theme={null} # List all workloads chamber workloads list # Filter by status chamber workloads list --status RUNNING # Filter by initiative chamber workloads list --initiative abc123 # Limit results chamber workloads list --limit 50 # Output as JSON chamber workloads list -o json ``` | Flag | Description | | ------------------ | ------------------------------------------------------------------------------------------------- | | `-s, --status` | Filter by status: `PENDING`, `QUEUED`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED`, `PREEMPTED` | | `-i, --initiative` | Filter by team ID | | `--submitted-by` | Filter by submitter user ID | | `-l, --limit` | Maximum results (1-100, default: 20) | Example output: ``` ID Name Status GPUs Type Class Submitted -------- ---------------------- -------- ---- ---- -------- ---------------- a1b2c3d4 gpt-finetune-v2 RUNNING 8 H100 RESERVED 2024-01-15T09:30 e5f6g7h8 embedding-training QUEUED 4 A100 ELASTIC 2024-01-15T09:15 ``` ### `chamber workloads get` Get detailed information about a specific workload. ```bash theme={null} chamber workloads get # Output as JSON chamber workloads get -o json ``` Example output: ``` ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890 Name: gpt-finetune-v2 Status: RUNNING Workload Class: RESERVED Priority: 75 GPUs: 8 x H100 Initiative: ml-training-team Submitted By: user@example.com Submitted At: 2024-01-15T09:30:00Z Started At: 2024-01-15T09:32:15Z ``` ### `chamber workloads stats` Get aggregated workload statistics. ```bash theme={null} # Default: last 7 days chamber workloads stats # Custom time range chamber workloads stats --time-range last_30_days # Group by submitter chamber workloads stats --group-by submitted_by ``` | Flag | Description | | -------------- | --------------------------------------------------------------------------------------- | | `--time-range` | Time range: `today`, `this_week`, `this_month`, `last_7_days` (default), `last_30_days` | | `--group-by` | Group results by: `submitted_by`, `initiative_id`, `instance_type` | ### `chamber workloads metrics` Get GPU metrics for a running workload. ```bash theme={null} chamber workloads metrics ``` Example output: ``` GPU Metrics: Metric Current Avg Min Max --------------- ------- ---- ---- ---- Utilization (%) 92.5 88.3 45.0 98.0 Memory (%) 78.2 75.1 60.0 82.0 Temperature (C) 72 68 55 76 Power (W) 420 385 250 450 ``` ### `chamber workloads cancel` Cancel a running or queued workload. ```bash theme={null} chamber workloads cancel ``` *** ## Submit Workloads ### `chamber submit` Submit a new GPU workload. ```bash theme={null} # Interactive mode chamber submit -i # With flags chamber submit \ --name "my-training-job" \ --gpus 8 \ --gpu-type H100 \ --class RESERVED \ --initiative abc123 # With Kubernetes manifest chamber submit \ --name "custom-job" \ --gpus 4 \ --gpu-type A100 \ --class ELASTIC \ --initiative abc123 \ --manifest job.yaml # Using a template chamber submit \ --name "my-job" \ --initiative abc123 \ --template template-id ``` | Flag | Description | | ------------------- | --------------------------------------------------------------- | | `-n, --name` | Workload name (required) | | `--initiative` | Team ID (required) | | `-g, --gpus` | Number of GPUs | | `--gpu-type` | GPU type: `H100`, `A100`, etc. (required unless using template) | | `-c, --class` | Workload class: `RESERVED` or `ELASTIC` (default: `ELASTIC`) | | `-p, --priority` | Priority: `critical`, `high`, `normal`, `low`, `background` | | `--external-id` | Your own workload identifier | | `-m, --manifest` | Path to Kubernetes manifest YAML | | `--template` | Use a template instead of specifying flags | | `--scaling-mode` | `gang` or `elastic` (default: `gang`) | | `--pods` | Number of pods for distributed training | | `--gpus-per-pod` | GPUs per pod (manual distribution) | | `--min-pods` | Minimum pods for elastic scaling | | `-i, --interactive` | Interactive mode with prompts | Use `--class RESERVED` for guaranteed capacity that won't be preempted. Use `--class ELASTIC` for lower-priority workloads that can run on spare capacity. *** ## Capacity ### `chamber capacity` View capacity pools and budget information. ```bash theme={null} chamber capacity # Output as JSON chamber capacity -o json ``` Example output: ``` Budget: Allocated: 10000 GPU-hours Used: 4500 GPU-hours Available: 5500 GPU-hours Capacity Pools: ID Name GPU Type Total Used Available -------- ---------------- -------- ----- ---- --------- pool-001 us-west-h100 H100 64 48 16 pool-002 us-east-a100 A100 128 96 32 ``` *** ## Teams Manage teams. Aliases: `team`, `initiatives` ### `chamber teams list` List all teams you have access to. ```bash theme={null} # List all teams chamber teams list # Output as JSON chamber teams list -o json ``` Example output: ``` ID Name Description Parent -------- ------------------- --------------------------- -------- team-001 ML Research Main ML research team - team-002 NLP Projects Natural language processing team-001 team-003 Computer Vision CV and image processing team-001 ``` ### `chamber teams get` Get detailed information about a specific team. ```bash theme={null} chamber teams get ``` ### `chamber teams create` Create a new team or sub-team. ```bash theme={null} # Create a root team (requires ORG_ADMIN) chamber teams create --name "New Team" --description "Team description" # Create a sub-team under an existing team chamber teams create --name "Sub Team" --parent parent-team-id ``` | Flag | Description | | --------------- | --------------------------------------- | | `--name` | Team name (required) | | `--description` | Team description | | `--parent` | Parent team ID (for creating sub-teams) | Creating root-level teams requires ORG\_ADMIN permissions. Sub-teams can be created by team members. *** ## Allocations Manage capacity allocations for teams. Aliases: `alloc` ### `chamber allocations list` List allocations for a team. ```bash theme={null} chamber allocations list --initiative ``` | Flag | Description | | -------------- | ------------------ | | `--initiative` | Team ID (required) | Example output: ``` ID Reservation Instances Status Expires ---------- ------------- --------- ------- ---------------- alloc-001 res-h100-west 4 ACTIVE 2024-06-30T23:59 alloc-002 res-a100-east 8 ACTIVE 2024-12-31T23:59 ``` ### `chamber allocations get` Get detailed information about a specific allocation. ```bash theme={null} chamber allocations get ``` ### `chamber allocations create` Create a new allocation for a team. Requires ORG\_ADMIN permissions. ```bash theme={null} chamber allocations create \ --initiative \ --reservation \ --instances 4 ``` | Flag | Description | | --------------- | ------------------------------------------ | | `--initiative` | Team ID (required) | | `--reservation` | Reservation ID (required) | | `--instances` | Number of instances to allocate (required) | *** ## Templates Manage reusable workload templates. Aliases: `template`, `tpl` ### `chamber templates list` List available templates. ```bash theme={null} # List all templates chamber templates list # Filter by name chamber templates list --name "training" # Filter by scope chamber templates list --scope ORGANIZATION # Include system templates chamber templates list --include-system ``` | Flag | Description | | ------------------ | ------------------------------------------------------ | | `--name` | Filter by template name | | `--scope` | Filter by scope: `PERSONAL`, `PROJECT`, `ORGANIZATION` | | `--include-system` | Include system-provided templates | Example output: ``` ID Name Scope GPU Type GPUs ----------- -------------------- ------------ -------- ---- tpl-001 standard-training ORGANIZATION H100 8 tpl-002 inference-job ORGANIZATION A100 4 tpl-003 my-custom-template PERSONAL H100 16 ``` ### `chamber templates get` Get detailed information about a specific template. ```bash theme={null} chamber templates get ``` *** ## Artifacts (Container Images) Manage container images and artifact repositories. Aliases: `artifact`, `images` Chamber supports multiple registry types: * **Doogle** - Doogle Artifact Repository (default, managed by Chamber) * **ECR** - AWS Elastic Container Registry * **GCR** - Google Container Registry * **ACR** - Azure Container Registry ### `chamber artifacts repos list` List artifact repositories in your organization. ```bash theme={null} # List all repositories chamber artifacts repos list # Filter by registry type chamber artifacts repos list --type doogle # Output as JSON chamber artifacts repos list -o json ``` | Flag | Description | | ------------- | ------------------------------------------------------ | | `--type` | Filter by registry type: `doogle`, `ecr`, `gcr`, `acr` | | `-l, --limit` | Maximum results (default: 20) | Example output: ``` ID Name Type URI Images Created -------- ---------------- ------ ------------------------------------- ------ ---------------- repo-001 ml-training doogle doogle.usechamber.io/org123/ml-train 12 2024-01-15T09:30 repo-002 inference-models ecr 123456.dkr.ecr.us-east-1.amazonaws.com 5 2024-01-10T14:20 ``` ### `chamber artifacts repos get` Get detailed information about a specific repository. ```bash theme={null} chamber artifacts repos get chamber artifacts repos get -o json ``` ### `chamber artifacts repos create` Create a new artifact repository. ```bash theme={null} # Create a Doogle repository (recommended) chamber artifacts repos create --name my-models # Create with description chamber artifacts repos create --name training-images --description "Training container images" # Create ECR repository chamber artifacts repos create --name my-ecr-repo --type ecr ``` | Flag | Description | | ------------------- | ------------------------------------------------------ | | `-n, --name` | Repository name (required) | | `-d, --description` | Repository description | | `--type` | Registry type: `doogle` (default), `ecr`, `gcr`, `acr` | Use Doogle Artifact Repository for a fully managed experience with no additional cloud setup required. ### `chamber artifacts repos delete` Delete an artifact repository. ```bash theme={null} chamber artifacts repos delete ``` This will delete all images in the repository. This action cannot be undone. ### `chamber artifacts list` List container images in a repository. ```bash theme={null} # List images in a repository chamber artifacts list --repo # Filter by tag chamber artifacts list --repo --tag latest # Output as JSON chamber artifacts list --repo -o json ``` | Flag | Description | | ------------- | ----------------------------- | | `-r, --repo` | Repository ID (required) | | `-t, --tag` | Filter by image tag | | `-l, --limit` | Maximum results (default: 20) | Example output: ``` Digest Tags Size Pushed At -------------------- ------------ -------- ---------------- sha256:a1b2c3d4... latest, v1.2 1.2 GB 2024-01-15T10:30 sha256:e5f6g7h8... v1.1 1.1 GB 2024-01-14T09:15 sha256:i9j0k1l2... 980 MB 2024-01-13T14:45 ``` ### `chamber artifacts get` Get detailed information about a specific artifact (image). ```bash theme={null} chamber artifacts get chamber artifacts get -o json ``` ### `chamber artifacts delete` Delete an artifact (image) from a repository. ```bash theme={null} chamber artifacts delete ``` ### `chamber artifacts login` Get Docker login credentials for pushing/pulling images. ```bash theme={null} # Get credentials chamber artifacts login # Get credentials for a specific repository chamber artifacts login # Output docker login command (can be piped to sh) chamber artifacts login --docker # Login directly with Docker chamber artifacts login --docker | sh ``` | Flag | Description | | ---------- | -------------------------------- | | `--docker` | Output full docker login command | Example output: ``` Registry: doogle.usechamber.io Username: chamber Password: eyJhbGc... Expires At: 2024-01-15T16:30:00Z To login with Docker: docker login -u chamber -p doogle.usechamber.io ``` *** ## Metrics ### `chamber metrics` View organization-wide GPU metrics. ```bash theme={null} # Default: last 24 hours chamber metrics # Filter by team chamber metrics --initiative # Custom time range chamber metrics --time-range last_7d # Group by team chamber metrics --group-by team # Output as JSON chamber metrics -o json ``` | Flag | Description | | -------------- | ----------------------------------------------------------------------------- | | `--initiative` | Filter by team ID | | `--time-range` | Time range: `last_1h`, `last_6h`, `last_24h` (default), `last_7d`, `last_30d` | | `--group-by` | Group metrics by: `team` | *** ## Configuration ### `chamber config show` Display current configuration. ```bash theme={null} chamber config show ``` ### `chamber config get` Get a specific configuration value. ```bash theme={null} chamber config get organization_id chamber config get api_url ``` ### `chamber config set` Set a configuration value. ```bash theme={null} chamber config set organization_id your-org-id chamber config set api_url https://api.usechamber.io/v1 ``` | Key | Description | | ----------------- | ------------------------------------- | | `organization_id` | Default organization for API requests | | `api_url` | Chamber API URL | *** ## System ### `chamber health` Check API health status. ```bash theme={null} chamber health ``` ### `chamber completion` Generate shell completion scripts. ```bash theme={null} chamber completion bash chamber completion zsh chamber completion fish ``` *** ## JSON Output All commands support `-o json` for machine-readable output: ```bash theme={null} # Get workloads as JSON chamber workloads list -o json # Pipe to jq for filtering chamber workloads list -o json | jq '.[] | select(.status == "RUNNING")' # Use in scripts WORKLOAD_ID=$(chamber workloads list -o json | jq -r '.[0].id') ``` **Early Access** — The Chamber CLI is currently in early access. Contact [support@usechamber.io](mailto:support@usechamber.io) to get started. # Configuration Source: https://docs.usechamber.io/cli/configuration Configure the Chamber CLI settings and credentials # Configuration The Chamber CLI stores configuration and credentials in `~/.chamber/`. ## Configuration Files | File | Purpose | | ------------------------- | --------------------------------------------------------- | | `~/.chamber/config.json` | CLI settings (API URL, organization ID, default registry) | | `~/.chamber/token.json` | Authentication credentials | | `~/.chamber/chat_history` | AI chat readline history (up to 500 entries) | The `token.json` file contains sensitive credentials. It's created with `0600` permissions (owner read/write only). Do not share or commit this file. ## Settings ### Organization ID Set your default organization for API requests: ```bash theme={null} chamber config set organization_id your-org-id ``` Most commands require an organization context. Setting this avoids having to specify it on every command. Find your organization ID in the [Chamber Dashboard](https://app.usechamber.io) under **Settings > Organization**. ### API URL By default, the CLI connects to `https://api.usechamber.io/v1`. Override this for development or private deployments: ```bash theme={null} chamber config set api_url https://your-api-endpoint.com/v1 ``` ### Default Registry Set your container registry for the `chamber run` command to avoid specifying it on every run: ```bash theme={null} chamber config set default_registry 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo ``` When using ECR, `chamber run` automatically authenticates using your AWS CLI credentials and creates the repository if it doesn't exist. ## View Configuration See all current settings: ```bash theme={null} chamber config show ``` Output: ``` Current configuration: API URL: https://api.usechamber.io/v1 Organization ID: my-org-id Default Registry: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo Config directory: /Users/you/.chamber ``` Get a specific value: ```bash theme={null} chamber config get organization_id ``` ## Environment Variables You can override configuration using environment variables: | Variable | Description | | ----------------- | ---------------------------------- | | `CHAMBER_API_URL` | Override API URL | | `CHAMBER_ORG_ID` | Override organization ID | | `CHAMBER_TOKEN` | Override authentication token | | `CHAMBER_DEBUG` | Set to `1` for verbose API logging | Example: ```bash theme={null} CHAMBER_ORG_ID=other-org chamber workloads list ``` ## Multiple Profiles For working with multiple organizations or environments, you can use shell aliases: ```bash theme={null} # In ~/.bashrc or ~/.zshrc alias chamber-prod="CHAMBER_ORG_ID=prod-org chamber" alias chamber-dev="CHAMBER_ORG_ID=dev-org CHAMBER_API_URL=https://dev-api.example.com/v1 chamber" ``` Usage: ```bash theme={null} chamber-prod workloads list chamber-dev workloads list ``` ## Reset Configuration To reset all configuration and credentials: ```bash theme={null} rm -rf ~/.chamber ``` Then re-authenticate: ```bash theme={null} chamber login --token ch.your-api-token chamber config set organization_id your-org-id ``` ## Troubleshooting ### "Not logged in" error ``` Error: not logged in - run 'chamber login' first ``` Your token may have expired or been deleted. Re-authenticate: ```bash theme={null} chamber login --token ch.your-api-token ``` ### "No organization configured" error ``` Error: no organization configured - run 'chamber config set organization_id ' ``` Set your organization: ```bash theme={null} chamber config set organization_id your-org-id ``` ### Check your setup Verify everything is configured correctly: ```bash theme={null} # Check health chamber health # Check authentication chamber whoami # Check configuration chamber config show ``` **Early Access** — The Chamber CLI is currently in early access. Contact [support@usechamber.io](mailto:support@usechamber.io) to get started. # Installation Source: https://docs.usechamber.io/cli/installation Install Chamber CLI in seconds and submit your first GPU workload # Installation The Chamber CLI is currently in early access. Contact [support@usechamber.io](mailto:support@usechamber.io) to get access. ## First-Time Setup **Chamber guides you through everything.** Just run `chamber login` and follow the prompts. No manual configuration required. ### Step 1: Login ```bash theme={null} chamber login ``` This opens your browser to authenticate. After logging in, you're automatically configured. For CI/CD or headless servers, use token-based auth: ```bash theme={null} chamber login --token ch.your-api-token ``` Generate tokens in the [Chamber Dashboard](https://app.usechamber.io) under **Settings > API Tokens**. The [AI Assistant](/cli/chat) (`chamber chat`) requires browser-based login and does not support API tokens. ### Step 2: Verify ```bash theme={null} chamber whoami ``` That's it! You're ready to submit workloads. ## Submit Your First Workload Navigate to your training code and run: ```bash theme={null} chamber run ./my-training-project --gpus 4 --team --dry-run ``` **First time?** The `--dry-run` flag shows you exactly what Chamber will generate without actually building or submitting. Remove it when you're ready to run for real. ### What happens next If it's your first time, Chamber will interactively guide you through: 1. **Registry setup** — Choose Google Artifact Registry, AWS ECR, or another registry 2. **Docker installation** — If Docker isn't installed, Chamber offers to help 3. **Cloud CLI setup** — If AWS CLI or gcloud isn't configured, Chamber walks you through it ``` $ chamber run ./my-project --gpus 4 --team abc123 No container registry configured Chamber needs a container registry to store your Docker images. Select your registry type: [1] Google Artifact Registry (recommended for GCP users) [2] AWS ECR (recommended for AWS users) [3] Other Docker registry Select an option [1]: ``` After the one-time setup, future runs are instant: ```bash theme={null} # This just works now chamber run ./my-project --gpus 4 --team abc123 ``` ## Optional: Set Your Organization If you belong to multiple organizations, set a default: ```bash theme={null} chamber config set organization_id your-org-id ``` Find your organization ID in the [Chamber Dashboard](https://app.usechamber.io) under **Settings > Organization**. ## Shell Completion Enable tab completion for faster workflows: ```bash theme={null} # Add to ~/.bashrc source <(chamber completion bash) ``` ```bash theme={null} # Add to ~/.zshrc source <(chamber completion zsh) ``` ```bash theme={null} chamber completion fish | source ``` ## Next Steps Ask about workloads, capacity, and more Submit training jobs with `chamber run` Explore all available commands # CLI Overview Source: https://docs.usechamber.io/cli/introduction Submit GPU workloads in seconds — no Docker or Kubernetes expertise required ![Build](https://github.com/ChamberOrg/chamber-cli/actions/workflows/test.yml/badge.svg?branch=main) ![Coverage](https://codecov.io/gh/ChamberOrg/chamber-cli/branch/main/graph/badge.svg) # Chamber CLI **Go from Python code to running GPU workload in one command.** The Chamber CLI eliminates the complexity of containerization, registry management, and Kubernetes — so ML engineers and data scientists can focus on what matters: training models. **No Docker expertise required.** Chamber auto-detects your project, generates optimized Dockerfiles, handles registry authentication, and submits your workload — all interactively guided. ## AI Assistant — Ask Your Infrastructure Anything Query your GPU infrastructure in natural language, directly from the terminal: ```bash theme={null} chamber chat "how many GPUs are running right now?" ``` Start an interactive conversation for back-and-forth troubleshooting, capacity planning, or workload analysis: ```bash theme={null} chamber chat ``` Interactive conversations, command execution, piped input, image analysis, and more Deep dive into `chamber run` ## The Fastest Path to GPU Training ```bash theme={null} chamber run ./my-training-project --gpus 4 --team my-team ``` That's it. One command. Chamber handles everything else: Automatically identifies PyTorch, TensorFlow, or JAX. Finds your entrypoint and requirements. Creates a GPU-optimized container with CUDA, cuDNN, and your dependencies. Missing Docker? No registry configured? Chamber walks you through each step interactively. Handles authentication, builds your image, pushes to your registry, and submits to Chamber. Install and run your first workload ## Interactive Setup — No Prior Configuration Needed Chamber CLI guides you through everything. Don't have Docker? It'll help you install it. No registry configured? It'll walk you through setting one up: ``` $ chamber run ./my-training --gpus 4 --team abc123 No container registry configured Chamber needs a container registry to store your Docker images. You can use Google Artifact Registry, AWS ECR, or any Docker-compatible registry. Select your registry type: [1] Google Artifact Registry (recommended for GCP users) Example: us-central1-docker.pkg.dev/my-project/ml-images [2] AWS ECR (recommended for AWS users) Example: 123456789012.dkr.ecr.us-east-1.amazonaws.com/ml-images [3] Other Docker registry Select an option [1]: 1 Google Artifact Registry Setup Enter your GAR registry URL: us-central1-docker.pkg.dev/my-project/ml-images Save as default registry? (y/n) [y]: y Default registry saved to ~/.chamber/config.json [detect] Analyzing project structure... [detect] Framework: PyTorch [detect] Entrypoint: train.py [setup] Checking prerequisites... ``` **First-time users:** Just run `chamber run` on your project. The CLI will guide you through every step — from installing Docker to configuring your registry to submitting your workload. ## Automatic Prerequisite Detection Missing a tool? Chamber detects it and offers to help: ``` $ chamber run ./my-project --gpus 4 --team abc123 ⚠ Docker is not installed Docker is required to build and push container images. Installation options: [1] Quick install (recommended) brew install --cask docker [2] Open installation guide in browser [3] Show manual installation instructions [4] Skip (continue anyway) Select an option [1]: ``` The same guided experience applies to: * **Docker** — Required for building images * **AWS CLI** — For ECR authentication * **gcloud CLI** — For Google Artifact Registry authentication * **Azure CLI** — For ACR authentication ## Why ML Engineers Love Chamber CLI Run `chamber run` and follow the prompts. No YAML files, no Docker knowledge needed. Auto-detects frameworks, entrypoints, and optimal GPU configurations. Configure once, run forever. Settings are saved for future use. Use `--dry-run` to see exactly what will be generated before building. Single binary with no dependencies. SSH-friendly for remote workstations. JSON output mode for CI/CD pipelines and automation. ## Quick Command Reference | What you want to do | Command | | ------------------------------ | ----------------------------------------------- | | **Ask a question** | `chamber chat "what GPUs are available?"` | | **Start a conversation** | `chamber chat` | | **Submit a training workload** | `chamber run ./my-project --gpus 4 --team ` | | Preview before submitting | `chamber run ./my-project --gpus 4 --dry-run` | | List your workloads | `chamber workloads list` | | Check GPU capacity | `chamber capacity` | | View workload status | `chamber workloads get ` | | Cancel a workload | `chamber workloads cancel ` | ## System Requirements * **macOS** (Intel or Apple Silicon) or **Linux** (x86\_64 or ARM64) * A Chamber account **For auto-containerization (`chamber run`):** * Docker — *Chamber will help you install it* * Cloud CLI (gcloud/aws/az) — *Chamber will help you install it* Install Chamber CLI and run your first workload # Auto-Containerize & Run Source: https://docs.usechamber.io/cli/run Submit GPU workloads with one command — no Docker or Kubernetes expertise needed **Coming Soon — Fully Managed GPU Infrastructure** We're building automated infrastructure management across cloud providers so your research and MLE teams can run GPU workloads directly in their own cloud accounts without ever thinking about infrastructure. If you'd like early access or want to learn more, reach out at [support@usechamber.io](mailto:support@usechamber.io). # Auto-Containerize with `chamber run` **One command. That's all it takes.** Point `chamber run` at your training code and it handles everything: containerization, registry authentication, image building, and workload submission. ```bash theme={null} chamber run ./my-training-project --gpus 4 --team my-team ``` **No Docker knowledge required.** Chamber auto-detects your project structure, generates optimized Dockerfiles, and guides you through any missing prerequisites. ## What Chamber Does For You Scans for PyTorch, TensorFlow, or JAX. Finds `train.py`, `main.py`, or your entrypoint. Reads `requirements.txt` or `pyproject.toml`. Creates a GPU-optimized container with the right CUDA version, cuDNN, and your dependencies pre-installed. Auto-authenticates with Google Artifact Registry or AWS ECR using your existing cloud credentials. Uses `docker buildx build --push` to build and push in a single efficient step. Automatically pulls the `:latest` tag to seed the layer cache so teammates get fast rebuilds. Uses content-addressed image tags — if the image already exists, build and push are skipped entirely. Creates and submits a Kubernetes job to Chamber with your GPU and resource requirements. ## Quick Start ```bash theme={null} # Preview what will be generated (recommended first step) chamber run ./my-training-project --gpus 4 --team --dry-run # Build, push, and submit the workload chamber run ./my-training-project --gpus 4 --team ``` **Always use `--dry-run` first** to preview the generated Dockerfile and Kubernetes manifest before building. ## Interactive Setup (First-Time Users) Chamber guides you through everything. Missing something? Chamber will help: ### No Registry Configured? ``` $ chamber run ./my-project --gpus 4 --team abc123 No container registry configured Chamber needs a container registry to store your Docker images. You can use Google Artifact Registry, AWS ECR, or any Docker-compatible registry. Select your registry type: [1] Google Artifact Registry (recommended for GCP users) Example: us-central1-docker.pkg.dev/my-project/ml-images [2] AWS ECR (recommended for AWS users) Example: 123456789012.dkr.ecr.us-east-1.amazonaws.com/ml-images [3] Other Docker registry Select an option [1]: 1 Google Artifact Registry Setup Enter your GAR registry URL: us-central1-docker.pkg.dev/my-project/ml-images Save as default registry? (y/n) [y]: y Default registry saved to ~/.chamber/config.json ``` ### Docker Not Installed? ``` ⚠ Docker is not installed Docker is required to build and push container images. Installation options: [1] Quick install (recommended) brew install --cask docker [2] Open installation guide in browser [3] Show manual installation instructions [4] Skip (continue anyway) Select an option [1]: ``` ### AWS CLI Not Configured? ``` ⚠ AWS CLI is not authenticated You need AWS credentials to push images to ECR. Options: [1] Run 'aws configure' interactively (recommended) [2] Set environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) [3] Show me how to get credentials [4] Skip (I'll handle authentication myself) Select an option [1]: ``` **One-time setup.** After your first successful run, these settings are saved. Future runs work instantly without prompts. ## Supported Container Registries Chamber automatically handles authentication for major cloud registries: | Registry | URL Pattern | Auto-Auth | | ---------------------------- | ------------------------------------------ | ------------------ | | **Google Artifact Registry** | `{region}-docker.pkg.dev/{project}/{repo}` | gcloud CLI | | **AWS ECR** | `{account}.dkr.ecr.{region}.amazonaws.com` | AWS CLI | | **Other registries** | Any Docker-compatible registry | Via `docker login` | ## Project Detection Chamber automatically detects your project configuration: | What | How | | ------------------------ | -------------------------------------------------------- | | **Framework** | Scans `requirements.txt` for PyTorch, TensorFlow, or JAX | | **Entrypoint** | Looks for `train.py`, `main.py`, `run.py`, or `app.py` | | **Python Version** | Checks `.python-version` or `pyproject.toml` | | **Distributed Training** | Detects Accelerate, DeepSpeed, Ray, or Horovod | | **Requirements** | Uses `requirements.txt`, `pyproject.toml`, or `setup.py` | ## Project Configuration Create a `.chamber.yaml` file for persistent settings (optional): ```yaml theme={null} # .chamber.yaml name: "llm-finetune" entrypoint: "train.py" entrypoint_args: "--config config.yaml --epochs 100" # Resources gpu_type: "H100" gpus: 4 job_class: "ELASTIC" # Environment variables injected into the container env: WANDB_PROJECT: "my-project" NCCL_DEBUG: "INFO" # Forward these local env vars to container (if set) forward_env: - WANDB_API_KEY - HF_TOKEN # Files to exclude from Docker build context ignore: - "output/" - "checkpoints/" - "*.bin" - "*.safetensors" ``` CLI flags always override `.chamber.yaml` values, so you can set defaults while still customizing per-run. ## Command Reference ```bash theme={null} chamber run [flags] ``` ### Required Flags | Flag | Description | | ------------ | ------------------------ | | `--team, -t` | Team ID for the workload | ### Resource Flags | Flag | Default | Description | | ------------- | ------------------- | --------------------------------------- | | `--gpus, -g` | From config or 1 | Number of GPUs | | `--gpu-type` | From config or H100 | GPU type (H100, A100, L40S, etc.) | | `--class, -c` | ELASTIC | Workload class: `RESERVED` or `ELASTIC` | ### Container Flags | Flag | Description | | -------------- | --------------------------------------------------------- | | `--registry` | Container registry URL (or use `default_registry` config) | | `--base-image` | Override the auto-detected base image | | `--dockerfile` | Use an existing Dockerfile instead of generating one | | `--no-cache` | Force Docker rebuild without cache | ### Entrypoint Flags | Flag | Description | | ------------------- | ------------------------------------------------------ | | `--name, -n` | Workload name (default: from config or directory name) | | `--entrypoint` | Override detected Python entrypoint | | `--entrypoint-args` | Arguments to pass to the entrypoint | | `--env` | Environment variable KEY=VALUE (repeatable) | ### Workflow Flags | Flag | Description | | ------------------- | ------------------------------------------------- | | `--dry-run` | Preview generated artifacts without executing | | `--save-dockerfile` | Write generated Dockerfile to project directory | | `--save-manifest` | Write generated K8s manifest to project directory | ## Examples ### Basic Training Workload ```bash theme={null} chamber run ./my-project --gpus 4 --gpu-type H100 --team abc123 ``` ### Custom Entrypoint with Arguments ```bash theme={null} chamber run ./my-project \ --gpus 8 \ --gpu-type H100 \ --team abc123 \ --entrypoint train.py \ --entrypoint-args "--config config.yaml --lr 1e-4 --batch-size 32" ``` ### With Environment Variables ```bash theme={null} chamber run ./my-project \ --gpus 4 \ --gpu-type H100 \ --team abc123 \ --env WANDB_API_KEY=$WANDB_API_KEY \ --env HF_TOKEN=$HF_TOKEN ``` ### Reserved (Non-Preemptible) Capacity ```bash theme={null} chamber run ./my-project \ --gpus 4 \ --gpu-type H100 \ --team abc123 \ --class RESERVED ``` ### Using Your Own Dockerfile ```bash theme={null} chamber run ./my-project \ --gpus 4 \ --gpu-type H100 \ --team abc123 \ --dockerfile Dockerfile.custom ``` ## Generated Artifacts ### Example Dockerfile For a PyTorch project with Accelerate, Chamber generates: ```dockerfile theme={null} # syntax=docker/dockerfile:1 # Auto-generated by Chamber CLI FROM nvcr.io/nvidia/pytorch:24.04-py3 WORKDIR /workspace COPY requirements.txt . RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt COPY . . CMD ["accelerate", "launch", "train.py", "--config", "config.yaml"] ``` Chamber uses [BuildKit](https://docs.docker.com/build/buildkit/) with pip cache mounts, so repeated builds reuse cached Python packages instead of re-downloading them. ### Example Kubernetes Manifest ```yaml theme={null} apiVersion: batch/v1 kind: Job metadata: name: llm-finetune-a1b2c3d4 spec: backoffLimit: 0 template: spec: restartPolicy: Never containers: - name: training image: us-central1-docker.pkg.dev/my-project/ml-images:abc123 resources: requests: nvidia.com/gpu: "4" limits: nvidia.com/gpu: "4" env: - name: "WANDB_PROJECT" value: "my-project" ``` ## Troubleshooting Chamber will prompt you with installation options: ``` ⚠ Docker is not installed Installation options: [1] Quick install (recommended) [2] Open installation guide in browser [3] Show manual installation instructions ``` Select an option and follow the prompts. If auto-authentication fails: **For Google Artifact Registry:** ```bash theme={null} gcloud auth login gcloud auth configure-docker {region}-docker.pkg.dev ``` **For AWS ECR:** ```bash theme={null} aws configure # Or set environment variables: export AWS_ACCESS_KEY_ID=your-key export AWS_SECRET_ACCESS_KEY=your-secret ``` Check your `requirements.txt` is complete. Use `--dry-run` to preview the Dockerfile: ```bash theme={null} chamber run ./my-project --dry-run ``` If needed, use `--save-dockerfile` to inspect and modify: ```bash theme={null} chamber run ./my-project --dry-run --save-dockerfile # Edit Dockerfile.chamber chamber run ./my-project --dockerfile Dockerfile.chamber ``` ## Docker Build Optimizations Chamber automatically applies several optimizations to make builds fast: | Optimization | What it does | | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Single build+push** | Uses `docker buildx build --push` to build and push in one step. This is significantly faster than separate build+push because buildkit pushes layers directly as they complete, avoiding Docker daemon/containerd manifest duplication issues | | **BuildKit** | Enabled by default (`DOCKER_BUILDKIT=1`) for parallel build stages and advanced caching | | **Pip cache mounts** | Uses `--mount=type=cache,target=/root/.cache/pip` so pip packages are cached across builds instead of re-downloaded | | **Remote layer caching** | Pulls the `:latest` tag from your registry before building to seed the local layer cache. After a successful build, tags as `:latest` using `docker buildx imagetools create` (fast manifest aliasing, no layer re-upload) so future builds benefit | | **Content-addressed tags** | Images are tagged with a content hash of your project. If the image already exists in the registry, build and push are skipped entirely | | **Platform targeting** | Explicitly builds for `linux/amd64` to ensure consistent images regardless of your local architecture | | **Reduced metadata** | Uses `--provenance=false --sbom=false` to skip unnecessary metadata generation that slows down builds | | **Context size warnings** | Reports build context size and warns if it exceeds 500MB, helping you identify large files that should be in `.dockerignore` | | **Streaming output** | Build output is streamed to your terminal in real-time so you can follow progress | **Why single build+push matters:** With Docker Desktop's containerd image store, a separate `docker push` can push ALL manifests from multi-platform base images (e.g., 6 manifests for NVIDIA images), causing each layer to be checked 6 times. The `buildx build --push` approach only pushes what it built — making pushes dramatically faster, especially for large ML images. Use `--no-cache` to force a full Docker rebuild (this does not force re-push if the image already exists): ```bash theme={null} chamber run ./my-project --gpus 4 --team abc123 --no-cache ``` ## Best Practices Always preview generated artifacts before building to catch issues early. Store project-specific settings to avoid repeating flags on every run. Configure your registry once: `chamber config set default_registry ` Securely inject API keys without hardcoding them in your config. # AWS EKS Source: https://docs.usechamber.io/cluster-deployment/aws-eks Deploy a GPU-ready EKS cluster with Chamber on AWS The [`terraform-aws-chamber-eks`](https://github.com/ChamberOrg/terraform-aws-chamber-eks) module deploys a production-ready Amazon EKS cluster with GPU autoscaling, NVIDIA drivers, and the Chamber Agent — all in a single `terraform apply`. ## Prerequisites Install from [developer.hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install). Verify with `terraform version`. The AWS provider uses your local credentials. Verify with `aws sts get-caller-identity`. You need a cluster token and cluster ID from the [Chamber Console](https://app.usechamber.io). See [Getting a Cluster Token](/agent/installation#getting-a-cluster-token) for instructions. ## Quick Start Create a new directory for your Terraform configuration and add a `main.tf` file: ```hcl theme={null} provider "aws" { region = var.aws_region } module "chamber_eks" { source = "github.com/ChamberOrg/terraform-aws-chamber-eks" cluster_name = "my-gpu-cluster" aws_region = var.aws_region chamber_cluster_token = var.chamber_cluster_token chamber_cluster_id = var.chamber_cluster_id } variable "aws_region" { type = string } variable "chamber_cluster_token" { type = string sensitive = true } variable "chamber_cluster_id" { type = string } output "configure_kubectl" { value = module.chamber_eks.configure_kubectl } ``` ```hcl theme={null} aws_region = "us-west-2" chamber_cluster_token = "your-token-here" chamber_cluster_id = "your-cluster-id" ``` Do not commit `terraform.tfvars` to version control. Add it to `.gitignore`. For CI/CD pipelines, use environment variables: `TF_VAR_chamber_cluster_token`. ```bash theme={null} terraform init terraform plan terraform apply ``` Deployment takes approximately **15-20 minutes**. ```bash theme={null} $(terraform output -raw configure_kubectl) ``` ```bash theme={null} # Verify system nodes are ready kubectl get nodes # Verify Karpenter is running kubectl get pods -n karpenter # Verify Chamber Agent is connected kubectl get pods -n chamber-system ``` Your cluster should appear in the [Chamber Console](https://app.usechamber.io) under **Capacity Pools**. ## Using an Existing VPC To deploy into an existing VPC instead of creating a new one: ```hcl theme={null} module "chamber_eks" { source = "github.com/ChamberOrg/terraform-aws-chamber-eks" cluster_name = "my-gpu-cluster" aws_region = var.aws_region chamber_cluster_token = var.chamber_cluster_token chamber_cluster_id = var.chamber_cluster_id create_vpc = false vpc_id = "vpc-xxxxxxxx" private_subnet_ids = ["subnet-aaa", "subnet-bbb", "subnet-ccc"] } ``` Private subnets must have outbound internet access (via NAT Gateway) for nodes to pull container images and connect to the Chamber control plane. ## Key Variables The table below covers the most commonly configured variables. For the complete list, see the [module README on GitHub](https://github.com/ChamberOrg/terraform-aws-chamber-eks#inputs). ### Required | Variable | Description | Type | | ----------------------- | ---------------------------------- | -------- | | `cluster_name` | Name of the EKS cluster | `string` | | `chamber_cluster_token` | Cluster token from Chamber Console | `string` | | `chamber_cluster_id` | Cluster ID from Chamber Console | `string` | ### AWS | Variable | Description | Default | | ------------ | ------------------------------ | ------------- | | `aws_region` | AWS region for the EKS cluster | `"us-west-2"` | ### VPC | Variable | Description | Default | | -------------------- | ---------------------------------------------------------------- | --------------- | | `create_vpc` | Create a new VPC or use existing | `true` | | `vpc_id` | Existing VPC ID (required when `create_vpc = false`) | `null` | | `private_subnet_ids` | Existing private subnet IDs (required when `create_vpc = false`) | `[]` | | `vpc_cidr` | CIDR block for new VPC | `"10.0.0.0/16"` | | `single_nat_gateway` | Use a single NAT gateway (cost savings for dev/staging) | `false` | ### EKS | Variable | Description | Default | | ---------------------------- | ------------------------------------ | ---------------------------------------- | | `cluster_version` | Kubernetes version | `"1.32"` | | `system_node_instance_types` | Instance types for system node group | `["m5.large", "m5a.large", "m6i.large"]` | ### GPU | Variable | Description | Default | | ----------------------------- | ------------------------------------- | --------------------------- | | `create_default_gpu_nodepool` | Create Terraform-managed GPU NodePool | `false` | | `gpu_instance_families` | GPU instance families for NodePool | `["g5", "g6", "p4d", "p5"]` | | `capacity_types` | Capacity types (`on-demand`, `spot`) | `["on-demand", "spot"]` | | `gpu_limits` | Maximum GPUs for NodePool | `100` | ### Chamber | Variable | Description | Default | | ----------------------- | ----------------------------------- | ---------- | | `chamber_agent_version` | Chamber Agent version | `"latest"` | | `enable_kai_scheduler` | Enable KAI fractional GPU scheduler | `true` | ## Key Outputs | Output | Description | | ------------------------- | --------------------------------- | | `cluster_name` | Name of the EKS cluster | | `cluster_endpoint` | EKS API server endpoint | | `vpc_id` | VPC ID | | `configure_kubectl` | Command to configure kubectl | | `verification_commands` | Commands to verify the deployment | | `karpenter_node_role_arn` | Karpenter node IAM role ARN | For all outputs, see the [module README on GitHub](https://github.com/ChamberOrg/terraform-aws-chamber-eks#outputs). ## GPU Pool Management After deployment, you need GPU pools for Karpenter to know which GPU nodes to provision. There are two approaches: Manage GPU pools through the [Chamber Console](https://app.usechamber.io): 1. Go to **Capacity Pools** > **Create Dynamic Pool** 2. Select your cluster and configure GPU type, limits, and capacity types 3. The pool syncs to your cluster automatically — Karpenter provisions GPU nodes on demand This is the recommended approach for most teams. It allows per-GPU-type management with real-time limit adjustments. To manage GPU pools entirely through Terraform, set `create_default_gpu_nodepool = true`: ```hcl theme={null} module "chamber_eks" { source = "github.com/ChamberOrg/terraform-aws-chamber-eks" # ... required variables ... create_default_gpu_nodepool = true gpu_instance_families = ["g5", "g6"] capacity_types = ["on-demand", "spot"] gpu_limits = 50 } ``` This creates a single broad NodePool covering the specified instance families. ## Troubleshooting Check the Chamber Agent logs: ```bash theme={null} kubectl logs -n chamber-system -l app=chamber-agent --tail=100 ``` Verify your `chamber_cluster_token` and `chamber_cluster_id` are correct. 1. Verify a GPU pool exists: ```bash theme={null} kubectl get nodepool ``` If none exists, create one via the Chamber Console or set `create_default_gpu_nodepool = true`. 2. Check Karpenter logs: ```bash theme={null} kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter --tail=100 ``` 3. Check for capacity errors: ```bash theme={null} kubectl get events --field-selector reason=FailedProvisioning ``` Your AWS account lacks GPU Spot quota. Either request a quota increase via the [AWS Service Quotas console](https://console.aws.amazon.com/servicequotas), or set `capacity_types = ["on-demand"]`. This is expected when no GPU nodes exist yet. GPU Operator DaemonSets start automatically when Karpenter provisions GPU nodes in response to a workload. ## Cleanup ```bash theme={null} terraform destroy ``` Ensure all GPU workloads are terminated before destroying to avoid orphaned resources. ## Next Steps Submit your first GPU workload Configure capacity pools and reservations Detailed troubleshooting guide Full source, examples, and changelog # Google Cloud GKE Source: https://docs.usechamber.io/cluster-deployment/google-gke Deploy a GPU-ready GKE cluster with Chamber on Google Cloud The [`terraform-google-chamber-gke`](https://github.com/ChamberOrg/terraform-google-chamber-gke) module deploys a production-ready Google GKE cluster with GPU autoscaling, NVIDIA drivers, and the Chamber Agent — all in a single `terraform apply`. ## Prerequisites Install from [developer.hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install). Verify with `terraform version`. Install the [gcloud CLI](https://cloud.google.com/sdk/docs/install) and authenticate: ```bash theme={null} gcloud auth login gcloud auth application-default login ``` Enable the required APIs in your project: ```bash theme={null} gcloud services enable \ container.googleapis.com \ compute.googleapis.com \ iam.googleapis.com \ --project=YOUR_PROJECT_ID ``` You need a cluster token and cluster ID from the [Chamber Console](https://app.usechamber.io). See [Getting a Cluster Token](/agent/installation#getting-a-cluster-token) for instructions. ## Quick Start The GKE module requires explicit provider configuration because the `kubernetes`, `helm`, and `kubectl` providers need the cluster endpoint and credentials from the module outputs. The full configuration is shown below. Create a new directory for your Terraform configuration and add a `main.tf` file: ```hcl theme={null} provider "google" { project = var.gcp_project_id; region = var.gcp_region } provider "google-beta" { project = var.gcp_project_id; region = var.gcp_region } data "google_client_config" "default" {} provider "kubernetes" { host = "https://${module.chamber_gke.cluster_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.chamber_gke.cluster_ca_certificate) } provider "helm" { kubernetes { host = "https://${module.chamber_gke.cluster_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.chamber_gke.cluster_ca_certificate) } } provider "kubectl" { host = "https://${module.chamber_gke.cluster_endpoint}" token = data.google_client_config.default.access_token cluster_ca_certificate = base64decode(module.chamber_gke.cluster_ca_certificate) load_config_file = false } module "chamber_gke" { source = "github.com/ChamberOrg/terraform-google-chamber-gke" gcp_project_id = var.gcp_project_id gcp_region = var.gcp_region cluster_name = "my-gpu-cluster" chamber_cluster_token = var.chamber_cluster_token chamber_cluster_id = var.chamber_cluster_id } variable "gcp_project_id" { type = string } variable "gcp_region" { type = string } variable "chamber_cluster_token" { type = string sensitive = true } variable "chamber_cluster_id" { type = string } output "configure_kubectl" { value = module.chamber_gke.configure_kubectl } ``` ```hcl theme={null} gcp_project_id = "my-gcp-project" gcp_region = "us-central1" chamber_cluster_token = "your-token-here" chamber_cluster_id = "your-cluster-id" ``` Do not commit `terraform.tfvars` to version control. Add it to `.gitignore`. For CI/CD pipelines, use environment variables: `TF_VAR_chamber_cluster_token`. ```bash theme={null} terraform init terraform plan terraform apply ``` Deployment takes approximately **15-20 minutes**. ```bash theme={null} $(terraform output -raw configure_kubectl) ``` ```bash theme={null} # Verify system nodes are ready kubectl get nodes -l purpose=system # Verify Karpenter is running kubectl get pods -n karpenter # Verify Chamber Agent is connected kubectl get pods -n chamber-system ``` Your cluster should appear in the [Chamber Console](https://app.usechamber.io) under **Capacity Pools**. ## Using an Existing VPC To deploy into an existing VPC instead of creating a new one: ```hcl theme={null} module "chamber_gke" { source = "github.com/ChamberOrg/terraform-google-chamber-gke" gcp_project_id = var.gcp_project_id gcp_region = var.gcp_region cluster_name = "my-gpu-cluster" chamber_cluster_token = var.chamber_cluster_token chamber_cluster_id = var.chamber_cluster_id create_vpc = false network_name = "my-existing-vpc" subnetwork_name = "my-existing-subnet" ip_range_pods = "pods" ip_range_services = "services" } ``` The existing subnet must have secondary IP ranges named for pods and services. Cloud NAT must be configured for private node egress. ## Key Variables The table below covers the most commonly configured variables. For the complete list, see the [module README on GitHub](https://github.com/ChamberOrg/terraform-google-chamber-gke#inputs). ### Required | Variable | Description | Type | | ----------------------- | ---------------------------------- | -------- | | `gcp_project_id` | GCP project ID | `string` | | `cluster_name` | Name of the GKE cluster | `string` | | `chamber_cluster_token` | Cluster token from Chamber Console | `string` | | `chamber_cluster_id` | Cluster ID from Chamber Console | `string` | ### GCP | Variable | Description | Default | | ------------ | --------------------------------------------- | --------------- | | `gcp_region` | GCP region for the GKE cluster | `"us-central1"` | | `gcp_zones` | Zones within the region (defaults to first 3) | `[]` | ### VPC | Variable | Description | Default | | ----------------- | --------------------------------------------------------- | --------------- | | `create_vpc` | Create a new VPC or use existing | `true` | | `network_name` | Existing VPC name (required when `create_vpc = false`) | `null` | | `subnetwork_name` | Existing subnet name (required when `create_vpc = false`) | `null` | | `vpc_cidr` | CIDR block for new VPC primary subnet | `"10.0.0.0/16"` | ### GKE | Variable | Description | Default | | -------------------------- | -------------------------------------------- | ----------------- | | `cluster_version` | Kubernetes version | `"1.32"` | | `system_node_machine_type` | Machine type for system node pool | `"e2-standard-4"` | | `enable_private_endpoint` | Private endpoint only (no public API access) | `false` | ### GPU | Variable | Description | Default | | ----------------------------- | ------------------------------------- | ------------------------------------------------------- | | `create_default_gpu_nodepool` | Create Terraform-managed GPU NodePool | `false` | | `gpu_machine_families` | GPU machine families for NodePool | `["a2", "g2", "a3"]` | | `gpu_accelerator_types` | GPU accelerator types | `["nvidia-l4", "nvidia-a100-80gb", "nvidia-h100-80gb"]` | | `capacity_types` | Capacity types (`on-demand`, `spot`) | `["on-demand", "spot"]` | | `gpu_limits` | Maximum GPUs for NodePool | `100` | ### Chamber | Variable | Description | Default | | ----------------------- | ----------------------------------- | ---------- | | `chamber_agent_version` | Chamber Agent version | `"latest"` | | `enable_kai_scheduler` | Enable KAI fractional GPU scheduler | `true` | ## Key Outputs | Output | Description | | --------------------------------- | ------------------------------------------ | | `cluster_name` | GKE cluster name | | `cluster_endpoint` | GKE API server endpoint | | `network_name` | VPC network name | | `configure_kubectl` | gcloud command to configure kubectl | | `verification_commands` | Commands to verify the deployment | | `karpenter_service_account_email` | Karpenter controller service account email | For all outputs, see the [module README on GitHub](https://github.com/ChamberOrg/terraform-google-chamber-gke#outputs). ## GPU Pool Management After deployment, you need GPU pools for Karpenter to know which GPU nodes to provision. There are two approaches: Manage GPU pools through the [Chamber Console](https://app.usechamber.io): 1. Go to **Capacity Pools** > **Create Dynamic Pool** 2. Select your cluster and configure GPU type, limits, and capacity types 3. The pool syncs to your cluster automatically — Karpenter provisions GPU nodes on demand This is the recommended approach for most teams. It allows per-GPU-type management with real-time limit adjustments. To manage GPU pools entirely through Terraform, set `create_default_gpu_nodepool = true`: ```hcl theme={null} module "chamber_gke" { source = "github.com/ChamberOrg/terraform-google-chamber-gke" # ... required variables ... create_default_gpu_nodepool = true gpu_machine_families = ["a2", "g2"] gpu_accelerator_types = ["nvidia-l4", "nvidia-a100-80gb"] capacity_types = ["on-demand", "spot"] gpu_limits = 50 } ``` This creates a single broad NodePool covering the specified machine families and accelerator types. ## Troubleshooting Check the Chamber Agent logs: ```bash theme={null} kubectl logs -n chamber-system -l app.kubernetes.io/name=chamber-agent --tail=50 ``` Verify your `chamber_cluster_token` and `chamber_cluster_id` are correct. 1. Verify a GPU pool exists: ```bash theme={null} kubectl get nodepools.karpenter.sh ``` If none exists, create one via the Chamber Console or set `create_default_gpu_nodepool = true`. 2. Check Karpenter logs: ```bash theme={null} kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter --tail=100 ``` 3. Verify GCENodeClass: ```bash theme={null} kubectl get gcenodeclasses ``` Check the KAI Scheduler logs and pod events: ```bash theme={null} kubectl logs -n chamber-system -l app=kai-scheduler --tail=50 kubectl describe pod ``` ## Cleanup ```bash theme={null} terraform destroy ``` Ensure all GPU workloads are terminated before destroying to avoid orphaned resources. ## Next Steps Submit your first GPU workload Configure capacity pools and reservations Detailed troubleshooting guide Full source, examples, and changelog # Cluster Deployment Source: https://docs.usechamber.io/cluster-deployment/overview Deploy GPU-ready Kubernetes clusters with Terraform Chamber provides Terraform modules that deploy complete GPU-ready Kubernetes clusters on AWS and Google Cloud. A single `terraform apply` creates the entire infrastructure stack — from networking to GPU workload orchestration. ## What Gets Deployed Each module provisions the full stack your team needs to run GPU workloads with Chamber: ```mermaid theme={null} flowchart TD VPC["VPC / Network"] --> K8s["Kubernetes Cluster\n(EKS or GKE)"] K8s --> System["System Node Pool"] K8s --> Karpenter["Karpenter\n(GPU Autoscaling)"] K8s --> NVIDIA["NVIDIA GPU Operator\n(Drivers & Metrics)"] K8s --> KAI["KAI Scheduler\n(Fractional GPU)"] K8s --> Agent["Chamber Agent"] Agent -->|Secure connection| Chamber["Chamber Control Plane"] ``` ## Terraform Modules vs. Helm Agent Chamber offers two ways to connect a cluster. Choose based on your starting point: | | Terraform Modules | Helm Agent Only | | ------------------- | ------------------------------------ | ------------------------------------- | | **What it creates** | Full infrastructure stack | Chamber agent only | | **Prerequisites** | Cloud provider account + Terraform | Existing Kubernetes cluster with GPUs | | **Time to deploy** | \~15-20 minutes | \~30 seconds | | **GPU autoscaling** | Included (Karpenter) | Not included | | **GPU drivers** | Included (NVIDIA GPU Operator) | Must be pre-installed | | **Best for** | New clusters, greenfield deployments | Existing clusters | Already have a Kubernetes cluster with GPU nodes? Skip the Terraform modules and [install the Chamber agent directly via Helm](/agent/installation). ## Choose Your Cloud Deploy a GPU-ready EKS cluster on Amazon Web Services Deploy a GPU-ready GKE cluster on Google Cloud Platform ## Components Both modules deploy the same core components: [Karpenter](https://karpenter.sh/) automatically provisions and deprovisions GPU nodes based on workload demand. When a GPU job is submitted, Karpenter launches the right instance type. When nodes sit idle, Karpenter consolidates or terminates them to reduce costs. The [NVIDIA GPU Operator](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/index.html) installs GPU drivers, the device plugin (enabling `nvidia.com/gpu` resource requests), DCGM-Exporter (GPU metrics for Chamber dashboards), and GPU Feature Discovery (node labeling by GPU type). The KAI Scheduler enables GPU time-sharing, allowing multiple containers to share a single GPU. This improves utilization and reduces costs for workloads that don't need a full GPU. The [Chamber Agent](/agent/overview) connects your cluster to the Chamber control plane, reporting capacity, managing workloads, and collecting GPU metrics. # Capacity Pools Source: https://docs.usechamber.io/concepts/capacity-pools GPU resource pools representing your clusters A capacity pool is a logical grouping of GPU resources. ## Key Points * Pools are created automatically when you install the Chamber agent * A single Kubernetes cluster can have multiple pools * The Chamber dashboard shows pool utilization and availability ## Related Concepts Setting up the cluster agent # Overview Source: https://docs.usechamber.io/concepts/overview How Chamber manages GPU capacity across your organization Chamber is a GPU capacity control plane designed to maximize utilization while ensuring teams have guaranteed access to the resources they need. ## Architecture Chamber operates as a SaaS platform with lightweight agents deployed in your Kubernetes clusters: ```mermaid theme={null} flowchart TB subgraph control["Chamber (Cloud)"] Dashboard["Dashboard"] end control <-->|Secure connection| A control <-->|Secure connection| B control <-->|Secure connection| C subgraph A["Cluster A"] AgentA["Agent"] GPUA["GPU Nodes"] end subgraph B["Cluster B"] AgentB["Agent"] GPUB["GPU Nodes"] end subgraph C["Cluster C"] AgentC["Agent"] GPUC["GPU Nodes"] end ``` ## How It Works 1. **Agents report capacity**: Lightweight agents in each cluster report available GPU resources 2. **Chamber schedules workloads**: When teams submit workloads, Chamber decides where to run them 3. **Agents execute locally**: Agents create and manage workloads on your clusters 4. **Dashboard provides visibility**: View utilization, manage teams, and track workloads The agent only makes **outbound** connections to Chamber. No inbound firewall rules are required. ## Data Model Chamber's data model reflects enterprise organizational structures: ```mermaid theme={null} flowchart TD Org["Organization"] Org --> Pools["Capacity Pools\n (GPU clusters)"] Org --> Teams["Teams"] Teams --> Child Teams["Child Teams"] Teams --> Res2["Reservations"] Pools --> Res1["Reservations"] Res1 <--> Res2 Res2 --> Workloads["Workloads"] ``` ### Key Relationships | Relationship | Description | | -------------------- | --------------------------------------- | | Organization → Teams | An org contains a hierarchy of teams | | Organization → Pools | An org can have multiple capacity pools | | Team ↔ Pool | Many-to-many via reservations | | Team → Workloads | Workloads belong to exactly one team | ## Workload Classes | Class | Capacity Source | Preemptible | Use Case | | ------------ | --------------------------------------- | ----------- | --------------------------------------- | | **Reserved** | Team's reservation | No | Production training, SLA workloads | | **Elastic** | Reserved capacity first, then idle pool | Yes | Experiments, batch processing, dev work | Elastic workloads maximize cluster utilization by using capacity that would otherwise sit idle, while still guaranteeing reserved workloads always have resources. ## Next Steps Understand the organizational hierarchy Learn about GPU resource pools How capacity is allocated to teams Deep dive into the scheduler # Reservations Source: https://docs.usechamber.io/concepts/reservations Allocating GPU capacity from pools to teams Reservations are the link between capacity pools and teams. They guarantee a specific amount of GPU capacity for a team. ## What is a Reservation? A reservation: * Allocates GPUs from a pool to a team * Guarantees capacity for reserved workloads * Can be adjusted or removed as needs change * Supports the many-to-many relationship between pools and teams ## Many-to-Many Relationships Teams and pools have a many-to-many relationship through reservations: ### One Team, Multiple Pools A team can have reservations in multiple pools: ```mermaid theme={null} flowchart LR Team["Team: ML Platform\n Total: 112 GPUs across 3 pools"] Team --> West["us-west-cluster\n 64 GPUs"] Team --> East["us-east-cluster\n 32 GPUs"] Team --> EU["eu-cluster\n 16 GPUs"] ``` This enables: * Geographic distribution of workloads * Access to different GPU types * Redundancy across clusters ### One Pool, Multiple Teams A pool can have reservations from multiple teams: ```mermaid theme={null} flowchart LR Pool["Pool: us-west-cluster\n 256 GPUs total"] Pool --> ML["ML Platform\n 64 GPUs"] Pool --> CV["CV Team\n 48 GPUs"] Pool --> NLP["NLP Team\n 32 GPUs"] Pool --> Unreserved["Unreserved\n 112 GPUs (elastic)"] ``` ## Capacity Guarantees ### Reserved Capacity When a team has a reservation: * Reserved workloads from that team are **guaranteed** those GPUs * Workloads can start immediately if capacity is available within the reservation * Other teams cannot use this capacity for reserved workloads ### Elastic Usage Unreserved pool capacity is available for elastic workloads from any team: ```mermaid theme={null} flowchart TD subgraph pool["Pool: 100 GPUs"] Reserved["Reserved: 60 GPUs"] Unreserved["Unreserved: 40 GPUs"] end subgraph runtime["At Runtime"] Running["Reserved running: 45 GPUs"] Idle["Reserved idle: 15 GPUs\n ← Elastic can use this!"] Elastic["Elastic running: 40 GPUs"] end pool --> runtime ``` Elastic workloads can use idle reserved capacity, but will be preempted if a reserved workload needs those resources. ## Best Practices Reserve what teams actually need, not what they might need. Unused reserved capacity can't serve elastic workloads from other teams. Teams with unpredictable demand should use smaller reservations plus elastic capacity rather than large reservations. Audit reservations quarterly. Teams' needs change; reservations should too. Configure alerts for low utilization (below 30%) and high queue depth to catch misconfigurations. ## Related Concepts The teams that receive reservations How workloads use reserved vs elastic capacity # Scheduling Source: https://docs.usechamber.io/concepts/scheduling How Chamber schedules GPU workloads across your organization Chamber's scheduling engine decides where and when your GPU workloads run — enforcing capacity guarantees, hierarchical bursting, and preemption automatically. ## How a Workload Gets Scheduled ```mermaid theme={null} flowchart LR User([You]) -->|submit| API[API] API -->|Pending| Scheduler[Scheduler] Scheduler -->|Queued| Agent[Chamber Agent] Agent -->|Starting| K8s[Kubernetes] K8s -->|Running| GPUs[GPUs] Agent -.->|report status| API ``` You submit a workload via the API, CLI, or dashboard. Chamber records it and marks it **Pending**. The scheduler assigns an allocation — picking the best fit based on your team's reservations and available capacity. The workload moves to **Queued**. The workload is dispatched to the Chamber Agent running in your Kubernetes cluster. The in-cluster scheduler admits the workload based on your team's quota and current demand. When GPUs are available, it places the pods. The workload moves to **Starting**, then **Running**. The agent reports status back — you see real-time updates as your workload progresses through to **Completed**, or is **Preempted** / **Failed** if something changes. ## Reserved vs Elastic Workloads Every workload you submit is either **Reserved** or **Elastic**. This determines how it accesses GPU capacity and whether it can be preempted. | | Reserved | Elastic | | ------------------------ | ----------------------------------------------------- | ---------------------------------------------- | | **What it means** | Guaranteed capacity backed by your team's reservation | Uses spare GPUs when available | | **Can it be preempted?** | Never | Yes — when reserved work needs the GPUs | | **Priority level** | Non-preemptible (priority ≥ 100) | Preemptible (priority \< 100) | | **Best for** | Production inference, critical training runs | Experiments, hyperparameter sweeps, batch jobs | Use **Reserved** for work that can't be interrupted. Use **Elastic** to take advantage of idle GPUs across the cluster — you get free capacity, but accept the trade-off that it can be reclaimed. ## How Scheduling Decisions Are Made When you submit a workload: 1. **Chamber picks the best allocation** for your workload based on available capacity across your team's reservations. 2. **Reserved workloads are admitted first.** If your team's allocation has room, the workload starts. Reserved capacity is guaranteed and protected. 3. **Elastic workloads use surplus capacity.** They run on idle GPUs — either from your team's unused reservation or from spare capacity elsewhere in the pool. Elastic workloads can be reclaimed at any time when reserved work needs the GPUs. 4. **The scheduler evaluates continuously.** As workloads complete and GPUs free up, waiting workloads are admitted automatically. ### Key Terms | Term | What It Means | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Bursting** | When a team's elastic workloads use GPUs beyond their reserved allocation. Your team "bursts" into idle capacity from the pool. | | **Burst limit** | The maximum amount a team can burst beyond its reservation. For example, a 50% burst limit on a 32-GPU reservation means the team can use up to 48 GPUs total (32 reserved + 16 burst). Set to 0 to disable bursting entirely. | | **Bursting priority** | A weight (1–10) that controls how surplus GPUs are divided when multiple teams are bursting at the same time. Higher priority means a larger share of the available surplus. | | **Preemption** | When the scheduler stops an elastic workload to free GPUs for higher-priority work. Only elastic workloads can be preempted — reserved workloads are always protected. | ## Hierarchical Bursting Your organization's teams are arranged in a tree. Chamber respects this hierarchy when distributing surplus capacity: ``` Acme Corp ├── Research (bursting priority: 3) │ ├── NLP Team (bursting priority: 2) │ └── Vision Team (bursting priority: 1) └── Production (bursting priority: 2) ├── Inference (bursting priority: 1) └── Training (bursting priority: 1) ``` * Each team has a **bursting priority** that controls its share of surplus GPUs when multiple teams are bursting. * Surplus capacity flows down the tree proportionally — Research gets 60% of excess (priority 3 out of 5), Production gets 40% (priority 2 out of 5). * Within Research, NLP gets twice the surplus share of Vision (priority 2 vs 1). * Teams don't compete in a flat pool. The hierarchy ensures organizational priorities are respected even when capacity is tight. * Each team can also have a **burst limit** that caps how far beyond its reservation it can go — preventing any single team from consuming the entire pool. ### Example: Hierarchical Bursting in Action A pool has 100 GPUs. Research has 48 reserved, Production has 32 reserved. Research is only using 20. | Team | Reservation | In Use | Idle | What Happens | | ---------- | ----------- | ------ | ---- | --------------------------------------------------------- | | Research | 48 | 20 | 28 | 28 idle GPUs available for bursting | | Production | 32 | 32 | 0 | Elastic workloads can burst into Research's idle capacity | | Pool total | 100 | 52 | — | 48 surplus GPUs distributed by bursting priority | Production's elastic workloads can temporarily burst into Research's idle GPUs. But the moment Research submits reserved work that needs those GPUs back, Production's elastic workloads are preempted. ## Preemption Preemption is how Chamber reclaims GPUs for higher-priority work. It's designed to be predictable and minimize disruption. ### Rules 1. **Reserved workloads are never preempted.** The scheduler will not reclaim them under any circumstances. 2. **Elastic workloads are always reclaimable.** The scheduler can reclaim their resources when reserved workloads need capacity. 3. **Higher-priority elastic workloads displace lower-priority ones.** Among elastic workloads, priority determines who stays when the pool is full. 4. **Cheapest workloads are reclaimed first.** The scheduler picks victims in this order: * **Queued** workloads (haven't started — zero cost) * **Starting** workloads (pods being created — minimal cost) * **Running** workloads, lowest priority first (most expensive, last resort) 5. **Only enough workloads are reclaimed** to free the capacity needed — no more. ### Preemption Examples NLP Team has a **32-GPU reservation**. They're running 20 GPUs of reserved inference and 12 GPUs of elastic experiments — fully utilizing their allocation. A researcher submits a **12-GPU reserved training workload**. ```mermaid theme={null} flowchart LR subgraph Before["Before — NLP Team: 32 / 32 GPUs"] B1["Reserved inference - 20 GPUs"] B2["Elastic experiments - 12 GPUs"] end E{{"New 12-GPU reserved workload"}} subgraph After["After — NLP Team: 32 / 32 GPUs"] A1["Reserved inference - 20 GPUs"] A2["Reserved training - 12 GPUs ✓"] end Before --> E --> After ``` The 12 elastic experiments are preempted to make room. Reserved always wins over elastic within the same allocation. The pool is fully utilized. Team A is running an **8-GPU elastic sweep at priority 50**. Team B submits an **8-GPU elastic workload at priority 75**. ```mermaid theme={null} flowchart LR subgraph Before["Before — Pool: fully utilized"] B1["Team A elastic sweep - 8 GPUs · priority 50"] B2["Team B - waiting"] end E{{"Team B submits priority-75 workload"}} subgraph After["After — Pool: fully utilized"] A1["Team A - preempted"] A2["Team B elastic workload - 8 GPUs · priority 75 ✓"] end Before --> E --> After ``` Both are elastic, but priority determines who stays. The lower-priority sweep is reclaimed. Vision Team has a **16-GPU reservation** but is only using 4 GPUs. A researcher submits an **8-GPU elastic workload**. ```mermaid theme={null} flowchart LR subgraph Before["Before — Vision Team: 4/16 GPUs"] B1["Reserved workload - 4 GPUs"] B2["Idle - 12 GPUs"] end E{{"New 8-GPU elastic workload"}} subgraph After["After — Vision Team: 12/16 GPUs"] A1["Reserved workload - 4 GPUs"] A2["Elastic workload - 8 GPUs ✓"] end Before --> E --> After ``` Plenty of idle capacity — the elastic workload starts immediately with no preemption. If reserved work later needs those GPUs, this elastic workload would be the first to go. Research has **48 GPUs reserved** but is only using 20. Production's elastic workloads have expanded into **28 of Research's idle GPUs**. A Research team member submits a **24-GPU reserved workload**. ```mermaid theme={null} flowchart LR subgraph Before["Before — Pool: 100 GPUs"] B1["Research - 20 reserved"] B2["Production - 32 reserved + 28 elastic"] end E{{"Research submits 24-GPU reserved workload"}} subgraph After["After — Pool: 100 GPUs"] A1["Research - 44 reserved ✓"] A2["Production - 32 reserved + 4 elastic"] end Before --> E --> After ``` Research's reservation can support the new workload (48 − 20 = 28 free slots ≥ 24 needed). The scheduler preempts 24 of Production's 28 elastic workloads — just enough to free the physical GPUs. Production's remaining 4 elastic workloads and all reserved workloads are untouched. ## Fractional GPUs Not every workload needs a full GPU. You can request fractions in 0.25 increments: | Request | Use Case | | ---------- | ------------------------------------------- | | `0.25` GPU | Lightweight inference, notebooks, debugging | | `0.5` GPU | Moderate inference, small model fine-tuning | | `0.75` GPU | Heavier single-GPU tasks | | `1.0+` GPU | Standard training and inference | Multiple fractional workloads share a single physical GPU via memory-based isolation and time-slicing. You can specify either a GPU fraction (e.g., `0.5`) or an explicit GPU memory limit in MiB. ## Distributed Training For multi-GPU workloads that span multiple pods, Chamber supports two scheduling modes. ### Gang Scheduling All pods must start together or none do. No partial starts, no stragglers. This is the default behavior. **Example:** You submit an 8-node distributed training workload. The cluster only has 6 GPUs free. Chamber waits until all 8 are available, then starts them simultaneously. Your training framework sees all workers from the first step. ### Topology-Aware Placement For latency-sensitive distributed workloads, Chamber co-locates pods within network topology boundaries: * **Required placement** — All pods must land within a specific topology boundary (e.g., same zone). If placement isn't possible, the workload waits. * **Preferred placement** — Pods are placed within a tighter boundary (e.g., same rack) when possible, but the constraint is relaxed if needed. This is useful for distributed training workloads that benefit from NVLink or high-bandwidth interconnects between nodes. Topology-aware placement requires that your cluster nodes are labeled with the appropriate topology keys (e.g., `topology.kubernetes.io/zone`, rack labels). A topology definition must also be configured on the cluster. Contact your cluster administrator to ensure nodes are properly tagged before using this feature. ## Workload Status Reference | Status | What It Means | What You Should Do | | ------------- | --------------------------------------------- | ---------------------------------------------------------- | | **Pending** | Submitted, waiting for allocation assignment | Wait — Chamber is finding the best allocation | | **Queued** | Dispatched to cluster, waiting for GPUs | Wait — the scheduler will admit when capacity is available | | **Starting** | Admitted by the scheduler, pods being created | Wait — images are pulling, almost there | | **Running** | All pods are running | Monitor your workload | | **Completed** | Finished successfully | Collect results | | **Failed** | Something went wrong | Check the failure reason | | **Preempted** | Reclaimed for a higher-priority workload | Resubmit — or switch to Reserved if this keeps happening | | **Cancelled** | You cancelled it | No action needed | If your elastic workloads are frequently preempted, consider increasing their priority, switching critical work to Reserved, asking your admin to raise your team's bursting priority, or scheduling during off-peak hours when more surplus capacity is available. ## Related Concepts Reserved vs elastic workload types How capacity is allocated to teams Organizational hierarchy and bursting priorities GPU resource pools representing your clusters # Teams Source: https://docs.usechamber.io/concepts/teams Hierarchical organization of teams and projects Teams are the core organizational unit in Chamber. They represent teams, projects, or business units that consume GPU resources. ## What is a Team? A team is a named entity that: * Belongs to an organization * Can have parent and child teams (forming a hierarchy) * Receives capacity reservations from pools * Contains workloads Think of teams as your org chart mapped to GPU resource allocation. ## Hierarchy Teams form a tree structure that mirrors your organization: ```mermaid theme={null} flowchart TD Research["Research (root team)"] Research --> CV["Computer Vision"] Research --> NLP Research --> Robotics CV --> OD["Object Detection"] CV --> IG["Image Generation"] NLP --> LLM["LLM Training"] NLP --> SR["Speech Recognition"] ``` ### Why Hierarchies Matter Child teams (aka Projects) can use parent capacity when their own is exhausted Managers see aggregate utilization for their entire subtree Team leads manage their subtree without org-wide access Restructure teams without recreating reservations ## Capacity and Workloads ### Reservations Each team can have reservations in one or more capacity pools: ```mermaid theme={null} flowchart LR Team["Team: Computer Vision"] Team --> West["us-west-cluster\n 64 GPUs reserved"] Team --> East["us-east-cluster\n 32 GPUs reserved"] ``` ### Workloads Workloads are associated with exactly one team via labels: ```yaml theme={null} metadata: labels: chamber.io/team: computer-vision ``` Workloads without a team label will be rejected by the Chamber scheduler. ## Best Practices Begin with a flat structure (one team per major team). Add hierarchy only when you need finer-grained capacity control. Slugs appear in workload labels and CLI commands. Use short, descriptive slugs like `cv-team` instead of `computer-vision-research-team-2024`. Structure teams to match how you want to see utilization reports. If you report by project, make projects teams. ## Related Concepts How capacity is allocated to teams Reserved vs elastic workloads # Workload Classes Source: https://docs.usechamber.io/concepts/workload-classes Reserved vs elastic workloads Chamber supports two workload classes that determine how workloads access GPU capacity: **Reserved** and **Elastic**. ## Overview | Class | Capacity Source | Preemptible | Best For | | ------------ | --------------------------------------- | ----------- | --------------------------------------- | | **Reserved** | Team's reservation | No | Production training, SLA workloads | | **Elastic** | Reserved capacity first, then idle pool | Yes | Experiments, batch processing, dev work | ## Reserved Workloads Reserved workloads use capacity from the team's reservation. They are guaranteed resources and cannot be preempted. **Use reserved for:** * Long-running training that can't be interrupted * Workloads with delivery commitments or deadlines * ML pipelines that must complete reliably ## Elastic Workloads Elastic workloads use idle capacity. They maximize utilization but can be preempted when reserved workloads need resources. **Use elastic for:** * Experiments and exploratory work * Development and debugging * Batch workloads that can checkpoint and resume Design elastic workloads to checkpoint periodically so they can resume if preempted. ## Related Concepts How Chamber schedules workloads # Introduction Source: https://docs.usechamber.io/introduction The AI Ops agent for ML teams Chamber is the AI Ops agent for ML teams. Chamber helps teams monitor, debug, root cause, and resolve GPU workload issues automatically without manual intervention. Gain out of the box insights into your GPU cluster resources, utilization, cost and team/workload level breakdowns automatically. Use AI-powered insights and autonomous agents to resolve failures, and optimize usage to accelerate development, reduce costs, and ship faster. ## What Chamber Does Autonomous agent that monitors, diagnoses, and resolves GPU workload issues 24/7 Dashboard with GPU utilization metrics, workload status, and team performance insights Allocate GPU resources through hierarchical teams with guaranteed reservations Two-phase scheduling with reserved and elastic workload classes for optimal resource utilization Manage capacity across multiple Kubernetes clusters from a single control plane *See Chamber AI Ops agent in action*