You are onboarding someone onto the Akuity platform. The full path starts from an Akuity account, one or more Kubernetes clusters, a container image, and a git repository, and ends with Argo CD running, the clusters connected, the app deployed to every environment by an Argo CD application, and a Kargo pipeline that promotes the image through those environments by updating git and syncing the apps — without ever opening the Akuity UI for the build itself. Each environment maps to a cluster the user names (several environments may share one — e.g. dev and staging on cluster A, prod on cluster B) and gets its own namespace. Not everyone wants the whole path, and parts of it may already exist — so the first move is agreeing on scope, not creating anything.
The whole flow runs on one MCP endpoint — the platform endpoint, with the organization and instance named explicitly on every call. Its apply tools are composite: one call carries an instance together with what lives inside it — Argo CD Applications ride in the Argo CD apply, Kargo projects, warehouses, and stages in the Kargo apply — and the platform endpoint also serves the sync, freight, and promotion tools the later steps need. Each provisioned instance can additionally serve its own MCP endpoint, where the same in-instance work runs under the instance's own RBAC — but connecting one is never required: with the platform endpoint connected, everything in this flow and its day-2 follow-ons is already reachable (instances this flow creates allow platform MCP actions automatically; a pre-existing instance must have MCP access enabled before the in-instance tools reach it — and every Kargo instance, new or pre-existing, needs its authentication configured before Kargo's API answers at all: ../../references/endpoints-and-auth.md). It is a choice the user can make, mainly for teammates who hold instance access without organization access — see "The instances' own endpoints" below. Read ../../references/endpoints-and-auth.md and ../../references/manifest-kinds.md (paths relative to this file) before your first call — they carry the endpoint model and the manifest rules this skill depends on. Before writing an instance, cluster, Argo CD, or Kargo resource, also read the relevant section of references/official-docs.md. For a new instance, omit its version as manifest-kinds.md requires; after it becomes healthy, read the assigned version before writing its in-instance resources. Then read tools/list and the tool descriptions; this skill gives you the order and the platform-specific facts, not the full tool contracts.
Treat the flow below as a dependency order, not a script. Tool names and manifest shapes may have moved since this was written. The live tool description defines the MCP call envelope; the installed product version's official docs and CRD define the resource inside it. When they disagree with this skill, use those current sources and tell the user about the difference rather than forcing the text. If neither source defines a field, stop and ask or defer that setup — never try plausible field names or nesting until one happens to apply. The goal state is fixed even when the path is not: whatever scope the user chose, standing and verifiable from MCP reads at the end.
The one principle that shapes everything here
You never configure the user's credentials or logins for them, and nothing optional blocks the flow. Passwords, password hashes, OIDC client secrets, git and registry tokens — all of it is the user's own action, in the portal UI or their own shell, with you supplying the exact place or command and a placeholder. Your job is to keep building everything that does not depend on the missing piece, say plainly at the moment a piece is needed what it is for and what fails without it, verify by outcome once the user has acted, and close with a checklist of anything still unconfigured and its consequences. Never park the whole flow on a setup question, and never take a secret into the conversation to unpark it.
The milestones — offer them, let the user choose
These are the milestones, in dependency order — not an all-or-nothing script:
- Argo CD instance — provisioned and healthy (flow steps 1–2).
- Clusters connected — every cluster the environments map to registered with the instance, agent installed, healthy (step 3).
- Kargo instance — provisioned likewise, with an Akuity-managed Kargo agent linked to the Argo CD instance (step 4).
- Apps created — deployment YAMLs per environment in git, one Argo CD Application per environment (steps 7–8). If the chosen scope stops here, this milestone also runs each app's first sync so the app is actually deployed; with a pipeline in scope, the tags come from the approved Stage-to-version plan and deployment is milestone 6's job.
- Pipeline wired — Kargo Project, a Warehouse watching their image, and — after the user has seen what the Warehouse discovered and chosen the desired version for each Stage — one chained Stage per environment (steps 5–9).
- Release promoted — the required Freight carried through the environments per a plan the user approved, each hop verified; in pipeline scope this is where each approved environment's first deployment happens (step 10).
- Incident response wired (optional) — Akuity Agents enabled on the Argo CD instance with a resource-degradation trigger scoped to the new clusters and namespaces, so a degraded app opens an incident by itself instead of waiting for someone to notice (step 11).
Open by naming these and asking how far they want to go: the full path, one milestone, or just the missing pieces. Then establish where they already stand with read tools before creating anything. An instance, cluster, or pipeline that already exists and is healthy is a prerequisite satisfied, not something to recreate. One dependency to name up front: Kargo Project, Stage, Freight, and Promotion tools require the instance to have an admin account or OIDC configured. Platform lifecycle reads and applies remain available, so instance creation and platform applies of Project, Warehouse, and Stage do not depend on this setup. Authentication is the user's own action and can happen at creation or later. It gates the Kargo reads and promotions in milestones 5–6, but it must not stall independent work. See steps 4–6 and references/instance-access.md. Someone with a running instance and a connected cluster who asks to "onboard" needs milestones 4–6, not a second instance.
Ask in two rounds
Provisioning waits are the rhythm of this flow, so batch the questions: one round at scope time, and — only when a pipeline is in scope — one round after the Warehouse reports its discovered artifacts, when the versions on the table are real data instead of guesses. Never ask for a token, password, or password hash in chat: anything pasted into the conversation persists in tool-call data. Instance logins are deliberately not asked about here at all — they are the user's own setup in the portal UI, raised at the moment they matter (step 4) and again in the closing checklist.
Round one — at scope time. Any scope:
- Their Akuity organization. Call
list_organizations to resolve its id, and offer the matching organization for confirmation before using it; never use a found candidate unconfirmed.
- A name prefix for the things you create.
- Confirmation that the MCP client reports the platform endpoint as connected and authenticated. Nothing in any milestone works without it.
Milestones 1–3 (the platform layer: instances, cluster registrations, agents):
- How the platform layer should be managed: direct apply (the default — this skill creates instances, cluster registrations, and agents through the platform endpoint's apply tools) or Terraform (they live in a Terraform repository with the
akuity/akp provider, the user runs terraform apply, and this skill writes the files and verifies with the read tools — see "Terraform mode" below). If Terraform: where the repository is (a new one laid out like akuity/akp-infra, or an existing one whose layout must be preserved), whether the shell has terraform installed, where state lives (local, or which remote backend), which Argo CD and Kargo versions to pin (the provider requires them; akuity argocd instance versions / akuity kargo instance versions or the portal list what the organization can run), and whether they want the instance admin accounts declared in Terraform too. Anything that already exists on the platform is adopted with terraform import, not recreated.
Milestone 2 (clusters):
- Which Kubernetes clusters to connect, by
kubectl context name, and which environments run on which cluster (e.g. dev and staging on A, prod on B — one cluster for everything is fine too). Confirm each context answers before relying on it: kubectl --context <ctx> get nodes.
- Whether the shell you run commands in has the akuity CLI installed and authenticated against their portal (
akuity login, or the AKUITY_API_KEY_ID/AKUITY_API_KEY_SECRET environment variables). The agent installs run through it; if the CLI is missing or unauthenticated, the user runs those commands themselves or uses the install command shown in the web UI. In Terraform mode, also whether Terraform may install the agents itself from their kubeconfig (it can read the kubeconfig by path and context) or whether the CLI install should stay the path — references/terraform-mode.md.
Milestones 4–6 (apps, pipeline, promotion):
- The container image repository, whether the registry is public, and how its tags are ordered — semantic versions, build timestamps, or lexical names — so the Warehouse gets the right selection strategy. When a pipeline is in scope, do not assume or ask them to approve
latest here: let the Warehouse's discovered artifacts be the source of truth in round two. Only a scope that stops at apps, with no Warehouse or pipeline, needs the user to name the tag here. A private registry will need an image credential before the Warehouse can see it — named again at the moment it matters.
- The git repository for the deployment YAMLs (URL, and whether it is private), whether it already has an environment/branch layout that must be preserved, and whether you may commit the scaffolding yourself or should hand them the files. In app-only scope the scaffolding can land during the first provisioning wait; in pipeline scope it waits for round two so the approved Stage-to-version plan supplies the tags. The push runs on the git credentials already on their machine, and it happens exactly once: promotion commits are later pushed by Kargo itself with the Project's own credential, never from their machine.
- Which environments they want, in promotion order (e.g.
dev → staging → prod), each mapped to one of the clusters above, and which of them count as production — those get an extra explicit confirmation before any promotion reaches them.
- How the Argo CD Applications and the Kargo pipeline resources should be managed: direct apply (the default — this skill applies them through the platform endpoint) or GitOps bootstrap (they live in the repo and Argo CD syncs them — see "GitOps mode" below). If they choose GitOps and have not already named a layout, ask which repo layout, in this order: the two-phase bootstrap this skill scaffolds (
bootstrap/argocd/ + bootstrap/kargo/, the split used by github.com/akuity/akp-demo; the default), the akp-platform quickstart (a fork of github.com/akuity/akp-platform; only with a pipeline in scope), or their existing layout (preserved as-is). Use the client's selection prompt when it offers one (Claude Code AskUserQuestion, Codex request_user_input), folded into the same prompt as the other round-one questions where the client takes several; otherwise one plain-text question with the default named. Proceed with the default when they state no preference, and skip the question when they named a layout up front. In either mode, offer to write the generated manifests into the repo so it records what exists: in direct-apply mode that is documentation, in GitOps mode it is the mechanism.
Milestone 7 (incident triggers):
- How long an app must stay degraded before an incident fires (
degradedFor — a duration like 5m or 1h30m; suggest 5m as a starting point), and whether the trigger should cover all the new namespaces or only some (e.g. prod only).
Round two — after the Warehouse reports discovered artifacts (step 6). Show the candidate versions from the Warehouse status and any Freight already produced, then ask for the desired end state as a complete Stage → version table. Every new Stage gets an explicit version; an existing deployed Stage may instead say "keep current." Separately ask which Stages should actually be promoted today; latest is valid only when the user says it, and must be resolved to the explicit tag and Freight currently discovered before confirmation. "Wire the pipeline but do not promote today" is valid. A skipped Stage cannot sit in the middle of an approved path to a downstream Stage — the normal chain must promote and verify Freight in every Stage it crosses — so surface that conflict instead of silently bypassing it. Compute the distinct versions required by the table, make sure the Warehouse has produced one Freight for each, then derive the ordered promotion hops needed to end at that table. A single Freight still moves through a contiguous Stage path, but one plan may use several Freight — for example, prod=v1 and staging=v2 means promote v1 through prod first, then v2 only through staging. Show every Freight, version, and hop and confirm the whole plan. references/pipeline-facts.md covers discovered artifacts, producing older Freight, and restoring the Warehouse's steady-state subscription afterward.
The flow
Every MCP call below runs on the platform endpoint. The user-owned moments are the agent installs (step 3), the instance login setup (raised at step 4), the git scaffolding (step 7), and the credentials (steps 6, 8, and 10 — each raised only when actually needed). The apply tools are full-tier: an organization whose MCP guardrail level is below full (unset means read_only) sees every apply refuse with requires guardrail level "full", the message naming its current level. An Organization Owner raises it under Organization Settings → MCP Access — name it, keep doing the reads, and do not work around it. In Terraform mode, steps 1, 3, 4, and 11 produce Terraform that the user applies instead of calls to the apply tools; see "Terraform mode" below for the deltas. Step 2's polling, every health check, steps 5–10, and step 12 are unchanged.
- Create the Argo CD instance. The platform's Argo CD apply tool is composite: one call carries the instance manifest, plus every cluster registration as
clusters entries (shapes in ../../references/manifest-kinds.md). Instances created through this endpoint get MCP access enabled automatically. spec.instanceSpec.mcpServer.enabled serves the instance's own /mcp endpoint and lets platform tools target the instance; carry it explicitly only when updating a pre-existing instance in direct-apply mode. In Terraform mode, the toggle is the mcp_server attribute when the pinned provider has it, otherwise a portal step; see "Terraform mode" below. Do not send admin-account or OIDC config with the initial request. The platform endpoint's Argo CD tools work without an instance login. A login is needed for people using the instance UI, CLI, or direct MCP endpoint, and the user can set it up later in the portal (references/instance-access.md and the closing checklist). Children in the same call as their instance are safe. Any other call that references the instance id must wait for health; see step 4. Creation returns when the request is accepted, not when the instance is usable.
- Poll a read tool until the instance reports healthy. A fresh instance may first read unknown ("failed to get tenant status") and then progressing — normal. Healthy usually lands within a couple of minutes; use background waits and report progress rather than going silent. If the instance disappears from list reads instead of going healthy, its creation failed: re-apply it and re-read its id — the recreated instance gets a new id, so never reuse an id recorded before the instance reported healthy. In app-only scope, the git scaffolding (step 7) needs no platform, so do it during this wait; in pipeline scope, wait for round two's Stage-to-version plan.
- Install the cluster agent with the akuity CLI — once per cluster. The platform apply tool's description names the exact command (
akuity argocd cluster install-agent --org-id=… --instance-id=… <cluster name>). Run it once for each registered cluster, each with --context set to that cluster's context. Pick the branch that fits: (a) if your shell has the akuity CLI authenticated and kubeconfig contexts for their clusters, run them yourself; (b) otherwise hand them the commands to run in their own shell; (c) if they are not using the CLI at all, tell them to copy the install command from each cluster's page in the web UI and run that. Always pass --organization-id explicitly — the CLI silently falls back to the default organization in its own config file, which may not be theirs. Never pipe or filter install-agent's output — piping wedges it silently, doing nothing for minutes; run it in the background with output redirected to a log file and read the log. And never fetch or print the raw install manifests — they contain live credentials; install-agent streams them straight into kubectl without ever putting them on stdout. install-agent exists in akuity CLI 0.33 and later; an older CLI has only get-agent-manifests, so have the user upgrade instead of piping manifests through kubectl. Then poll until every cluster reports healthy — before its agent is installed a cluster reads unknown with "Did you install the agent manifests?".
- Create the Kargo instance only after the Argo CD instance reports healthy. The Kargo apply is composite too: the instance manifest (
spec.kargoInstanceSpec), plus an Akuity-managed Kargo agent as an agents entry. Set spec.data.akuityManaged: true and set spec.data.remoteArgocd to the Argo CD instance id read after it became healthy. A reference to a still-provisioning or failed instance is rejected. Nothing needs to be installed or run by the user, and this link lets promotion steps drive Argo CD. Do not send authentication config with this call, but use the provisioning wait to tell the user what Kargo needs from them. Freight reads and promotions require an admin account or OIDC. Without it, those tools may return Internal error occurred (reference: …), while platform lifecycle reads and applies remain available. The user enables the admin account and sets a password under Settings → System Accounts, or configures Settings → OIDC Config. They act in the UI, and you verify afterward from the instance read (apiCm.adminAccountEnabled: true, or OIDC config present) and a cheap Kargo read. references/instance-access.md covers both modes and a declarative fallback. If they defer it, keep going through step 5; step 6 is the first Kargo read that depends on it.
- Create the Kargo Project and Warehouse, and nothing else yet. Do not put a Kargo read in front of this step: the platform apply remains available before the instance has admin or OIDC configured. One platform Kargo apply carries the
Project and the Warehouse subscribed to the container image repository. Set metadata.namespace: <project name> on the Warehouse and on every Stage and credential Secret later. On the platform endpoint, an omitted namespace silently lands the resource in the wrong place. Read references/pipeline-facts.md before writing these manifests. The shard, namespace, tag-selection, and credential rules there are required for a working pipeline. Start with filters broad enough to expose useful candidates and a discoveryLimit large enough for the initial choice. An automatically produced newest Freight is discovery output, not permission to deploy it. Creating the Warehouse before choosing versions or creating the Stages is deliberate: its status is the source of truth for the first release. If no pipeline is in scope, skip steps 5–6 and use the tag the user named in round one at step 7.
- Read discovered artifacts, make the target matrix, then ensure its Freight exists. First try one cheap Kargo read. If it fails and the instance read shows neither
apiCm.adminAccountEnabled: true nor OIDC config, point the user to Settings → System Accounts or Settings → OIDC Config (or the declarative fallback). State that Freight selection and promotion cannot continue without authentication, and leave the Project and Warehouse standing while they decide. Once Kargo answers, read the Warehouse status and wait for status.discoveredArtifacts, not merely its automatically produced newest Freight. A private registry yields nothing until its image credential exists in the Project. That credential is the user's action: a labeled Secret applied with akuity kargo apply using a placeholder, or the instance UI's credentials page. See references/pipeline-facts.md for the shapes. No discovered artifacts after a full interval means something is misconfigured; check references/troubleshooting.md instead of waiting indefinitely. Run round two with the discovered versions and collect the full Stage-to-version table. Compute the required version set; for each version without Freight, temporarily narrow the image subscription so it becomes the best match, wait for its Freight, and repeat. Restore the Warehouse to the user's intended ongoing selection policy after the required Freight exist. Never leave a temporary exact or upper-bound constraint behind. Finally derive every contiguous hop for every Freight, order the hops so the final Stage state matches the table, show the full plan, and get approval.
- Scaffold the repo: preserve an existing layout, or create one directory per environment with a Deployment and a Service. In pipeline scope, pin each new environment to the version approved for that Stage in step 6 and leave an existing "keep current" environment unchanged. A Stage not being promoted today still has valid desired state in git, but its Application remains unsynced. In app-only scope, use the tag named in round one. Commit and push. This is a user-owned step done with git, not MCP; use their clone and their credentials, and only if they said you may. This is also the only moment anything is pushed from their machine. Each later promotion updates the image tag through Kargo using the Project's git credential from step 10. Neither you nor the user pushes a promotion manually.
- Create one Argo CD Application per environment — through the same platform apply tool, the Application manifests riding in the call's applications list with the instance named explicitly: source is the repo plus that environment's path; destination is that environment's registered cluster by name, namespace
<prefix>-<env> with CreateNamespace=true; and the kargo.akuity.io/authorized-stage annotation naming the Stage that will manage it (format in references/pipeline-facts.md; Stage names are the environment names, so this is known before the Stages land in step 9). A failed apply may still have landed earlier resources — apply is upsert, so fix what the error names and re-send the same call. Give the apps no automated sync policy — and whether you sync them now depends on scope. Pipeline in scope: do not sync anything; each environment's first deployment is its first promotion (step 10), so every version that reaches a cluster arrives through the pipeline, and an environment whose promotion the user never approves stays undeployed. Scope stops at milestone 4: run the platform endpoint's application sync tool once per app and confirm each reaches the pushed revision healthy. If the repo is private, Argo CD needs its own repository credential before it can read the repo at all — apps show comparison errors until it exists. That credential is the user's action (a repository-credential Secret with the token left as a placeholder and the akuity argocd apply command for their own shell — exact shape in references/pipeline-facts.md — or the repository settings in the instance UI); hand it to them, verify by outcome, and don't stall unrelated work on it.
- Create the complete Stage topology. Apply one chained Stage for every environment named in round one, regardless of how far this release will go: the first takes Freight directly from the Warehouse and each downstream Stage takes it from the Stage before it. The release plan controls which promotions execute, not which pipeline resources exist. Carry all Stages in the same platform Kargo apply's list argument, every one with
metadata.namespace: <project name> and promotion steps that update that environment's YAML in git and sync its app (references/pipeline-facts.md has the working shape). This completes the wired pipeline even when the user chose no promotion today.
- Execute the approved multi-Freight plan — and this is the moment the git credential is needed. Promotion steps clone the repo and push commits, so before the first promotion the Project needs a git credential with read access when the repo is private and push access in every case — the user's action in their own shell (labeled Secret via
akuity kargo apply, or the instance UI; exact command with a placeholder in references/pipeline-facts.md). If they chose not to promote today, stop here cleanly: everything built so far stands, and the closing checklist names what promotion will need. For each approved hop, in order: re-read that Freight for the target Stage first (the promote tool's own contract — Freight eligibility is per-Stage), then promote, then confirm three things before the next hop: the Promotion succeeded, the environment's Argo CD app is synced and healthy — in pipeline scope this is that environment's first deployment, and a Promotion may find nothing to change when the scaffold already carries that hop's tag; the sync it drives is still the point — and the same Freight shows verifiedIn for that Stage, which the downstream Stage requires. Before any environment the user named as production, stop and confirm explicitly one more time, even though the plan was approved — name the Freight, the version, and the target.
- Wire incident response (if chosen — and worth offering once the apps are deployed, even to a user who stopped before promotion). Akuity agents and their triggers live in the Argo CD instance spec. In Terraform mode, update the instance's Terraform configuration as described under "Terraform mode" below. In direct-apply mode they are applied through the same platform endpoint, and that apply is a JSON merge patch: nested objects merge field by field, but lists are replaced whole —
incidents.triggers and runbooks included — and no MCP read returns the instance's full manifest (the list reads are compact). So on an instance this flow just created, a partial spec carrying only the additions is safe; on a pre-existing instance that may already have triggers or runbooks, do not guess — have the user export the current manifest in their shell, filtered to the one field so nothing else leaves it — akuity argocd export --organization-id <org> <instance name> | yq 'select(.kind == "ArgoCD") | .spec.instanceSpec.kubeVisionConfig.aiConfig' (the raw export is unredacted: OIDC client secrets, password hashes) — and hand you only that aiConfig block to carry forward, or add the trigger themselves in the portal (instance settings, Akuity Intelligence, Incidents tab). Set spec.instanceSpec.akuityIntelligenceExtension.enabled: true, and add one entry per scope under spec.instanceSpec.kubeVisionConfig.aiConfig.incidents.triggers, each a selector of argocdApplications, k8sNamespaces, clusters, and degradedFor (how long the object must stay degraded before the incident is created). A trigger with no clusters entry never fires — always name at least the clusters from milestone 2. The apply's success is the only MCP-side signal — no read returns the triggers — so confirm in the portal's Incidents tab or by a trigger firing. In direct-apply mode, the same config is editable later in the portal under the instance's Akuity Intelligence settings (Incidents tab). Once a trigger fires, the incident is investigated by Akuity's On-call Agent — working with it is the akuity:delegate skill's job, not this one's. If the extension is unavailable to the organization, that is plan gating — the organization talks to Akuity; there is no configuration path around it.
- Read back what you built and show them, from platform-endpoint reads alone: instances, clusters, agent, apps, pipeline, and promotion history (incident triggers are not readable over MCP — point at the portal).
If a step misbehaves — a Warehouse that never produces Freight, a Promotion that fails at clone or push — check references/troubleshooting.md before retrying anything; most of these failures are silent misconfigurations with exact fixes, not transient errors.
GitOps mode (optional)
The default flow direct-applies the Applications and the Kargo pipeline, which leaves the repo holding only the deployment YAMLs. If the user chose GitOps at scope time, the control resources live in the repo instead and Argo CD syncs them. Round one also settled which layout: the two-phase bootstrap (the default), the akp-platform quickstart, or their existing one. Instances, clusters, credentials, round two, and promotion approval are identical in every layout; only the steps below change, and only the chosen layout's subsection applies.
Shared by every layout
- Register the Kargo control plane as an Argo CD destination — once, and only if the repo's control Applications target it. The two-phase and akp-platform layouts sync Kargo resources through an Argo CD Application whose destination is the Kargo control plane, conventionally named
kargo (akp-platform's personalize.sh asks for the name; match whatever the repo's manifests use). An existing repo that already targets it under any name needs nothing, and mixed mode (Kargo resources direct-applied) needs nothing. Shape in ../../references/manifest-kinds.md: a Cluster with spec.data.size: small and spec.data.directClusterSpec. The Kargo id exists only after step 4, so this lands as an instance update once the Kargo instance is healthy. In Terraform mode it is an akp_cluster with spec.data.direct_cluster_spec and cluster_type = "kargo" (stack 02-kargo in the reference layout); read the pinned provider's schema for the exact attributes, then plan and hand over as for the other stacks. A Kargo instance can be registered on one Argo CD instance only — a second attempt fails with kargo instance is already registered with another argocd instance as a target cluster. The cluster list read does not echo directClusterSpec — verify by outcome: the Application targeting it reaches Synced.
- Credential Secrets never enter git; they stay a user-shell action exactly as in
references/pipeline-facts.md, one per Kargo Project.
- After bootstrap, git is the write path. Changing or removing a GitOps'd Application or Kargo resource means a commit, not an MCP apply or delete — an MCP write would fight the bootstrap app's sync and be pruned or reverted. The MCP tools stay the read, verify, and promote surface.
Layout: two-phase bootstrap (default)
The layout of Akuity's demo repo (github.com/akuity/akp-demo, akp-demo/bootstrap): bootstrap/argocd/ holds the Applications, bootstrap/kargo/ holds the Kargo resources.
- Bootstrap the control resources before choosing versions. At step 5,
bootstrap/kargo/ holds only the Project and Warehouse, while bootstrap/argocd/ holds one bootstrap Application whose destination is the Kargo control plane (kargo), source path is bootstrap/kargo/, and sync policy is automated with prune. After round two, the step-7 commit adds the environment directories pinned to their approved Stage versions, step 8 adds the per-environment Application manifests (authorized-stage annotations included, no automated sync), and step 9 adds the complete Stage chain.
- Steps 5 and 9's Kargo applies become commits and syncs: apply only the contents of
bootstrap/argocd/ through the platform apply — the bootstrap Application first, then the per-environment Applications after the Stage-to-version plan — and the Project, Warehouse, and later the complete Stage chain arrive by sync from git. (For everything-in-git, wrap bootstrap/argocd/ itself in one more app-of-apps Application and direct-apply only that.) Credentials, artifact discovery, round two, and promotion verification are unchanged.
Layout: akp-platform quickstart (pipeline scope only) — read references/akp-platform.md once this layout is chosen. In short: a fork of github.com/akuity/akp-platform (root app-of-apps, discovery ApplicationSets over apps/<name>/argocd/ and apps/<name>/kargo/, four sample promotion patterns); two phases — control files plus the platform-aoa apply before round two so the Warehouse exists, then manifests, appset, Stages, and pinned env/<stage> after the plan; needs spec.kargoInstanceSpec.defaultShardAgent (the repo carries no spec.shard) and one git credential per Kargo Project; offered only with a pipeline in scope because the rendered-branch samples have no source until promoted.
Layout: existing repo
- Preserve what is there. Read their tree first and map it: where Argo CD control resources live (an app-of-apps, or a directory one Application syncs), where Kargo resources live, where per-environment manifests live. Apply only what serves as the root today — their existing bootstrap Application, or one new Application pointing at the directory that holds the control resources — and land the Project and Warehouse (step 5), the Applications (step 8), and the Stages (step 9) as commits into their existing places, in the same two phases as the default layout above. If the layout has no home for Kargo resources, say so and direct-apply those while the Applications stay GitOps'd — a mixed mode is fine when it is explicit. Never restructure a repo to fit a template they did not choose.
Terraform mode (optional)
The default flow creates the platform layer — instances, cluster registrations, agents — through the apply tools, so it exists only on the platform. If the user chose Terraform at scope time, that layer lives in a Terraform repository with the akuity/akp provider, laid out like Akuity's own github.com/akuity/akp-infra (01-argocd, 02-kargo, 03-clusters), and the user or their CI runs terraform apply. It is independent of the config-layer choice: Terraform with direct apply, or Terraform with GitOps mode (which is exactly akp-infra plus akp-platform). Read references/terraform-mode.md before writing any Terraform — it carries the layout, the source of every value the provider schema leaves open, the attributes that must be explicit, the import loop, and what the agent runs versus what only the user runs. The flow above still holds; these are the deltas:
- You write, validate, and plan; the user applies. For each stack: write the files in their clone (start from akp-infra's stack, not a blank page, keeping only the choices
terraform-mode.md marks as this flow's defaults), run terraform init, terraform validate, and — once their API key is exported in the shell — terraform plan, show the plan, and hand over. terraform apply, destroy, and import are theirs. Then verify with the platform read tools exactly as steps 2–4 describe; an apply finishing is not the health signal.
- Every attribute comes from the installed provider's schema, every open value from its one source. Pin one exact provider version, read
terraform providers schema -json before each resource block, and never guess a name or nesting; a validate or plan failure gets one schema-backed correction, and two with no new information is a stop. The instance version is required by the provider — the user names it in round one; offer the list from akuity argocd instance versions / akuity kargo instance versions if they want help, and never fill it from an example, a template, or latest.
- Step 1 becomes stack
01-argocd (one akp_instance); cluster registrations do not ride in it — they are stack 03. Step 4 becomes stack 02-kargo: akp_kargo_instance plus one Akuity-managed akp_kargo_agent (akuity_managed = true, remote_argocd = the Argo CD instance id from a data "akp_instance" lookup by name), applied only after the Argo CD instance reads healthy. akp-infra's self-hosted per-cluster agents are an option the user chooses, not the default. Step 3 becomes stack 03-clusters: one akp_cluster per cluster from round one, with the explicit attributes terraform-mode.md lists; with kube_config set from their kubeconfig path and context plus ensure_healthy = true, Terraform installs the agent and the apply blocks until it is healthy; without kube_config, the registration lands and the agent is installed with the CLI as in step 3.
- Step 11 updates
akp_instance in the Terraform repository (01-argocd in the reference layout). Read the current instance and Terraform configuration, preserve existing AI settings and triggers, and add the requested incident scopes using the pinned provider's schema. Plan and hand over as for the other stacks. Then read the instance back to verify the extension and triggers. Later changes to these settings follow the same path.
- Instance logins can be declared in Terraform if the user asked for it in round one: the admin account and a bcrypt-hashed password from a
TF_VAR_admin_password variable they export themselves, with ignore_changes on the secret — shape in terraform-mode.md. The password never enters the chat or a command line. Otherwise the login stays the portal action of step 4 and references/instance-access.md.
- MCP access on Terraform-created instances. Instances the apply tools create get it automatically; Terraform-created ones get it only when the configuration says so. Let the pinned provider's schema decide: when
akp_instance and akp_kargo_instance carry mcp_server, set mcp_server = { enabled = true } in stacks 01 and 02 and access is on from creation, with Terraform owning the toggle (a portal switch-off shows as drift on the next plan). Provider 0.15.0 and earlier have no such attribute; there, right after stack 02 applies, have the user enable both instances under Organization Settings → MCP Access → Endpoints → Instance access — a later terraform apply does not turn it off. Either way, the lifecycle reads that verify milestones 1–3 work regardless, and every in-instance tool from step 5 on (applications, freight, promotions) is denied until it is on.
- Existing instances and clusters are imported, not recreated. Write the block to match the live object (read it with the lifecycle tools), take the import ID format from the pinned provider version's registry docs, prefer
import blocks the user applies, and reconcile the plan to zero — a destroy/recreate in that plan is a stop, not something to apply.
- **After the first ap
…(truncated)
1---2name: onboard3description: Onboard onto the Akuity platform through its platform MCP endpoint: create Argo CD and Kargo instances, connect clusters, deploy an app to every environment through Argo CD applications, wire a Kargo pipeline to those apps, and promote an image release through the environments — all on the one endpoint. Use when asked to onboard onto Akuity, set up Akuity from scratch, or deploy a first app with a promotion pipeline — for the whole path or any part of it (a single instance, a cluster connection, or a pipeline onto instances that already exist), including when the instances and clusters should be managed with Terraform.4---56You are onboarding someone onto the Akuity platform. The full path starts from an Akuity account, one or more Kubernetes clusters, a container image, and a git repository, and ends with Argo CD running, the clusters connected, the app deployed to every environment by an Argo CD application, and a Kargo pipeline that promotes the image through those environments by updating git and syncing the apps — without ever opening the Akuity UI for the build itself. Each environment maps to a cluster the user names (several environments may share one — e.g. dev and staging on cluster A, prod on cluster B) and gets its own namespace. Not everyone wants the whole path, and parts of it may already exist — so the first move is agreeing on scope, not creating anything.78The whole flow runs on **one MCP endpoint — the platform endpoint**, with the organization and instance named explicitly on every call. Its apply tools are composite: one call carries an instance together with what lives inside it — Argo CD Applications ride in the Argo CD apply, Kargo projects, warehouses, and stages in the Kargo apply — and the platform endpoint also serves the sync, freight, and promotion tools the later steps need. Each provisioned instance can additionally serve its own MCP endpoint, where the same in-instance work runs under the instance's own RBAC — but **connecting one is never required**: with the platform endpoint connected, everything in this flow and its day-2 follow-ons is already reachable (instances this flow creates allow platform MCP actions automatically; a pre-existing instance must have MCP access enabled before the in-instance tools reach it — and every Kargo instance, new or pre-existing, needs its authentication configured before Kargo's API answers at all: `../../references/endpoints-and-auth.md`). It is a choice the user can make, mainly for teammates who hold instance access without organization access — see "The instances' own endpoints" below. Read `../../references/endpoints-and-auth.md` and `../../references/manifest-kinds.md` (paths relative to this file) before your first call — they carry the endpoint model and the manifest rules this skill depends on. Before writing an instance, cluster, Argo CD, or Kargo resource, also read the relevant section of `references/official-docs.md`. For a new instance, omit its version as `manifest-kinds.md` requires; after it becomes healthy, read the assigned version before writing its in-instance resources. Then read `tools/list` and the tool descriptions; this skill gives you the order and the platform-specific facts, not the full tool contracts.910Treat the flow below as a dependency order, not a script. Tool names and manifest shapes may have moved since this was written. The live tool description defines the MCP call envelope; the installed product version's official docs and CRD define the resource inside it. When they disagree with this skill, use those current sources and tell the user about the difference rather than forcing the text. If neither source defines a field, stop and ask or defer that setup — never try plausible field names or nesting until one happens to apply. The goal state is fixed even when the path is not: whatever scope the user chose, standing and verifiable from MCP reads at the end.1112## The one principle that shapes everything here1314**You never configure the user's credentials or logins for them, and nothing optional blocks the flow.** Passwords, password hashes, OIDC client secrets, git and registry tokens — all of it is the user's own action, in the portal UI or their own shell, with you supplying the exact place or command and a placeholder. Your job is to keep building everything that does not depend on the missing piece, say plainly at the moment a piece is needed what it is for and what fails without it, verify by outcome once the user has acted, and close with a checklist of anything still unconfigured and its consequences. Never park the whole flow on a setup question, and never take a secret into the conversation to unpark it.1516## The milestones — offer them, let the user choose1718These are the milestones, in dependency order — not an all-or-nothing script:19201. **Argo CD instance** — provisioned and healthy (flow steps 1–2).212. **Clusters connected** — every cluster the environments map to registered with the instance, agent installed, healthy (step 3).223. **Kargo instance** — provisioned likewise, with an Akuity-managed Kargo agent linked to the Argo CD instance (step 4).234. **Apps created** — deployment YAMLs per environment in git, one Argo CD Application per environment (steps 7–8). If the chosen scope stops here, this milestone also runs each app's first sync so the app is actually deployed; with a pipeline in scope, the tags come from the approved Stage-to-version plan and deployment is milestone 6's job.245. **Pipeline wired** — Kargo Project, a Warehouse watching their image, and — after the user has seen what the Warehouse discovered and chosen the desired version for each Stage — one chained Stage per environment (steps 5–9).256. **Release promoted** — the required Freight carried through the environments per a plan the user approved, each hop verified; in pipeline scope this is where each approved environment's first deployment happens (step 10).267. **Incident response wired** (optional) — Akuity Agents enabled on the Argo CD instance with a resource-degradation trigger scoped to the new clusters and namespaces, so a degraded app opens an incident by itself instead of waiting for someone to notice (step 11).2728Open by naming these and asking how far they want to go: the full path, one milestone, or just the missing pieces. Then establish where they already stand with read tools before creating anything. An instance, cluster, or pipeline that already exists and is healthy is a prerequisite satisfied, not something to recreate. One dependency to name up front: **Kargo Project, Stage, Freight, and Promotion tools require the instance to have an admin account or OIDC configured.** Platform lifecycle reads and applies remain available, so instance creation and platform applies of Project, Warehouse, and Stage do not depend on this setup. Authentication is the user's own action and can happen at creation or later. It gates the Kargo reads and promotions in milestones 5–6, but it must not stall independent work. See steps 4–6 and `references/instance-access.md`. Someone with a running instance and a connected cluster who asks to "onboard" needs milestones 4–6, not a second instance.2930## Ask in two rounds3132Provisioning waits are the rhythm of this flow, so batch the questions: one round at scope time, and — only when a pipeline is in scope — one round after the Warehouse reports its discovered artifacts, when the versions on the table are real data instead of guesses. **Never ask for a token, password, or password hash in chat**: anything pasted into the conversation persists in tool-call data. Instance logins are deliberately not asked about here at all — they are the user's own setup in the portal UI, raised at the moment they matter (step 4) and again in the closing checklist.3334**Round one — at scope time.** Any scope:3536- Their Akuity organization. Call `list_organizations` to resolve its id, and offer the matching organization for confirmation before using it; never use a found candidate unconfirmed.37- A name prefix for the things you create.38- Confirmation that the MCP client reports the platform endpoint as connected and authenticated. Nothing in any milestone works without it.3940Milestones 1–3 (the platform layer: instances, cluster registrations, agents):4142- How the platform layer should be managed: **direct apply** (the default — this skill creates instances, cluster registrations, and agents through the platform endpoint's apply tools) or **Terraform** (they live in a Terraform repository with the `akuity/akp` provider, the user runs `terraform apply`, and this skill writes the files and verifies with the read tools — see "Terraform mode" below). If Terraform: where the repository is (a new one laid out like `akuity/akp-infra`, or an existing one whose layout must be preserved), whether the shell has `terraform` installed, where state lives (local, or which remote backend), which Argo CD and Kargo versions to pin (the provider requires them; `akuity argocd instance versions` / `akuity kargo instance versions` or the portal list what the organization can run), and whether they want the instance admin accounts declared in Terraform too. Anything that already exists on the platform is adopted with `terraform import`, not recreated.4344Milestone 2 (clusters):4546- Which Kubernetes clusters to connect, by `kubectl` context name, and which environments run on which cluster (e.g. dev and staging on A, prod on B — one cluster for everything is fine too). Confirm each context answers before relying on it: `kubectl --context <ctx> get nodes`.47- Whether the shell you run commands in has the akuity CLI installed and authenticated against their portal (`akuity login`, or the `AKUITY_API_KEY_ID`/`AKUITY_API_KEY_SECRET` environment variables). The agent installs run through it; if the CLI is missing or unauthenticated, the user runs those commands themselves or uses the install command shown in the web UI. In Terraform mode, also whether Terraform may install the agents itself from their kubeconfig (it can read the kubeconfig by path and context) or whether the CLI install should stay the path — `references/terraform-mode.md`.4849Milestones 4–6 (apps, pipeline, promotion):5051- The container image repository, whether the registry is public, and how its tags are ordered — semantic versions, build timestamps, or lexical names — so the Warehouse gets the right selection strategy. When a pipeline is in scope, **do not assume or ask them to approve `latest` here**: let the Warehouse's discovered artifacts be the source of truth in round two. Only a scope that stops at apps, with no Warehouse or pipeline, needs the user to name the tag here. A private registry will need an image credential before the Warehouse can see it — named again at the moment it matters.52- The git repository for the deployment YAMLs (URL, and whether it is private), whether it already has an environment/branch layout that must be preserved, and whether you may commit the scaffolding yourself or should hand them the files. In app-only scope the scaffolding can land during the first provisioning wait; in pipeline scope it waits for round two so the approved Stage-to-version plan supplies the tags. The push runs on the git credentials already on their machine, and it happens exactly once: promotion commits are later pushed by Kargo itself with the Project's own credential, never from their machine.53- Which environments they want, in promotion order (e.g. `dev` → `staging` → `prod`), each mapped to one of the clusters above, and which of them count as production — those get an extra explicit confirmation before any promotion reaches them.54- How the Argo CD Applications and the Kargo pipeline resources should be managed: **direct apply** (the default — this skill applies them through the platform endpoint) or **GitOps bootstrap** (they live in the repo and Argo CD syncs them — see "GitOps mode" below). If they choose GitOps and have not already named a layout, ask **which repo layout**, in this order: the **two-phase bootstrap** this skill scaffolds (`bootstrap/argocd/` + `bootstrap/kargo/`, the split used by github.com/akuity/akp-demo; the default), the **akp-platform quickstart** (a fork of github.com/akuity/akp-platform; only with a pipeline in scope), or their **existing layout** (preserved as-is). Use the client's selection prompt when it offers one (Claude Code `AskUserQuestion`, Codex `request_user_input`), folded into the same prompt as the other round-one questions where the client takes several; otherwise one plain-text question with the default named. Proceed with the default when they state no preference, and skip the question when they named a layout up front. In either mode, offer to write the generated manifests into the repo so it records what exists: in direct-apply mode that is documentation, in GitOps mode it is the mechanism.5556Milestone 7 (incident triggers):5758- How long an app must stay degraded before an incident fires (`degradedFor` — a duration like `5m` or `1h30m`; suggest `5m` as a starting point), and whether the trigger should cover all the new namespaces or only some (e.g. prod only).5960**Round two — after the Warehouse reports discovered artifacts (step 6).** Show the candidate versions from the Warehouse status and any Freight already produced, then ask for the desired end state as a complete **Stage → version** table. Every new Stage gets an explicit version; an existing deployed Stage may instead say "keep current." Separately ask which Stages should actually be promoted today; `latest` is valid only when the user says it, and must be resolved to the explicit tag and Freight currently discovered before confirmation. "Wire the pipeline but do not promote today" is valid. A skipped Stage cannot sit in the middle of an approved path to a downstream Stage — the normal chain must promote and verify Freight in every Stage it crosses — so surface that conflict instead of silently bypassing it. Compute the distinct versions required by the table, make sure the Warehouse has produced one Freight for each, then derive the ordered promotion hops needed to end at that table. A single Freight still moves through a contiguous Stage path, but one plan may use several Freight — for example, `prod=v1` and `staging=v2` means promote `v1` through prod first, then `v2` only through staging. Show every Freight, version, and hop and confirm the whole plan. `references/pipeline-facts.md` covers discovered artifacts, producing older Freight, and restoring the Warehouse's steady-state subscription afterward.6162## The flow6364Every MCP call below runs on the platform endpoint. The user-owned moments are the agent installs (step 3), the instance login setup (raised at step 4), the git scaffolding (step 7), and the credentials (steps 6, 8, and 10 — each raised only when actually needed). The apply tools are `full`-tier: an organization whose MCP guardrail level is below `full` (unset means `read_only`) sees every apply refuse with `requires guardrail level "full"`, the message naming its current level. An Organization Owner raises it under Organization Settings → MCP Access — name it, keep doing the reads, and do not work around it. In Terraform mode, steps 1, 3, 4, and 11 produce Terraform that the user applies instead of calls to the apply tools; see "Terraform mode" below for the deltas. Step 2's polling, every health check, steps 5–10, and step 12 are unchanged.65661. **Create the Argo CD instance.** The platform's Argo CD apply tool is composite: one call carries the instance manifest, plus every cluster registration as `clusters` entries (shapes in `../../references/manifest-kinds.md`). Instances created through this endpoint get MCP access enabled automatically. `spec.instanceSpec.mcpServer.enabled` serves the instance's own `/mcp` endpoint and lets platform tools target the instance; carry it explicitly only when updating a pre-existing instance in direct-apply mode. In Terraform mode, the toggle is the `mcp_server` attribute when the pinned provider has it, otherwise a portal step; see "Terraform mode" below. **Do not send admin-account or OIDC config with the initial request.** The platform endpoint's Argo CD tools work without an instance login. A login is needed for people using the instance UI, CLI, or direct MCP endpoint, and the user can set it up later in the portal (`references/instance-access.md` and the closing checklist). Children in the same call as their instance are safe. Any other call that references the instance id must wait for health; see step 4. Creation returns when the request is accepted, not when the instance is usable.672. **Poll a read tool until the instance reports healthy.** A fresh instance may first read unknown ("failed to get tenant status") and then progressing — normal. Healthy usually lands within a couple of minutes; use background waits and report progress rather than going silent. **If the instance disappears from list reads instead of going healthy, its creation failed**: re-apply it and re-read its id — the recreated instance gets a new id, so never reuse an id recorded before the instance reported healthy. In app-only scope, the git scaffolding (step 7) needs no platform, so do it during this wait; in pipeline scope, wait for round two's Stage-to-version plan.683. **Install the cluster agent with the akuity CLI — once per cluster.** The platform apply tool's description names the exact command (`akuity argocd cluster install-agent --org-id=… --instance-id=… <cluster name>`). Run it once for each registered cluster, each with `--context` set to that cluster's context. Pick the branch that fits: (a) if your shell has the akuity CLI authenticated and kubeconfig contexts for their clusters, run them yourself; (b) otherwise hand them the commands to run in their own shell; (c) if they are not using the CLI at all, tell them to copy the install command from each cluster's page in the web UI and run that. Always pass `--organization-id` explicitly — the CLI silently falls back to the default organization in its own config file, which may not be theirs. Never pipe or filter `install-agent`'s output — piping wedges it silently, doing nothing for minutes; run it in the background with output redirected to a log file and read the log. And never fetch or print the raw install manifests — they contain live credentials; `install-agent` streams them straight into kubectl without ever putting them on stdout. `install-agent` exists in akuity CLI 0.33 and later; an older CLI has only `get-agent-manifests`, so have the user upgrade instead of piping manifests through kubectl. Then poll until every cluster reports healthy — before its agent is installed a cluster reads unknown with "Did you install the agent manifests?".694. **Create the Kargo instance only after the Argo CD instance reports healthy.** The Kargo apply is composite too: the instance manifest (`spec.kargoInstanceSpec`), plus an **Akuity-managed Kargo agent as an `agents` entry**. Set `spec.data.akuityManaged: true` and set `spec.data.remoteArgocd` to the Argo CD instance **id read after it became healthy**. A reference to a still-provisioning or failed instance is rejected. Nothing needs to be installed or run by the user, and this link lets promotion steps drive Argo CD. **Do not send authentication config with this call, but use the provisioning wait to tell the user what Kargo needs from them.** Freight reads and promotions require an admin account or OIDC. Without it, those tools may return `Internal error occurred (reference: …)`, while platform lifecycle reads and applies remain available. The user enables the admin account and sets a password under **Settings → System Accounts**, or configures **Settings → OIDC Config**. They act in the UI, and you verify afterward from the instance read (`apiCm.adminAccountEnabled: true`, or OIDC config present) and a cheap Kargo read. `references/instance-access.md` covers both modes and a declarative fallback. If they defer it, keep going through step 5; step 6 is the first Kargo read that depends on it.705. **Create the Kargo Project and Warehouse, and nothing else yet.** Do not put a Kargo read in front of this step: the platform apply remains available before the instance has admin or OIDC configured. One platform Kargo apply carries the `Project` and the `Warehouse` subscribed to the container image repository. **Set `metadata.namespace: <project name>` on the Warehouse** and on every Stage and credential Secret later. On the platform endpoint, an omitted namespace silently lands the resource in the wrong place. **Read `references/pipeline-facts.md` before writing these manifests.** The shard, namespace, tag-selection, and credential rules there are required for a working pipeline. Start with filters broad enough to expose useful candidates and a `discoveryLimit` large enough for the initial choice. An automatically produced newest Freight is discovery output, not permission to deploy it. Creating the Warehouse before choosing versions or creating the Stages is deliberate: its status is the source of truth for the first release. If no pipeline is in scope, skip steps 5–6 and use the tag the user named in round one at step 7.716. **Read discovered artifacts, make the target matrix, then ensure its Freight exists.** First try one cheap Kargo read. If it fails and the instance read shows neither `apiCm.adminAccountEnabled: true` nor OIDC config, point the user to **Settings → System Accounts** or **Settings → OIDC Config** (or the declarative fallback). State that Freight selection and promotion cannot continue without authentication, and leave the Project and Warehouse standing while they decide. Once Kargo answers, read the Warehouse status and wait for `status.discoveredArtifacts`, not merely its automatically produced newest Freight. A **private registry yields nothing until its image credential exists in the Project**. That credential is the user's action: a labeled Secret applied with `akuity kargo apply` using a placeholder, or the instance UI's credentials page. See `references/pipeline-facts.md` for the shapes. No discovered artifacts after a full interval means something is misconfigured; check `references/troubleshooting.md` instead of waiting indefinitely. Run round two with the discovered versions and collect the full Stage-to-version table. Compute the required version set; for each version without Freight, temporarily narrow the image subscription so it becomes the best match, wait for its Freight, and repeat. **Restore the Warehouse to the user's intended ongoing selection policy after the required Freight exist.** Never leave a temporary exact or upper-bound constraint behind. Finally derive every contiguous hop for every Freight, order the hops so the final Stage state matches the table, show the full plan, and get approval.727. **Scaffold the repo**: preserve an existing layout, or create one directory per environment with a Deployment and a Service. In pipeline scope, pin each new environment to the version approved for that Stage in step 6 and leave an existing "keep current" environment unchanged. A Stage not being promoted today still has valid desired state in git, but its Application remains unsynced. In app-only scope, use the tag named in round one. Commit and push. This is a user-owned step done with git, not MCP; use their clone and their credentials, and only if they said you may. This is also the **only** moment anything is pushed from their machine. Each later promotion updates the image tag through Kargo using the Project's git credential from step 10. Neither you nor the user pushes a promotion manually.738. **Create one Argo CD Application per environment — through the same platform apply tool**, the Application manifests riding in the call's applications list with the instance named explicitly: source is the repo plus that environment's path; destination is that environment's registered cluster by name, namespace `<prefix>-<env>` with `CreateNamespace=true`; and the `kargo.akuity.io/authorized-stage` annotation naming the Stage that will manage it (format in `references/pipeline-facts.md`; Stage names are the environment names, so this is known before the Stages land in step 9). A failed apply may still have landed earlier resources — apply is upsert, so fix what the error names and re-send the same call. Give the apps **no automated sync policy** — and **whether you sync them now depends on scope**. Pipeline in scope: do not sync anything; each environment's first deployment is its first promotion (step 10), so every version that reaches a cluster arrives through the pipeline, and an environment whose promotion the user never approves stays undeployed. Scope stops at milestone 4: run the platform endpoint's application sync tool once per app and confirm each reaches the pushed revision healthy. If the repo is private, Argo CD needs its own repository credential before it can read the repo at all — apps show comparison errors until it exists. That credential is the user's action (a repository-credential Secret with the token left as a placeholder and the `akuity argocd apply` command for their own shell — exact shape in `references/pipeline-facts.md` — or the repository settings in the instance UI); hand it to them, verify by outcome, and don't stall unrelated work on it.749. **Create the complete Stage topology.** Apply one chained Stage for **every environment named in round one**, regardless of how far this release will go: the first takes Freight directly from the Warehouse and each downstream Stage takes it from the Stage before it. The release plan controls which promotions execute, not which pipeline resources exist. Carry all Stages in the same platform Kargo apply's list argument, every one with `metadata.namespace: <project name>` and promotion steps that update that environment's YAML in git and sync its app (`references/pipeline-facts.md` has the working shape). This completes the wired pipeline even when the user chose no promotion today.7510. **Execute the approved multi-Freight plan — and this is the moment the git credential is needed.** Promotion steps clone the repo and push commits, so before the first promotion the Project needs a git credential with read access when the repo is private and push access in every case — the user's action in their own shell (labeled Secret via `akuity kargo apply`, or the instance UI; exact command with a placeholder in `references/pipeline-facts.md`). If they chose not to promote today, stop here cleanly: everything built so far stands, and the closing checklist names what promotion will need. For each approved hop, in order: **re-read that Freight for the target Stage first** (the promote tool's own contract — Freight eligibility is per-Stage), then promote, then confirm three things before the next hop: the Promotion succeeded, the environment's Argo CD app is synced and healthy — in pipeline scope this is that environment's first deployment, and a Promotion may find nothing to change when the scaffold already carries that hop's tag; the sync it drives is still the point — and the same Freight shows `verifiedIn` for that Stage, which the downstream Stage requires. **Before any environment the user named as production, stop and confirm explicitly one more time**, even though the plan was approved — name the Freight, the version, and the target.7611. **Wire incident response** (if chosen — and worth offering once the apps are deployed, even to a user who stopped before promotion). Akuity agents and their triggers live in the Argo CD instance spec. **In Terraform mode, update the instance's Terraform configuration as described under "Terraform mode" below.** In direct-apply mode they are applied through the same platform endpoint, and that apply is a JSON merge patch: nested objects merge field by field, but **lists are replaced whole** — `incidents.triggers` and `runbooks` included — and no MCP read returns the instance's full manifest (the list reads are compact). So on an instance this flow just created, a partial spec carrying only the additions is safe; on a pre-existing instance that may already have triggers or runbooks, do not guess — have the user export the current manifest in their shell, filtered to the one field so nothing else leaves it — `akuity argocd export --organization-id <org> <instance name> | yq 'select(.kind == "ArgoCD") | .spec.instanceSpec.kubeVisionConfig.aiConfig'` (the raw export is unredacted: OIDC client secrets, password hashes) — and hand you only that `aiConfig` block to carry forward, or add the trigger themselves in the portal (instance settings, Akuity Intelligence, Incidents tab). Set `spec.instanceSpec.akuityIntelligenceExtension.enabled: true`, and add one entry per scope under `spec.instanceSpec.kubeVisionConfig.aiConfig.incidents.triggers`, each a selector of `argocdApplications`, `k8sNamespaces`, `clusters`, and `degradedFor` (how long the object must stay degraded before the incident is created). **A trigger with no `clusters` entry never fires** — always name at least the clusters from milestone 2. The apply's success is the only MCP-side signal — no read returns the triggers — so confirm in the portal's Incidents tab or by a trigger firing. In direct-apply mode, the same config is editable later in the portal under the instance's Akuity Intelligence settings (Incidents tab). Once a trigger fires, the incident is investigated by Akuity's On-call Agent — working with it is the `akuity:delegate` skill's job, not this one's. If the extension is unavailable to the organization, that is plan gating — the organization talks to Akuity; there is no configuration path around it.7712. **Read back** what you built and show them, from platform-endpoint reads alone: instances, clusters, agent, apps, pipeline, and promotion history (incident triggers are not readable over MCP — point at the portal).7879If a step misbehaves — a Warehouse that never produces Freight, a Promotion that fails at clone or push — check `references/troubleshooting.md` before retrying anything; most of these failures are silent misconfigurations with exact fixes, not transient errors.8081## GitOps mode (optional)8283The default flow direct-applies the Applications and the Kargo pipeline, which leaves the repo holding only the deployment YAMLs. If the user chose GitOps at scope time, the control resources live in the repo instead and Argo CD syncs them. Round one also settled **which layout**: the two-phase bootstrap (the default), the akp-platform quickstart, or their existing one. Instances, clusters, credentials, round two, and promotion approval are identical in every layout; only the steps below change, and only the chosen layout's subsection applies.8485**Shared by every layout**8687- **Register the Kargo control plane as an Argo CD destination — once, and only if the repo's control Applications target it.** The two-phase and akp-platform layouts sync Kargo resources through an Argo CD Application whose destination is the Kargo control plane, conventionally named `kargo` (akp-platform's `personalize.sh` asks for the name; match whatever the repo's manifests use). An existing repo that already targets it under any name needs nothing, and mixed mode (Kargo resources direct-applied) needs nothing. Shape in `../../references/manifest-kinds.md`: a `Cluster` with `spec.data.size: small` and `spec.data.directClusterSpec`. The Kargo id exists only after step 4, so this lands as an instance update once the Kargo instance is healthy. **In Terraform mode** it is an `akp_cluster` with `spec.data.direct_cluster_spec` and `cluster_type = "kargo"` (stack `02-kargo` in the reference layout); read the pinned provider's schema for the exact attributes, then plan and hand over as for the other stacks. A Kargo instance can be registered on one Argo CD instance only — a second attempt fails with `kargo instance is already registered with another argocd instance as a target cluster`. The cluster list read does not echo `directClusterSpec` — verify by outcome: the Application targeting it reaches Synced.88- **Credential Secrets never enter git**; they stay a user-shell action exactly as in `references/pipeline-facts.md`, one per Kargo Project.89- **After bootstrap, git is the write path.** Changing or removing a GitOps'd Application or Kargo resource means a commit, not an MCP apply or delete — an MCP write would fight the bootstrap app's sync and be pruned or reverted. The MCP tools stay the read, verify, and promote surface.9091**Layout: two-phase bootstrap (default)**9293The layout of Akuity's demo repo (github.com/akuity/akp-demo, `akp-demo/bootstrap`): `bootstrap/argocd/` holds the Applications, `bootstrap/kargo/` holds the Kargo resources.9495- **Bootstrap the control resources before choosing versions.** At step 5, `bootstrap/kargo/` holds only the Project and Warehouse, while `bootstrap/argocd/` holds one bootstrap Application whose destination is the Kargo control plane (`kargo`), source path is `bootstrap/kargo/`, and sync policy is automated with prune. After round two, the step-7 commit adds the environment directories pinned to their approved Stage versions, step 8 adds the per-environment Application manifests (`authorized-stage` annotations included, no automated sync), and step 9 adds the complete Stage chain.96- **Steps 5 and 9's Kargo applies become commits and syncs**: apply only the contents of `bootstrap/argocd/` through the platform apply — the bootstrap Application first, then the per-environment Applications after the Stage-to-version plan — and the Project, Warehouse, and later the complete Stage chain arrive by sync from git. (For everything-in-git, wrap `bootstrap/argocd/` itself in one more app-of-apps Application and direct-apply only that.) Credentials, artifact discovery, round two, and promotion verification are unchanged.9798**Layout: akp-platform quickstart (pipeline scope only)** — read `references/akp-platform.md` once this layout is chosen. In short: a fork of github.com/akuity/akp-platform (root app-of-apps, discovery ApplicationSets over `apps/<name>/argocd/` and `apps/<name>/kargo/`, four sample promotion patterns); two phases — control files plus the `platform-aoa` apply before round two so the Warehouse exists, then manifests, appset, Stages, and pinned `env/<stage>` after the plan; needs `spec.kargoInstanceSpec.defaultShardAgent` (the repo carries no `spec.shard`) and one git credential per Kargo Project; offered only with a pipeline in scope because the rendered-branch samples have no source until promoted.99100**Layout: existing repo**101102- Preserve what is there. Read their tree first and map it: where Argo CD control resources live (an app-of-apps, or a directory one Application syncs), where Kargo resources live, where per-environment manifests live. Apply only what serves as the root today — their existing bootstrap Application, or one new Application pointing at the directory that holds the control resources — and land the Project and Warehouse (step 5), the Applications (step 8), and the Stages (step 9) as commits into their existing places, in the same two phases as the default layout above. If the layout has no home for Kargo resources, say so and direct-apply those while the Applications stay GitOps'd — a mixed mode is fine when it is explicit. Never restructure a repo to fit a template they did not choose.103104## Terraform mode (optional)105106The default flow creates the platform layer — instances, cluster registrations, agents — through the apply tools, so it exists only on the platform. If the user chose Terraform at scope time, that layer lives in a Terraform repository with the `akuity/akp` provider, laid out like Akuity's own github.com/akuity/akp-infra (`01-argocd`, `02-kargo`, `03-clusters`), and the user or their CI runs `terraform apply`. It is independent of the config-layer choice: Terraform with direct apply, or Terraform with GitOps mode (which is exactly akp-infra plus akp-platform). **Read `references/terraform-mode.md` before writing any Terraform** — it carries the layout, the source of every value the provider schema leaves open, the attributes that must be explicit, the import loop, and what the agent runs versus what only the user runs. The flow above still holds; these are the deltas:107108- **You write, validate, and plan; the user applies.** For each stack: write the files in their clone (start from akp-infra's stack, not a blank page, keeping only the choices `terraform-mode.md` marks as this flow's defaults), run `terraform init`, `terraform validate`, and — once their API key is exported in the shell — `terraform plan`, show the plan, and hand over. `terraform apply`, `destroy`, and `import` are theirs. Then verify with the platform read tools exactly as steps 2–4 describe; an apply finishing is not the health signal.109- **Every attribute comes from the installed provider's schema, every open value from its one source.** Pin one exact provider version, read `terraform providers schema -json` before each resource block, and never guess a name or nesting; a validate or plan failure gets one schema-backed correction, and two with no new information is a stop. The instance `version` is required by the provider — the user names it in round one; offer the list from `akuity argocd instance versions` / `akuity kargo instance versions` if they want help, and never fill it from an example, a template, or `latest`.110- **Step 1 becomes stack `01-argocd`** (one `akp_instance`); cluster registrations do not ride in it — they are stack 03. **Step 4 becomes stack `02-kargo`**: `akp_kargo_instance` plus one Akuity-managed `akp_kargo_agent` (`akuity_managed = true`, `remote_argocd` = the Argo CD instance id from a `data "akp_instance"` lookup by name), applied only after the Argo CD instance reads healthy. akp-infra's self-hosted per-cluster agents are an option the user chooses, not the default. **Step 3 becomes stack `03-clusters`**: one `akp_cluster` per cluster from round one, with the explicit attributes `terraform-mode.md` lists; with `kube_config` set from their kubeconfig path and context plus `ensure_healthy = true`, Terraform installs the agent and the apply blocks until it is healthy; without `kube_config`, the registration lands and the agent is installed with the CLI as in step 3.111- **Step 11 updates `akp_instance` in the Terraform repository** (`01-argocd` in the reference layout). Read the current instance and Terraform configuration, preserve existing AI settings and triggers, and add the requested incident scopes using the pinned provider's schema. Plan and hand over as for the other stacks. Then read the instance back to verify the extension and triggers. Later changes to these settings follow the same path.112- **Instance logins can be declared in Terraform if the user asked for it in round one**: the admin account and a bcrypt-hashed password from a `TF_VAR_admin_password` variable they export themselves, with `ignore_changes` on the secret — shape in `terraform-mode.md`. The password never enters the chat or a command line. Otherwise the login stays the portal action of step 4 and `references/instance-access.md`.113- **MCP access on Terraform-created instances.** Instances the apply tools create get it automatically; Terraform-created ones get it only when the configuration says so. Let the pinned provider's schema decide: when `akp_instance` and `akp_kargo_instance` carry `mcp_server`, set `mcp_server = { enabled = true }` in stacks 01 and 02 and access is on from creation, with Terraform owning the toggle (a portal switch-off shows as drift on the next plan). Provider 0.15.0 and earlier have no such attribute; there, **right after stack 02 applies, have the user enable both instances** under **Organization Settings → MCP Access → Endpoints → Instance access** — a later `terraform apply` does not turn it off. Either way, the lifecycle reads that verify milestones 1–3 work regardless, and every in-instance tool from step 5 on (applications, freight, promotions) is denied until it is on.114- **Existing instances and clusters are imported, not recreated.** Write the block to match the live object (read it with the lifecycle tools), take the import ID format from the pinned provider version's registry docs, prefer `import` blocks the user applies, and reconcile the plan to zero — a destroy/recreate in that plan is a stop, not something to apply.115- **After the first ap116117…(truncated)