Update to Control Plane
Snapshot Oct 30, 2026 · 00:05 UTC · version 1.2.0
Collection source: downloaded plugin package.
Instructions updated for workload
Skill instructions — Now says: and `promote_workload` need `?toolsets=full`; `create_workload`, `update_workload`, and the other job tools are core. A workload is the unit of deployment:...
Observed in instructions or declared skills. Runtime behavior has not been tested.
Up to 10 plugins free · no card required.
All fields and original values.
Skill instructions
Oct 28, 2026 · 18:05 UTC
need `?toolsets=full`; `create_workload`, `update_workload`, and the job tools are core. A workload is the unit of deployment: one to eight containers plus how they scale, get exposed, store data, and stay healthy. `mcp__cpln__deploy_app...
Oct 30, 2026 · 00:05 UTC
and `promote_workload` need `?toolsets=full`; `create_workload`, `update_workload`, and the other job tools are core. A workload is the unit of deployment: one to eight containers plus how they scale, get exposed, store data, and stay he...
Compare saved observations
Download comparison JSONSKILL.md text changes
− removed · + added
--- before +++ after @@ -5,9 +5,9 @@ # Workloads -> **Tool availability:** the `configure_workload_*` tools need `?toolsets=full`; `create_workload`, `update_workload`, and the job tools are core. +> **Tool availability:** the `configure_workload_*` tools and `promote_workload` need `?toolsets=full`; `create_workload`, `update_workload`, and the other job tools are core. -A workload is the unit of deployment: one to eight containers plus how they scale, get exposed, store data, and stay healthy. `mcp__cpln__deploy_app` covers a single-container HTTP app, image, or repository: a standard workload, with a data directory every replica shares (`storage` with `shared: true`), or a stateful workload on one replica when the data directory is per replica (`storage` without `shared`). `create_workload` and `update_workload` cover the rest: serverless, several containers, cron, non-HTTP ports, custom firewall rules, probes and scaling tuned in depth. `restart_workload`, `rollback_workload`, `promote_workload`, and `allow_workload_access` do those jobs in one call. +A workload is the unit of deployment: one to eight containers plus how they scale, get exposed, store data, and stay healthy. `mcp__cpln__deploy_app` covers a single-container HTTP app, image, or repository: a standard workload, with a data directory every replica shares (`storage` with `shared: true`), or a stateful workload on one replica when the data directory is per replica (`storage` without `shared`). `create_workload` and `update_workload` cover the rest: serverless, several containers, cron, non-HTTP ports, custom firewall rules, probes and scaling tuned in depth. `restart_workload`, `rollback_workload`, `promote_workload` (`?toolsets=full`), and `allow_workload_access` do those jobs in one call. ## Workload type (immutable, standard by default) @@ -28,18 +28,17 @@ | Spec block | Set with | |---|---| | `containers[]`: image, ports, cpu/memory, env, command/args, probes, metrics, volumes | `create_workload` / `update_workload` | -| `autoscaling`, `capacityAI`, `timeoutSeconds`, `suspend`, `debug` | `create_workload` / `update_workload` | +| `autoscaling`, `capacityAI`, `capacityAIUpdateMinutes`, `multiZone`, `timeoutSeconds`, `suspend`, `debug` | `create_workload` / `update_workload` | +| `localOptions` (per-location overrides); `removeLocalOptions` on update | `create_workload` / `update_workload` | | `firewallConfig`, or the `public` shortcut | `create_workload` / `update_workload` | +| `rolloutOptions` (termination grace, surge, `rolloutOnReferenceChange`) and `securityOptions` (`runAsUser`, `filesystemGroupId`) | `create_workload` / `update_workload` | | `schedule` and job policy (`concurrencyPolicy`, `historyLimit`, `restartPolicy`, `activeDeadlineSeconds`) | the same tools with `type: cron` | | `loadBalancer` (direct, geo, replicaDirect) | `configure_workload_load_balancer` | | `sidecar.envoy` (JWT auth, Envoy filters) | `configure_workload_sidecar` | | `extras` (BYOK affinity, tolerations, topology) | `configure_workload_extras` | -| `localOptions` (per-location overrides, `multiZone`, `capacityAIUpdateMinutes`) | `configure_workload_local_options` | -| `rolloutOptions` (termination grace, surge) | `configure_workload_rollout` | -| `securityOptions` (`runAsUser`, `filesystemGroupId`) | `configure_workload_security` | | `requestRetryPolicy` | `configure_workload_retry` | -`update_workload` merges `containers[]` by name: send only the containers that change; an unknown name adds a container. On cron it patches the schedule, job policy, `suspend`, `capacityAI`, and containers, and rejects autoscaling, `timeoutSeconds`, and `debug`; schedule and job fields are rejected on other types. +`update_workload` merges `containers[]` by name: send only the containers that change; an unknown name adds a container. It merges `localOptions` by location the same way; read the **autoscaling-capacity** skill before changing one, since an override replaces `defaultOptions` in its location. It merges `rolloutOptions` and `securityOptions` field by field, and `removeSecurityOptions: true` deletes the security block. On `create_workload`, each `localOptions` override starts as a copy of the `defaultOptions` the same call sets. On cron it patches the schedule, job policy, `suspend`, `capacityAI`, and containers, and rejects autoscaling, `timeoutSeconds`, and `debug`; schedule and job fields are rejected on other types. `start_workload_cron` runs a cron workload now, with optional `containerOverrides` for that run only; each call starts another run, and it returns a command id that `get_command` follows. ## Production defaults beyond the core rules @@ -98,5 +97,5 @@ ## Metrics and live replicas -- Custom Prometheus metrics: `containers[].metrics` with `port` and `path` (default `/metrics`). Query with `list_metrics`, then `query_metrics`; measure before changing scaling. -- `list_workload_replicas` lists replicas; a command inside one goes through the CLI (`cpln` skill), with confirmation for anything that changes state. +- Custom Prometheus metrics: `containers[].metrics` with `port` and `path` (default `/metrics`). List them with `query_metrics` without a `query`, then query them; measure before changing scaling. +- `list_deployments` names each location's running replicas, the `--replica` value for `cpln workload exec` and `cpln workload connect`; a command inside one goes through the CLI (`cpln` skill), with confirmation for anything that changes state.
Full technical diff · 1 changed fields
changed /skill_md_contents
"---\nname: workload\ndescription: \"Primary skill for creating, updating, running, and debugging workloads on Control Plane; routes to a deeper skill per subject. Use when the user asks to deploy or run a container, app, API, service, worker, or job, or to change, scale, expose, secure, or diagnose one.\"\n---\n\n# Workloads\n\n> **Tool availability:** the `configure_workload_*` tools need `?toolsets=full`; `create_workload`, `update_workload`, and the job tools are core.\n\nA workload is the unit of deployment: one to eight containers plus how they scale, get exposed, store data, and stay healthy. `mcp__cpln__deploy_app` covers a single-container HTTP app, image, or repository: a standard workload, with a data directory every replica shares (`storage` with `shared: true`), or a stateful workload on one replica when the data directory is per replica (`storage` without `shared`). `create_workload` and `update_workload` cover the rest: serverless, several containers, cron, non-HTTP ports, custom firewall rules, probes and scaling tuned in depth. `restart_workload`, `rollback_workload`, `promote_workload`, and `allow_workload_access` do those jobs in one call.\n\n## Workload type (immutable, standard by default)\n\n| | **standard** | serverless | stateful | cron |\n|---|---|---|---|---|\n| Use for | long-running services, APIs, workers | request-driven HTTP that scales on demand | databases, stable disk or per-replica identity | scheduled jobs |\n| Autoscaling metrics | cpu, memory, latency, rps, multi, keda, disabled | concurrency, cpu, memory, rps, disabled | cpu, memory, latency, rps, multi, keda, disabled | none: runs on `schedule` |\n| Capacity AI | on by default | on by default | supported | on by default; lands at the next run |\n| Default probes | none | TCP readiness and liveness | none | ignored |\n| `ext4`/`xfs` volumes | no | no | **only here** | no |\n| `shared` volumes | yes | yes | yes | yes |\n| Scale to zero | KEDA only | yes | KEDA only | no |\n\n`concurrency` scaling exists only on serverless; on standard or stateful the closest is `rps`. Since type cannot change, pick it for the metric the user wants.\n\n## Which tool sets what\n\n| Spec block | Set with |\n|---|---|\n| `containers[]`: image, ports, cpu/memory, env, command/args, probes, metrics, volumes | `create_workload` / `update_workload` |\n| `autoscaling`, `capacityAI`, `timeoutSeconds`, `suspend`, `debug` | `create_workload` / `update_workload` |\n| `firewallConfig`, or the `public` shortcut | `create_workload` / `update_workload` |\n| `schedule` and job policy (`concurrencyPolicy`, `historyLimit`, `restartPolicy`, `activeDeadlineSeconds`) | the same tools with `type: cron` |\n| `loadBalancer` (direct, geo, replicaDirect) | `configure_workload_load_balancer` |\n| `sidecar.envoy` (JWT auth, Envoy filters) | `configure_workload_sidecar` |\n| `extras` (BYOK affinity, tolerations, topology) | `configure_workload_extras` |\n| `localOptions` (per-location overrides, `multiZone`, `capacityAIUpdateMinutes`) | `configure_workload_local_options` |\n| `rolloutOptions` (termination grace, surge) | `configure_workload_rollout` |\n| `securityOptions` (`runAsUser`, `filesystemGroupId`) | `configure_workload_security` |\n| `requestRetryPolicy` | `configure_workload_retry` |\n\n`update_workload` merges `containers[]` by name: send only the containers that change; an unknown name adds a container. On cron it patches the schedule, job policy, `suspend`, `capacityAI`, and containers, and rejects autoscaling, `timeoutSeconds`, and `debug`; schedule and job fields are rejected on other types.\n\n## Production defaults beyond the core rules\n\n- `minScale: 1` only with a named reason: a single writer, leader election, dev or staging. Stateful is often right at 1.\n- `maxScale` stays at its default of 5 unless the user names a maximum; then use exactly that number.\n- Define `readinessProbe` and `livenessProbe` yourself on standard, stateful, and cron.\n- Size CPU and memory to the runtime, not the platform defaults of `50m` and `128Mi`. Floors: `25m` and `32Mi`. Memory in MiB at most 8 times CPU in millicores; the tag `cpln/relaxMemoryToCpuRatio` raises that to 32.\n- Never silently downgrade a request the type rejects to `disabled`, one replica, or a weaker firewall: say what conflicts and offer alternatives.\n\n## Images\n\n- Another Control Plane org's registry: `OTHER-ORG.registry.cpln.io/NAME:TAG` works in a spec for cross-org pulls. For your own org prefer `//image/NAME:TAG`; the hostname form is for `docker login` and `docker push`.\n- A wrong-architecture image fails with `exec format error`.\n- A private external registry needs a pull secret on the GVC (`spec.pullSecretLinks`); same-org `//image/...` needs none. Detail: `image` skill.\n- An app you write for the user is built first (`create-app` skill); to change an existing app's code, `get_app_files` with its image NAME says where the code lives.\n\n## Health\n\n- `readinessProbe` gates traffic: it may check request-path dependencies (database, auth, cache).\n- `livenessProbe` restarts a hung process: it checks only the process itself, never a dependency, or one outage restarts every replica.\n- Each probe uses exactly one handler: `exec`, `grpc`, `tcpSocket`, or `httpGet`. Defaults: readiness `initialDelaySeconds` 10, liveness 60, `periodSeconds` 10. Tune the delay to the real cold start.\n- `list_deployments` with `location` shows one location's deployment in full detail.\n\n## Autoscaling\n\nMatch the metric to the traffic: `rps` or `concurrency` for HTTP, `cpu` or `memory` for compute, `latency` for SLO-driven APIs, `keda` for queues. On standard with Capacity AI on, an omitted metric resolves to `disabled`, so name it. Capacity AI is rejected with the `cpu` metric and with GPUs. The metric table, KEDA, and Capacity AI: `autoscaling-capacity` skill.\n\n## Networking\n\n- Blocked CIDRs beat allowed ones, and CIDR rules beat hostname rules.\n- Hostname outbound rules allow ports 80, 443, and 445 by default; `outboundAllowPort` replaces that set. Private RFC1918 and CGNAT ranges in `outboundAllowCIDR` are ignored on managed locations; reaching a private network takes an agent (`native-networking` skill).\n- Same-GVC internal traffic is free; cross-GVC traffic needs the caller admitted (`allow_workload_access`) and pays egress.\n- The canonical URL serves one port: the first container port. Standard and stateful may expose more ports across containers, reachable internally or through a direct or dedicated load balancer; serverless allows one container with one port.\n- Load balancers: shared is the default (HTTP and HTTPS on 80 and 443). **Direct** gives a workload custom TCP or UDP ports 22 to 32768, optional static IPs, and geo headers (`configure_workload_load_balancer`). **Dedicated** is a GVC setting for custom domains and wildcard hosts (`update_gvc`). Toggling either needs the `configureLoadBalancer` permission, which `edit` does not include. Detail: `ipset-load-balancing` and `firewall-networking` skills.\n\n## Storage\n\n- Durable disk or a stable per-replica identity means a stateful workload with a volume set. A volume set's filesystem and performance class cannot change.\n- `ext4` and `xfs` mount on stateful only; `shared` mounts on any type. At most 15 volumes per container; no two mounts may share or nest a path; `/dev`, `/dev/log`, `/tmp`, `/var`, and `/var/log` are rejected.\n- Snapshot before a shrink, restore, or delete; snapshots exist for `ext4` and `xfs` only. Detail: `stateful-storage` skill.\n\n## Env, names, and the workload's own API access\n\n- Env names cannot start with `CPLN_` or be `K_SERVICE`, `K_CONFIGURATION`, or `K_REVISION`; they match `^[-._a-zA-Z][-._a-zA-Z0-9]*$`, at most 120 characters. The platform injects `CPLN_TOKEN`, `CPLN_ENDPOINT`, `CPLN_GLOBAL_ENDPOINT`, `CPLN_ORG`, `CPLN_GVC`, `CPLN_GVC_ALIAS`, `CPLN_LOCATION`, `CPLN_PROVIDER`, `CPLN_WORKLOAD`, `CPLN_WORKLOAD_VERSION`, `CPLN_IMAGE`, `CPLN_NAME`, `CPLN_MAIN` on the first container, and `PORT` on standard when unset.\n- A workload calls the Control Plane API as its identity: `curl -H \"Authorization: Bearer $CPLN_TOKEN\" $CPLN_ENDPOINT/org/$CPLN_ORG/...`. `CPLN_ENDPOINT` is plain HTTP, and a call succeeds only where a policy grants the attached identity the permission; otherwise it returns 403.\n- Container names are lowercase `^[a-z]([-a-z0-9])*[a-z0-9]$`, at most 64 characters, and cannot start with `cpln-` or `debugger-`. A workload name is at most 49 characters and cannot end with `-headless`.\n\n## Ports and runtime traps\n\n- Reserved container ports: 8012, 8022, 9090, 9091, 15000, 15001, 15006, 15020, 15021, 15090, 41000. Valid ports run from 80 to 65535 and must be unique across containers.\n- Termination grace is `spec.rolloutOptions.terminationGracePeriodSeconds`, 0 to 900, default 90. The shutdown sequence and its traps: `workload-security` skill.\n\n## Renames and recreates\n\nChanging a workload's type or name means delete and recreate. Recreating under the same name keeps its public URL and internal DNS name; a new name breaks every domain route, policy link, internal caller, and external client that used the old one.\n\n## Metrics and live replicas\n\n- Custom Prometheus metrics: `containers[].metrics` with `port` and `path` (default `/metrics`). Query with `list_metrics`, then `query_metrics`; measure before changing scaling.\n- `list_workload_replicas` lists replicas; a command inside one goes through the CLI (`cpln` skill), with confirmation for anything that changes state.\n"
"---\nname: workload\ndescription: \"Primary skill for creating, updating, running, and debugging workloads on Control Plane; routes to a deeper skill per subject. Use when the user asks to deploy or run a container, app, API, service, worker, or job, or to change, scale, expose, secure, or diagnose one.\"\n---\n\n# Workloads\n\n> **Tool availability:** the `configure_workload_*` tools and `promote_workload` need `?toolsets=full`; `create_workload`, `update_workload`, and the other job tools are core.\n\nA workload is the unit of deployment: one to eight containers plus how they scale, get exposed, store data, and stay healthy. `mcp__cpln__deploy_app` covers a single-container HTTP app, image, or repository: a standard workload, with a data directory every replica shares (`storage` with `shared: true`), or a stateful workload on one replica when the data directory is per replica (`storage` without `shared`). `create_workload` and `update_workload` cover the rest: serverless, several containers, cron, non-HTTP ports, custom firewall rules, probes and scaling tuned in depth. `restart_workload`, `rollback_workload`, `promote_workload` (`?toolsets=full`), and `allow_workload_access` do those jobs in one call.\n\n## Workload type (immutable, standard by default)\n\n| | **standard** | serverless | stateful | cron |\n|---|---|---|---|---|\n| Use for | long-running services, APIs, workers | request-driven HTTP that scales on demand | databases, stable disk or per-replica identity | scheduled jobs |\n| Autoscaling metrics | cpu, memory, latency, rps, multi, keda, disabled | concurrency, cpu, memory, rps, disabled | cpu, memory, latency, rps, multi, keda, disabled | none: runs on `schedule` |\n| Capacity AI | on by default | on by default | supported | on by default; lands at the next run |\n| Default probes | none | TCP readiness and liveness | none | ignored |\n| `ext4`/`xfs` volumes | no | no | **only here** | no |\n| `shared` volumes | yes | yes | yes | yes |\n| Scale to zero | KEDA only | yes | KEDA only | no |\n\n`concurrency` scaling exists only on serverless; on standard or stateful the closest is `rps`. Since type cannot change, pick it for the metric the user wants.\n\n## Which tool sets what\n\n| Spec block | Set with |\n|---|---|\n| `containers[]`: image, ports, cpu/memory, env, command/args, probes, metrics, volumes | `create_workload` / `update_workload` |\n| `autoscaling`, `capacityAI`, `capacityAIUpdateMinutes`, `multiZone`, `timeoutSeconds`, `suspend`, `debug` | `create_workload` / `update_workload` |\n| `localOptions` (per-location overrides); `removeLocalOptions` on update | `create_workload` / `update_workload` |\n| `firewallConfig`, or the `public` shortcut | `create_workload` / `update_workload` |\n| `rolloutOptions` (termination grace, surge, `rolloutOnReferenceChange`) and `securityOptions` (`runAsUser`, `filesystemGroupId`) | `create_workload` / `update_workload` |\n| `schedule` and job policy (`concurrencyPolicy`, `historyLimit`, `restartPolicy`, `activeDeadlineSeconds`) | the same tools with `type: cron` |\n| `loadBalancer` (direct, geo, replicaDirect) | `configure_workload_load_balancer` |\n| `sidecar.envoy` (JWT auth, Envoy filters) | `configure_workload_sidecar` |\n| `extras` (BYOK affinity, tolerations, topology) | `configure_workload_extras` |\n| `requestRetryPolicy` | `configure_workload_retry` |\n\n`update_workload` merges `containers[]` by name: send only the containers that change; an unknown name adds a container. It merges `localOptions` by location the same way; read the **autoscaling-capacity** skill before changing one, since an override replaces `defaultOptions` in its location. It merges `rolloutOptions` and `securityOptions` field by field, and `removeSecurityOptions: true` deletes the security block. On `create_workload`, each `localOptions` override starts as a copy of the `defaultOptions` the same call sets. On cron it patches the schedule, job policy, `suspend`, `capacityAI`, and containers, and rejects autoscaling, `timeoutSeconds`, and `debug`; schedule and job fields are rejected on other types. `start_workload_cron` runs a cron workload now, with optional `containerOverrides` for that run only; each call starts another run, and it returns a command id that `get_command` follows.\n\n## Production defaults beyond the core rules\n\n- `minScale: 1` only with a named reason: a single writer, leader election, dev or staging. Stateful is often right at 1.\n- `maxScale` stays at its default of 5 unless the user names a maximum; then use exactly that number.\n- Define `readinessProbe` and `livenessProbe` yourself on standard, stateful, and cron.\n- Size CPU and memory to the runtime, not the platform defaults of `50m` and `128Mi`. Floors: `25m` and `32Mi`. Memory in MiB at most 8 times CPU in millicores; the tag `cpln/relaxMemoryToCpuRatio` raises that to 32.\n- Never silently downgrade a request the type rejects to `disabled`, one replica, or a weaker firewall: say what conflicts and offer alternatives.\n\n## Images\n\n- Another Control Plane org's registry: `OTHER-ORG.registry.cpln.io/NAME:TAG` works in a spec for cross-org pulls. For your own org prefer `//image/NAME:TAG`; the hostname form is for `docker login` and `docker push`.\n- A wrong-architecture image fails with `exec format error`.\n- A private external registry needs a pull secret on the GVC (`spec.pullSecretLinks`); same-org `//image/...` needs none. Detail: `image` skill.\n- An app you write for the user is built first (`create-app` skill); to change an existing app's code, `get_app_files` with its image NAME says where the code lives.\n\n## Health\n\n- `readinessProbe` gates traffic: it may check request-path dependencies (database, auth, cache).\n- `livenessProbe` restarts a hung process: it checks only the process itself, never a dependency, or one outage restarts every replica.\n- Each probe uses exactly one handler: `exec`, `grpc`, `tcpSocket`, or `httpGet`. Defaults: readiness `initialDelaySeconds` 10, liveness 60, `periodSeconds` 10. Tune the delay to the real cold start.\n- `list_deployments` with `location` shows one location's deployment in full detail.\n\n## Autoscaling\n\nMatch the metric to the traffic: `rps` or `concurrency` for HTTP, `cpu` or `memory` for compute, `latency` for SLO-driven APIs, `keda` for queues. On standard with Capacity AI on, an omitted metric resolves to `disabled`, so name it. Capacity AI is rejected with the `cpu` metric and with GPUs. The metric table, KEDA, and Capacity AI: `autoscaling-capacity` skill.\n\n## Networking\n\n- Blocked CIDRs beat allowed ones, and CIDR rules beat hostname rules.\n- Hostname outbound rules allow ports 80, 443, and 445 by default; `outboundAllowPort` replaces that set. Private RFC1918 and CGNAT ranges in `outboundAllowCIDR` are ignored on managed locations; reaching a private network takes an agent (`native-networking` skill).\n- Same-GVC internal traffic is free; cross-GVC traffic needs the caller admitted (`allow_workload_access`) and pays egress.\n- The canonical URL serves one port: the first container port. Standard and stateful may expose more ports across containers, reachable internally or through a direct or dedicated load balancer; serverless allows one container with one port.\n- Load balancers: shared is the default (HTTP and HTTPS on 80 and 443). **Direct** gives a workload custom TCP or UDP ports 22 to 32768, optional static IPs, and geo headers (`configure_workload_load_balancer`). **Dedicated** is a GVC setting for custom domains and wildcard hosts (`update_gvc`). Toggling either needs the `configureLoadBalancer` permission, which `edit` does not include. Detail: `ipset-load-balancing` and `firewall-networking` skills.\n\n## Storage\n\n- Durable disk or a stable per-replica identity means a stateful workload with a volume set. A volume set's filesystem and performance class cannot change.\n- `ext4` and `xfs` mount on stateful only; `shared` mounts on any type. At most 15 volumes per container; no two mounts may share or nest a path; `/dev`, `/dev/log`, `/tmp`, `/var`, and `/var/log` are rejected.\n- Snapshot before a shrink, restore, or delete; snapshots exist for `ext4` and `xfs` only. Detail: `stateful-storage` skill.\n\n## Env, names, and the workload's own API access\n\n- Env names cannot start with `CPLN_` or be `K_SERVICE`, `K_CONFIGURATION`, or `K_REVISION`; they match `^[-._a-zA-Z][-._a-zA-Z0-9]*$`, at most 120 characters. The platform injects `CPLN_TOKEN`, `CPLN_ENDPOINT`, `CPLN_GLOBAL_ENDPOINT`, `CPLN_ORG`, `CPLN_GVC`, `CPLN_GVC_ALIAS`, `CPLN_LOCATION`, `CPLN_PROVIDER`, `CPLN_WORKLOAD`, `CPLN_WORKLOAD_VERSION`, `CPLN_IMAGE`, `CPLN_NAME`, `CPLN_MAIN` on the first container, and `PORT` on standard when unset.\n- A workload calls the Control Plane API as its identity: `curl -H \"Authorization: Bearer $CPLN_TOKEN\" $CPLN_ENDPOINT/org/$CPLN_ORG/...`. `CPLN_ENDPOINT` is plain HTTP, and a call succeeds only where a policy grants the attached identity the permission; otherwise it returns 403.\n- Container names are lowercase `^[a-z]([-a-z0-9])*[a-z0-9]$`, at most 64 characters, and cannot start with `cpln-` or `debugger-`. A workload name is at most 49 characters and cannot end with `-headless`.\n\n## Ports and runtime traps\n\n- Reserved container ports: 8012, 8022, 9090, 9091, 15000, 15001, 15006, 15020, 15021, 15090, 41000. Valid ports run from 80 to 65535 and must be unique across containers.\n- Termination grace is `spec.rolloutOptions.terminationGracePeriodSeconds`, 0 to 900, default 90. The shutdown sequence and its traps: `workload-security` skill.\n\n## Renames and recreates\n\nChanging a workload's type or name means delete and recreate. Recreating under the same name keeps its public URL and internal DNS name; a new name breaks every domain route, policy link, internal caller, and external client that used the old one.\n\n## Metrics and live replicas\n\n- Custom Prometheus metrics: `containers[].metrics` with `port` and `path` (default `/metrics`). List them with `query_metrics` without a `query`, then query them; measure before changing scaling.\n- `list_deployments` names each location's running replicas, the `--replica` value for `cpln workload exec` and `cpln workload connect`; a command inside one goes through the CLI (`cpln` skill), with confirmation for anything that changes state.\n"
Full snapshot data
{
"description": "Primary skill for creating, updating, running, and debugging workloads on Control Plane; routes to a deeper skill per subject. Use when the user asks to deploy or run a container, app, API, service, worker, or job, or to change, scale, expose, secure, or diagnose one.",
"included_files": [],
"name": "workload",
"skill_md_contents": "---\nname: workload\ndescription: \"Primary skill for creating, updating, running, and debugging workloads on Control Plane; routes to a deeper skill per subject. Use when the user asks to deploy or run a container, app, API, service, worker, or job, or to change, scale, expose, secure, or diagnose one.\"\n---\n\n# Workloads\n\n> **Tool availability:** the `configure_workload_*` tools and `promote_workload` need `?toolsets=full`; `create_workload`, `update_workload`, and the other job tools are core.\n\nA workload is the unit of deployment: one to eight containers plus how they scale, get exposed, store data, and stay healthy. `mcp__cpln__deploy_app` covers a single-container HTTP app, image, or repository: a standard workload, with a data directory every replica shares (`storage` with `shared: true`), or a stateful workload on one replica when the data directory is per replica (`storage` without `shared`). `create_workload` and `update_workload` cover the rest: serverless, several containers, cron, non-HTTP ports, custom firewall rules, probes and scaling tuned in depth. `restart_workload`, `rollback_workload`, `promote_workload` (`?toolsets=full`), and `allow_workload_access` do those jobs in one call.\n\n## Workload type (immutable, standard by default)\n\n| | **standard** | serverless | stateful | cron |\n|---|---|---|---|---|\n| Use for | long-running services, APIs, workers | request-driven HTTP that scales on demand | databases, stable disk or per-replica identity | scheduled jobs |\n| Autoscaling metrics | cpu, memory, latency, rps, multi, keda, disabled | concurrency, cpu, memory, rps, disabled | cpu, memory, latency, rps, multi, keda, disabled | none: runs on `schedule` |\n| Capacity AI | on by default | on by default | supported | on by default; lands at the next run |\n| Default probes | none | TCP readiness and liveness | none | ignored |\n| `ext4`/`xfs` volumes | no | no | **only here** | no |\n| `shared` volumes | yes | yes | yes | yes |\n| Scale to zero | KEDA only | yes | KEDA only | no |\n\n`concurrency` scaling exists only on serverless; on standard or stateful the closest is `rps`. Since type cannot change, pick it for the metric the user wants.\n\n## Which tool sets what\n\n| Spec block | Set with |\n|---|---|\n| `containers[]`: image, ports, cpu/memory, env, command/args, probes, metrics, volumes | `create_workload` / `update_workload` |\n| `autoscaling`, `capacityAI`, `capacityAIUpdateMinutes`, `multiZone`, `timeoutSeconds`, `suspend`, `debug` | `create_workload` / `update_workload` |\n| `localOptions` (per-location overrides); `removeLocalOptions` on update | `create_workload` / `update_workload` |\n| `firewallConfig`, or the `public` shortcut | `create_workload` / `update_workload` |\n| `rolloutOptions` (termination grace, surge, `rolloutOnReferenceChange`) and `securityOptions` (`runAsUser`, `filesystemGroupId`) | `create_workload` / `update_workload` |\n| `schedule` and job policy (`concurrencyPolicy`, `historyLimit`, `restartPolicy`, `activeDeadlineSeconds`) | the same tools with `type: cron` |\n| `loadBalancer` (direct, geo, replicaDirect) | `configure_workload_load_balancer` |\n| `sidecar.envoy` (JWT auth, Envoy filters) | `configure_workload_sidecar` |\n| `extras` (BYOK affinity, tolerations, topology) | `configure_workload_extras` |\n| `requestRetryPolicy` | `configure_workload_retry` |\n\n`update_workload` merges `containers[]` by name: send only the containers that change; an unknown name adds a container. It merges `localOptions` by location the same way; read the **autoscaling-capacity** skill before changing one, since an override replaces `defaultOptions` in its location. It merges `rolloutOptions` and `securityOptions` field by field, and `removeSecurityOptions: true` deletes the security block. On `create_workload`, each `localOptions` override starts as a copy of the `defaultOptions` the same call sets. On cron it patches the schedule, job policy, `suspend`, `capacityAI`, and containers, and rejects autoscaling, `timeoutSeconds`, and `debug`; schedule and job fields are rejected on other types. `start_workload_cron` runs a cron workload now, with optional `containerOverrides` for that run only; each call starts another run, and it returns a command id that `get_command` follows.\n\n## Production defaults beyond the core rules\n\n- `minScale: 1` only with a named reason: a single writer, leader election, dev or staging. Stateful is often right at 1.\n- `maxScale` stays at its default of 5 unless the user names a maximum; then use exactly that number.\n- Define `readinessProbe` and `livenessProbe` yourself on standard, stateful, and cron.\n- Size CPU and memory to the runtime, not the platform defaults of `50m` and `128Mi`. Floors: `25m` and `32Mi`. Memory in MiB at most 8 times CPU in millicores; the tag `cpln/relaxMemoryToCpuRatio` raises that to 32.\n- Never silently downgrade a request the type rejects to `disabled`, one replica, or a weaker firewall: say what conflicts and offer alternatives.\n\n## Images\n\n- Another Control Plane org's registry: `OTHER-ORG.registry.cpln.io/NAME:TAG` works in a spec for cross-org pulls. For your own org prefer `//image/NAME:TAG`; the hostname form is for `docker login` and `docker push`.\n- A wrong-architecture image fails with `exec format error`.\n- A private external registry needs a pull secret on the GVC (`spec.pullSecretLinks`); same-org `//image/...` needs none. Detail: `image` skill.\n- An app you write for the user is built first (`create-app` skill); to change an existing app's code, `get_app_files` with its image NAME says where the code lives.\n\n## Health\n\n- `readinessProbe` gates traffic: it may check request-path dependencies (database, auth, cache).\n- `livenessProbe` restarts a hung process: it checks only the process itself, never a dependency, or one outage restarts every replica.\n- Each probe uses exactly one handler: `exec`, `grpc`, `tcpSocket`, or `httpGet`. Defaults: readiness `initialDelaySeconds` 10, liveness 60, `periodSeconds` 10. Tune the delay to the real cold start.\n- `list_deployments` with `location` shows one location's deployment in full detail.\n\n## Autoscaling\n\nMatch the metric to the traffic: `rps` or `concurrency` for HTTP, `cpu` or `memory` for compute, `latency` for SLO-driven APIs, `keda` for queues. On standard with Capacity AI on, an omitted metric resolves to `disabled`, so name it. Capacity AI is rejected with the `cpu` metric and with GPUs. The metric table, KEDA, and Capacity AI: `autoscaling-capacity` skill.\n\n## Networking\n\n- Blocked CIDRs beat allowed ones, and CIDR rules beat hostname rules.\n- Hostname outbound rules allow ports 80, 443, and 445 by default; `outboundAllowPort` replaces that set. Private RFC1918 and CGNAT ranges in `outboundAllowCIDR` are ignored on managed locations; reaching a private network takes an agent (`native-networking` skill).\n- Same-GVC internal traffic is free; cross-GVC traffic needs the caller admitted (`allow_workload_access`) and pays egress.\n- The canonical URL serves one port: the first container port. Standard and stateful may expose more ports across containers, reachable internally or through a direct or dedicated load balancer; serverless allows one container with one port.\n- Load balancers: shared is the default (HTTP and HTTPS on 80 and 443). **Direct** gives a workload custom TCP or UDP ports 22 to 32768, optional static IPs, and geo headers (`configure_workload_load_balancer`). **Dedicated** is a GVC setting for custom domains and wildcard hosts (`update_gvc`). Toggling either needs the `configureLoadBalancer` permission, which `edit` does not include. Detail: `ipset-load-balancing` and `firewall-networking` skills.\n\n## Storage\n\n- Durable disk or a stable per-replica identity means a stateful workload with a volume set. A volume set's filesystem and performance class cannot change.\n- `ext4` and `xfs` mount on stateful only; `shared` mounts on any type. At most 15 volumes per container; no two mounts may share or nest a path; `/dev`, `/dev/log`, `/tmp`, `/var`, and `/var/log` are rejected.\n- Snapshot before a shrink, restore, or delete; snapshots exist for `ext4` and `xfs` only. Detail: `stateful-storage` skill.\n\n## Env, names, and the workload's own API access\n\n- Env names cannot start with `CPLN_` or be `K_SERVICE`, `K_CONFIGURATION`, or `K_REVISION`; they match `^[-._a-zA-Z][-._a-zA-Z0-9]*$`, at most 120 characters. The platform injects `CPLN_TOKEN`, `CPLN_ENDPOINT`, `CPLN_GLOBAL_ENDPOINT`, `CPLN_ORG`, `CPLN_GVC`, `CPLN_GVC_ALIAS`, `CPLN_LOCATION`, `CPLN_PROVIDER`, `CPLN_WORKLOAD`, `CPLN_WORKLOAD_VERSION`, `CPLN_IMAGE`, `CPLN_NAME`, `CPLN_MAIN` on the first container, and `PORT` on standard when unset.\n- A workload calls the Control Plane API as its identity: `curl -H \"Authorization: Bearer $CPLN_TOKEN\" $CPLN_ENDPOINT/org/$CPLN_ORG/...`. `CPLN_ENDPOINT` is plain HTTP, and a call succeeds only where a policy grants the attached identity the permission; otherwise it returns 403.\n- Container names are lowercase `^[a-z]([-a-z0-9])*[a-z0-9]$`, at most 64 characters, and cannot start with `cpln-` or `debugger-`. A workload name is at most 49 characters and cannot end with `-headless`.\n\n## Ports and runtime traps\n\n- Reserved container ports: 8012, 8022, 9090, 9091, 15000, 15001, 15006, 15020, 15021, 15090, 41000. Valid ports run from 80 to 65535 and must be unique across containers.\n- Termination grace is `spec.rolloutOptions.terminationGracePeriodSeconds`, 0 to 900, default 90. The shutdown sequence and its traps: `workload-security` skill.\n\n## Renames and recreates\n\nChanging a workload's type or name means delete and recreate. Recreating under the same name keeps its public URL and internal DNS name; a new name breaks every domain route, policy link, internal caller, and external client that used the old one.\n\n## Metrics and live replicas\n\n- Custom Prometheus metrics: `containers[].metrics` with `port` and `path` (default `/metrics`). List them with `query_metrics` without a `query`, then query them; measure before changing scaling.\n- `list_deployments` names each location's running replicas, the `--replica` value for `cpln workload exec` and `cpln workload connect`; a command inside one goes through the CLI (`cpln` skill), with confirmation for anything that changes state.\n"
}SHA-256 of public snapshot: 42598192b4e3a911be618595a454b144f63f42b75845f2f2ed529775f9998379