Infrastructure & Deployment — Conceptual Deep Dive
Purpose
Agentweaver's AKS infrastructure is organized around deployment logic rather than manifest order. An equivalent deployment follows from understanding the responsibilities, boundaries, and operational trade-offs.
The deployment is built around five ideas:
- One public HTTPS entry point routes browser, API, OAuth, and MCP traffic by path.
- Four long-running application workloads run separately: API, worker, frontend/static host, and MCP server. API and worker share the API image.
- State is explicit: PostgreSQL Flexible Server holds all application state; the workspace volume is a shared multi-writer file share for worktrees and sandbox files.
- Identity replaces static cloud credentials: pods use Azure Workload Identity to read Key Vault secrets; API app secrets use CSI, while AgentHost user tokens are resolved on the API side and brokered to the sandbox in
/configure(the sandbox identity has no Key Vault access, issue #471). - Networking starts closed: default deny policies are opened only for the paths each component actually needs.
The deployment scripts default to agentweaver-rg, agentweaver-aks, agentweaverregistry, westus2, namespace agentweaver, and an image tag based on the short Git SHA unless IMAGE_TAG is supplied. KEYVAULT_NAME is required environment configuration and has no default.
Rebuild mental model
At a high level, Agentweaver is a private application stack behind a public Gateway:
The shared AKS component map is the single overview; this page does not keep a competing local copy. Its shared-owner refresh must reconcile the baseline worker count (two), actual secret consumers (API/worker, not MCP), and the absence of direct AgentHost vault access. Until then, use the current workload and identity details below rather than stale labels in that reference.
If rebuilding this from scratch, create the platform first, then identity and secrets, then images, then Kubernetes primitives in dependency order. The application deployments are deliberately last because they depend on identity, persistent volumes, routes, and secrets being ready.
Where this lives: scripts/azure, k8s.
AKS platform choices
Why AKS with app routing, Gateway API, and Istio?
Agentweaver needs public HTTPS, path-based routing, TLS certificate management, and clean separation between routing intent and individual services. Gateway API gives a Kubernetes-native model for that:
- A Gateway says “this namespace owns an HTTPS listener for this host”.
- HTTPRoutes say “these paths go to these services”.
- Services remain ordinary internal Kubernetes load-balancing points.
Cluster creation enables AKS app routing with the Istio variant, Gateway API, and the managed default domain. That means the cluster can provision the gateway implementation and certificate plumbing without hand-maintaining an ingress controller, public load balancer, and TLS cert chain separately.
The trade-off is platform coupling: this deployment assumes AKS app routing behavior, the approuting-istio GatewayClass, and the managed default-domain certificate resource. A rebuild on another Kubernetes distribution would need an equivalent GatewayClass and certificate issuer.
Why Azure CNI overlay, Cilium, and ACNS?
The network model uses both Kubernetes NetworkPolicy and Cilium FQDN-aware policies. Kubernetes NetworkPolicy is good at pod/namespace/IP/port rules, but it cannot express “allow api.github.com and Azure OpenAI domains by DNS name”. Cilium can.
That is why the cluster is created with Azure CNI overlay, the Cilium dataplane, and ACNS. Overlay networking avoids consuming a VNet IP for every pod, while Cilium provides the dataplane features needed for DNS-aware egress controls.
The manifests are not merely generic Kubernetes networking. However, the current Kata policy uses public-IP HTTPS exceptions, not an effective external-domain allowlist; Cilium FQDN capability does not make the broader additive rules narrower.
Why workload identity and Key Vault CSI?
Secrets are cloud-owned data, not Kubernetes manifest data. The desired flow is:
- Store secrets in Azure Key Vault.
- Grant a user-assigned managed identity permission to read those secrets.
- Federate the Kubernetes service account to that managed identity through the AKS OIDC issuer.
- Mount selected Key Vault secrets into pods through the Secrets Store CSI driver.
This avoids committing secrets, avoids long-lived Azure credentials inside containers, and lets Azure RBAC decide what the pod identity can read.
The trade-off is bootstrapping complexity. The service account annotation, pod label for workload identity injection, federated credential subject, Key Vault RBAC assignment, tenant ID, and CSI SecretProviderClass must all agree. If one link is wrong, the pod can start but fail to mount secrets or fail the application startup guard.
Why Kata VM isolation and agent-sandbox CRDs?
Agentweaver launches agent work in sandbox pods. Those pods run tools such as git, language runtimes, and package managers, so they are more exposed than the API/frontend/MCP pods. Kata VM isolation provides a stronger boundary than a normal Linux container runtime by putting each sandbox in a lightweight VM boundary.
The sandbox controller adds higher-level objects such as sandbox templates and warm pools. The template defines the shape of sandbox pods; the warm pool keeps a few ready so first-use latency is lower.
The trade-off is platform maturity and availability: the deploy script only applies sandbox resources when the CRDs are installed. A rebuild can run the core web/API/MCP stack without the sandbox CRDs, but agent execution that depends on Kubernetes sandboxes will not behave the same.
Where this lives: scripts/azure/steps/10-create-cluster.mjs, scripts/azure/steps/15-setup-identity.mjs, k8s/base/gateway.yaml, k8s/base/secret-provider-class.yaml, k8s/base/sandbox-template-agenthost.yaml, k8s/base/sandbox-warmpool-agenthost.yaml.
Workloads and their responsibilities
API workload
The API is the authoritative backend. It handles orchestration, project/workspace operations, authentication/OAuth authorization-server endpoints, memory/decision data, sandbox lifecycle calls, git worktree management, and durable run state. Its runtime image includes both libgit2 and the git CLI because normal headless operations use LibGit2Sharp while the collective Build & Test gate creates a detached integration-branch worktree through git worktree add --detach (apps/Agentweaver.Api/Git/WorktreeManager.cs:155, :546; apps/Agentweaver.Api/Dockerfile:58).
It runs as two replicas with a RollingUpdate strategy. Application state lives in Azure Database for PostgreSQL Flexible Server — multiple pods can write concurrently because status transitions use CAS-style UPDATE ... WHERE guards and run-level leasing prevents double-dispatch. The init container runs the EF migration bundle before the API container starts, ensuring the schema is current before serving traffic.
Worker workload
The worker deployment uses the API image without a public Gateway backend. Its baseline is two replicas; the HPA permits 2-3 replicas using CPU 70% and memory 80%, and its PDB keeps one replica available. Backlog-driven KEDA remains an alternative documented in comments, not the shipped autoscaler. Public and orchestration roles are logical responsibilities: background heartbeat pickup is independently enabled, not prohibited solely by App:Role.
Frontend workload
The frontend image contains two things:
- the React/Vite single-page app;
- the generated VitePress documentation site.
Both are served by a small ASP.NET Core static-file host. The frontend is safe to run with two replicas because it does not own writable application state. Runtime configuration is injected through a generated env-config.js, so the browser can call the API through the public /api path rather than a baked build-time URL.
Docs are built into the frontend: documentation is part of the frontend container image. Updating Markdown under docs does not update the deployed site until the frontend image is rebuilt and rolled out. Conversely, the frontend Docker build context must include docs; excluding it would produce an image without the published docs site.
MCP workload
The MCP server is a separate resource-server process. It exposes the MCP endpoint and validates tokens issued by the API's OAuth authorization server. It uses the internal API service for API calls and JWKS lookup, while its issuer and audience settings are pinned to the public host so token claims match what clients see externally.
This split keeps MCP protocol concerns out of the frontend and avoids making the API process also serve as the MCP resource server. The cost is that routing, identity, network policy, and OAuth metadata must all agree on which paths belong to the authorization server and which paths belong to the MCP resource server.
Sandbox workload
Sandbox pods are not normal always-on services. The live pod-per-run path claims pre-warmed AgentHost pods (agentweaver-agent-host, replicas: 2), then configures the bound pod with /configure before the first A2A turn. AgentHost runs as a dedicated, Key-Vault-less workload identity (issue #471); the run owner's token is brokered to it per-run by the API in /configure rather than fetched directly from Key Vault.
The API has narrow RBAC for creating and interacting with these sandbox resources. That is intentional: the API needs to create sandbox claims/pods and exec into them, but it should not be a broad cluster administrator.
Where this lives: k8s/base/api-deployment.yaml, k8s/base/frontend-deployment.yaml, k8s/base/mcp-deployment.yaml, k8s/base/rbac-api.yaml, apps/web/Dockerfile, apps/Agentweaver.Web/Program.cs.
Request routing logic
The public routing model is path-based. The Gateway terminates TLS once, then HTTPRoutes select the backend service.
The important design detail is specific routes before the catch-all. The frontend route matches /, so it is intentionally the fallback. More specific API and MCP routes must exist for protocol paths that should not be swallowed by the SPA host.
API routes
The API owns:
- REST/API calls under
/api; - GitHub auth callback and related browser auth paths under
/auth; - OpenAPI under
/openapi; - exact configured OAuth paths
/oauth/authorize,/oauth/token,/oauth/register,/oauth/resume,/oauth/revoke, and/oauth/jwks(not every/oauthpath); - authorization-server and OpenID discovery documents under
/.well-known/....
This is because the API is the OAuth issuer. Clients must discover authorization, token, registration, revocation, and JWKS endpoints from the same public issuer host that appears in token claims.
MCP routes
The MCP server owns:
- MCP traffic under
/mcp; - protected-resource metadata discovery paths;
- a public health convenience path that is rewritten to the MCP server's internal health endpoint.
The MCP server is the OAuth resource server. It validates tokens but does not mint them. For public metadata, clients need to discover the protected resource and then follow that metadata back to the API authorization server.
Frontend route
The frontend owns everything else. It serves static assets, the React SPA fallback, and the generated docs under /docs. Unknown non-doc application paths return the SPA shell so client-side routing can handle them. Unknown docs paths return 404 rather than the SPA shell, which keeps broken documentation links visible.
Where this lives: k8s/base/httproute-api.yaml, k8s/base/mcp-httproute.yaml, k8s/base/httproute-frontend.yaml, k8s/base/frontend-service.yaml, apps/Agentweaver.Web/Program.cs.
Secrets and workload identity
The secret path is deliberately indirect:
Separate authorization from secret delivery. API/worker startup reads CSI-mounted files, while the application also uses workload-identity-authenticated SecretClient/ISecretStore for runtime secret storage and OAuth certificate loading. The managed identity has Secrets User and Secrets Officer roles; this is not exclusively a file-consumer design.
The API and worker read the required API authentication key from the CSI-mounted mcp-api-key file. MCP mounts no secrets. API and worker have distinct federation subjects for agentweaver-api-identity; an MCP ServiceAccount annotation alone does not establish a configured federation or vault consumer. AgentHost uses the separate agentweaver-agenthost-identity with no Key Vault roles (issue #471). The static agentweaver-secrets SecretProviderClass serves API/worker secret mounts.
sandbox-warmpool-agenthost.yaml keeps two AgentHost pods pre-warmed in standby. At run launch, the API claims one and sends run-scoped provider, repository, preview, workspace, and turn-authentication data through /configure. The AgentHost identity has no Key Vault roles, so the pod does not read the vault directly. There are no per-run SecretProviderClasses, cloned templates, or per-run warm pools to clean up.
Rotation constraint: the CSI driver can refresh mounted API files on a polling interval, but these containers export the file contents into environment variables during startup. Environment variables do not update when the file changes. Plan to restart pods after secret rotation unless the application is changed to re-read mounted files for the specific secret.
API-key constraint: mcp-api-key remains a required first-deploy prerequisite. Run npm run azure:provision-infra before the first npm run azure:deploy-from-local; without the CSI-delivered key, API authentication and worker loopback calls cannot operate and diagnostics report key_vault: critical: secret 'mcp-api-key' not found.
Where this lives: scripts/azure/steps/15-setup-identity.mjs, k8s/base/serviceaccount-api.yaml, k8s/base/serviceaccount-agenthost.yaml, k8s/base/secret-provider-class.yaml, k8s/base/api-deployment.yaml, apps/Agentweaver.Api/Diagnostics/DiagnosticsService.cs.
Storage and persistence
Agentweaver separates storage by access pattern.
PostgreSQL: primary application state
All application state — runs, projects, backlog tasks, revisions, memory, decisions, OAuth state, and run events — is stored in Azure Database for PostgreSQL Flexible Server, provisioned by scripts/azure/steps/17-provision-postgres.mjs. The connection string is stored in the agentweaver-postgres Kubernetes Secret and injected as environment variables at pod startup. Use Azure's built-in automated backups and point-in-time restore for data protection.
Workspace PVC: shared worktrees and sandbox files
The workspace PVC is a 50Gi Azure Files Premium ReadWriteMany share mounted by API, worker and AgentHost. Detached shared worktrees must sit under the shared mount. Local execution modes use verified ephemeral checkouts and explicit writeback instead of executing directly on SMB.
The custom StorageClass exists because ownership matters. Containers run as uid/gid 1000 with locked-down filesystems. A default Azure Files mount can appear root-owned and ignore pod fsGroup, causing ordinary workspace writes to fail. The repo-owned StorageClass pins mount options so files are usable by the non-root containers.
StorageClass constraint: mount options are immutable. Do not patch a cluster-managed built-in class and hope existing PVCs change. Define the desired class, create/recreate the PVC as needed, and keep the storage behavior under version control.
Backups
Primary application state lives in Azure Database for PostgreSQL Flexible Server, with automated backups and point-in-time restore. Workspace files and Key Vault secrets are separate persistence domains and need their own protection. Do not apply old SQLite memory.db backup or RWO/Recreate advice to the current RollingUpdate API/worker deployments. The deploy list still contains a legacy 10Gi RWO data claim; that does not make it the live workspace mount.
Where this lives: k8s/base/pvc-workspace.yaml, k8s/base/storageclass-workspace.yaml, apps/Agentweaver.Api/Program.cs.
Network policy model
The network design starts with “nothing can talk unless there is a reason”. That is the safest default for a system that runs agent-controlled work.
Ingress
Selected application and AgentHost traffic is default-denied, with explicit service/control/preview exceptions. API ingress includes Gateway, MCP and AgentHost peers. The worker's stated API egress has no corresponding worker peer in the checked-in API ingress rules: this is a manifest coverage gap, not a live connectivity measurement.
This creates a clean public boundary:
- external clients enter through the Gateway;
- the Gateway reaches services through narrow pod-level allows;
- MCP-to-API is an explicit east-west exception, not an accidental side effect;
- AgentHost accepts API/worker control ingress on TCP 8088 and same-namespace preview-Gateway ingress on TCP 3000-9000. Since 8088 lies in that range, additive policies do not prove that only API/worker can reach the control listener. Authentication and configured mTLS remain separate protections.
Egress
Application pods are default-denied for egress and then granted:
- DNS to kube-dns;
- internal Agentweaver service traffic on the app port;
- external HTTPS where required;
- Cilium FQDN allows for GitHub, Azure AI/OpenAI/Cognitive Services/model endpoints, and telemetry.
AgentHost egress permits public-IP HTTPS with explicit private/link-local CIDR exclusions, DNS, and API/MCP exceptions. It is not an enforced domain allowlist; the IPv4 exclusions do not include 100.64.0.0/10. The template enables a service account token for the AgentHost platform container and leaves its root filesystem writable. The executor has a separate credential and child-mount boundary; do not attribute that narrower boundary to every container in the pod.
Operational constraints
- DNS must be allowed for FQDN policies to work; blocking DNS breaks name-based egress.
- FQDN allowlists depend on Cilium. Rebuilding on a non-Cilium dataplane requires a different egress-control strategy.
- The shipped public-IP HTTPS allowance is broader than the old FQDN-only prose; assess the actual union of policies, not isolated policy names or comments.
- Gateway pods are created by the app-routing implementation, so label/namespace assumptions must match the actual Gateway implementation.
Where this lives: k8s/base/networkpolicy-default-deny.yaml, k8s/base/networkpolicy-mcp.yaml, k8s/base/networkpolicy-sandbox.yaml, k8s/base/cilium-network-policy-sandbox.yaml, k8s/base/serviceentry-telemetry.yaml.
Build, retag, deploy, rollout logic
Deployment converges on desired image tags. API, frontend, MCP and AgentHost are the four image identities; worker reuses the API image. AGENTHOST_IMAGE_TAG defaults to IMAGE_TAG but may be overridden explicitly.
Why use a single image tag per release?
The four images are developed together. A common default tag simplifies rollout and rollback, but is not an invariant forbidding the AgentHost tag override.
Build changed images
When code changes affect a service, build that image and push it to ACR with the release tag. The build script uses ACR remote builds, so the operator does not need a local Docker daemon. API, frontend, MCP, and AgentHost use the repo root as their build context because their Dockerfiles depend on shared repository content.
AgentHost image builds have one non-obvious invariant: apps/Agentweaver.AgentHost/Dockerfile publishes with dotnet publish --runtime linux-x64 --self-contained false. The runtime identifier is required for GitHub.Copilot.SDK to place the native copilot binary at /app/runtimes/linux-x64/native/copilot. Without it, AgentHost pods start but crash with Copilot runtime not found at '/app/runtimes/linux-x64/native/copilot'.
For the API specifically, the image is more than the web host: it also carries the EF migration bundle used by the init container. That is why “build API” and “roll out API” are coupled to database migration behavior.
Retag unchanged images
Conceptually, unchanged services still need the release tag. The clean registry pattern is to retag/import the previous known-good image digest to the new release tag instead of rebuilding it. That keeps all deployment manifests on one tag while avoiding unnecessary builds.
Retag/import is implemented in 20-build-push-images.mjs using az acr import. The four image identities are API, frontend, MCP and AgentHost; worker uses the API image.
Render and apply manifests
Deployment renders manifests with environment-specific values: public host, ACR login server, image tag, workload identity client ID, Key Vault name, and tenant ID. Rendering keeps the source manifests reusable while still producing concrete Kubernetes objects for one environment.
Apply order matters:
- Namespace first.
- Default-domain certificate and host derivation.
- Service account, workload identity annotation, static SecretProviderClasses, RBAC, quotas, and PVCs.
- Network policies and egress allowlists.
- Services, runtime configuration, Gateway and HTTPRoutes.
- Sandbox template/warm pool if the CRDs exist.
- API/frontend/MCP deployments, then worker with HPA/PDB.
- Rollout waits and post-deploy verification.
This order prevents common race conditions: pods should not start before API secrets can mount, before volumes exist, before identity is annotated, or before the Gateway host is known. The static SecretProviderClass is reused; the server brokers per-run capability data through /configure. AgentHost never fetches user tokens directly from Key Vault.
Rollout and verification
Rollout waits confirm that Kubernetes accepted and started the API, frontend, and MCP deployments. Verification should then check route readiness, HTTP health, static SecretProviderClass status, RBAC assumptions, and sandbox CRD/resources where applicable.
The important distinction: rollout success means pods became ready; it does not prove all external protocol flows work. OAuth discovery, MCP metadata, JWKS validation, and docs routing each deserve smoke tests because they cross multiple components.
Where this lives: scripts/azure/variables.mjs, scripts/azure/steps/20-build-push-images.mjs, scripts/azure/steps/30-deploy.mjs, scripts/azure/steps/40-verify.mjs, .dockerignore.
Rebuild checklist
To stand up an equivalent deployment:
- Create an AKS cluster with Cilium/ACNS, app routing Istio, Gateway API, managed default domain, Key Vault CSI, OIDC issuer, workload identity, and ACR attachment.
- Install sandbox CRDs/controller if Kubernetes-backed agent sandboxes are required.
- Run
npm run azure:provision-infrato create Key Vault secrets, the user-assigned managed identity, and the requiredmcp-api-keybefore first deploy. - Federate the
agentweaver-apiservice account subject to that managed identity. - Build or retag API, frontend, MCP and AgentHost to their desired tags; worker shares the API image.
- Render manifests with the environment-specific host, ACR, tag, identity, Key Vault, and tenant values.
- Apply identity, CSI, RBAC, storage, network policies, services and routes before workloads.
- Deploy workloads and wait for rollouts.
- Smoke test browser routing, API health, OAuth discovery, MCP protected-resource metadata, MCP health, docs under
/docs, secret mounting, and sandbox creation. - Protect PostgreSQL, shared workspace files and vault secrets as separate persistence domains.
Common failure modes
- Frontend works but API calls fail: the catch-all frontend route is present, but API/MCP routes or route specificity are wrong.
- MCP initializes slowly or times out: the MCP pod may be unable to reach the API JWKS endpoint because the east-west network allow is missing.
- Pods fail to start after secret rotation: CSI files updated, but process environment variables did not; restart pods or change the app to re-read files.
- Workspace writes fail with permission errors: Azure Files mounted with root ownership or wrong mount options; use a uid/gid-aware StorageClass and recreate affected PVCs if needed.
- Docs changes are not visible: docs are baked into the frontend image; rebuild and roll out frontend.
- Cluster diagnostics report
key_vault: critical: secret 'mcp-api-key' not found: the required API authentication key is absent; runnpm run azure:provision-infra, thennpm run azure:deploy-from-local. - AgentHost pod crashes with missing Copilot runtime: rebuild the AgentHost image with the Dockerfile's
dotnet publish --runtime linux-x64 --self-contained falseso theGitHub.Copilot.SDKnative binary is copied to/app/runtimes/linux-x64/native/copilot. - Workspace mount fails: inspect RWX Azure Files mount options and permissions; current API/worker RollingUpdate does not use the old RWO/Recreate workspace model.
- Sandbox cannot reach package/model endpoints: Cilium FQDN policy or DNS allowance is missing, stale, or not supported by the cluster dataplane.
- OAuth clients reject tokens: issuer/audience/public host values must match exactly between API token minting, MCP validation, and public metadata.
Minimal source map
Use these paths for implementation details only after the concepts above are clear:
- Platform and pipeline:
scripts/azure. - Kubernetes objects:
k8s. - Frontend/docs image and static host:
apps/web/Dockerfile,apps/Agentweaver.Web. - API image/runtime:
apps/Agentweaver.Api. - MCP image/runtime:
apps/Agentweaver.Mcp. - AgentHost image/runtime:
apps/Agentweaver.AgentHost.
Diagram details and constraints
| Element | Contract |
|---|---|
| title | AKS separates control from execution |
| takeaway | Replicated API and workers share durable services; AgentHost pods execute isolated turns. |
| group-title0 | APPLICATION CONTROL |
| group-title1 | EXECUTION / DURABLE STATE |
| Application ingress | Application ingress |
| Application ingress | Frontend deployment |
| Application ingress | AKS App Routing Gateway |
| Application ingress | Frontend: 2 replicas |
| Application ingress | Preview gateway separate |
| API deployment | API deployment |
| API deployment | Request and run control |
| API deployment | 2 API replicas |
| API deployment | Postgres + CSI secrets |
| API deployment | Shared workspace mount |
| MCP deployment | MCP deployment |
| MCP deployment | Broker-authenticated tools |
| MCP deployment | 1 MCP replica |
| MCP deployment | Forwards requests to API |
| MCP deployment | No CSI secret mount |
| Worker deployment | Worker deployment |
| Worker deployment | Background orchestration |
| Worker deployment | 2 baseline replicas |
| Worker deployment | HPA scales from 2 to 3 |
| AgentHost pods | AgentHost pods |
| AgentHost pods | SandboxClaim warm pool |
| AgentHost pods | Per-run /configure |
| AgentHost pods | Kata-isolated agent turns |
| AgentHost pods | No ambient user secrets |
| Durable services | Durable services |
| Durable services | Postgres + Azure Files |
| Durable services | Run state / events in DB |
| Durable services | RWX project workspace |
| Durable services | Key Vault via API/worker CSI |
| relation-0 | 1 HTTPS |
| relation-1 | 2 API tools |
| relation-2 | 3 persist / mount |
| relation-3 | 4 persist / mount |
| relation-4 | 5 claim + dispatch |
| assurance | Application and preview Gateways are separate. AgentHost has no Key Vault-role identity or CSI secret mount. |
| assurance-0-label | Azure AKS environment |
| assurance-0-fact | GatewayClass: approuting-istio. |
| assurance-0-source | gateway.yaml |
| assurance-1-label | Manifest facts |
| assurance-1-fact | Worker HPA is CPU-based, 2–3. |
| assurance-1-source | worker-hpa.yaml |
| assurance-2-label | Distinct identities |
| assurance-2-fact | AgentHost has no Key Vault role. |
| assurance-2-source | serviceaccount-agenthost.yaml |
| n0 | AKS App Routing Gateway; Frontend: 2 replicas |
| n1 | 2 API replicas; Postgres + CSI secrets |
| n2 | 1 MCP replica; Forwards requests to API |
| n3 | 2 baseline replicas; HPA scales from 2 to 3 |
| n4 | Per-run /configure; Kata-isolated agent turns |
| n5 | Run state / events in DB; RWX project workspace |
| groups | APPLICATION CONTROL; EXECUTION / DURABLE STATE |
Diagram details and constraints
| Element | Contract |
|---|---|
| title | Identity authorizes; CSI delivers secrets |
| takeaway | API and worker consume vault secrets; AgentHost receives brokered configuration. |
| API / worker accounts | API / worker accounts |
| API / worker accounts | Distinct federation subjects |
| API / worker accounts | Kubernetes ServiceAccounts |
| Managed identity | Managed identity |
| Managed identity | OIDC federated credentials |
| Managed identity | Secrets User + Secrets Officer |
| Azure Key Vault | Azure Key Vault |
| Azure Key Vault | Secret storage and authorization |
| Azure Key Vault | No static Azure credential |
| Secrets Store CSI | Secrets Store CSI |
| Secrets Store CSI | Static SecretProviderClass |
| Secrets Store CSI | Mounted files + synced Secret |
| API / worker | API / worker |
| API / worker | Startup exports API key |
| API / worker | Also runtime SecretClient calls |
| Application secret store | Application secret store |
| Application secret store | Workload identity authentication |
| Application secret store | Not file-only consumers |
| MCP | MCP |
| MCP | No secret mounts |
| MCP | Annotation is not federation proof |
| Run configuration | Run configuration |
| Run configuration | Purpose-bound brokered payload |
| Run configuration | Provider / repo / turn / preview |
| AgentHost | AgentHost |
| AgentHost | Separate identity, no vault roles |
| AgentHost | No direct vault or CSI token fetch |
| arrow-1 | federate |
| arrow-2 | authorize |
| arrow-3 | secrets |
| arrow-4 | mount |
| arrow-5 | use |
| arrow-6 | read/write |
| arrow-7 | deliver |
| note-0 | Top row is authorization, not a secret-data flow. |
| note-1 | Key Vault supplies CSI and the application SecretClient path. |
| note-2 | MCP and AgentHost are explicitly not CSI secret consumers. |
| notes | Top row is authorization, not a secret-data flow.; Key Vault supplies CSI and the application SecretClient path.; MCP and AgentHost are explicitly not CSI secret consumers. |
Diagram details and constraints
| Element | Contract |
|---|---|
| title | Build or reuse, then converge deployment |
| takeaway | Four image identities converge before ordered prerequisites and workload rollout. |
| Desired images | Desired images |
| Desired images | API / frontend / MCP / AgentHost |
| Desired images | Worker reuses API image |
| Build or retag | Build or retag |
| Build or retag | Changed: build + push |
| Build or retag | Reusable: az acr import |
| Concrete manifests | Concrete manifests |
| Concrete manifests | Host / registry / identity / tags |
| Concrete manifests | AgentHost tag can override |
| Namespace + domain | Namespace + domain |
| Namespace + domain | Platform prerequisites |
| Namespace + domain | Before dependent resources |
| Identity and storage | Identity and storage |
| Identity and storage | SA / CSI / RBAC / quota / PVC |
| Identity and storage | Then network policy |
| Services and routing | Services and routing |
| Services and routing | Runtime config / Gateway / routes |
| Services and routing | No invented backup-job stage |
| AgentHost pool | AgentHost pool |
| AgentHost pool | Template then warm pool |
| AgentHost pool | Only when CRDs are available |
| Workload rollout | Workload rollout |
| Workload rollout | API / frontend / MCP / worker |
| Workload rollout | Worker HPA and PDB |
| Verify externally | Verify externally |
| Verify externally | Rollout then protocol checks |
| Verify externally | Ready pods are not full proof |
| arrow-1 | resolve |
| arrow-2 | render |
| arrow-3 | apply |
| arrow-6 | CRDs |
| arrow-8 | check |
| note-0 | Rows are successive deployment phases, not independent pipelines. |
| note-1 | Retag/import is implemented; it is not a future optimization. |
| note-2 | Desired tags may differ through the explicit AgentHost override. |
| notes | Rows are successive deployment phases, not independent pipelines.; Retag/import is implemented; it is not a future optimization.; Desired tags may differ through the explicit AgentHost override. |
Diagram details and constraints
| Element | Contract |
|---|---|
| title | Specific routes before frontend fallback |
| takeaway | Gateway TLS termination and HTTPRoute selection keep public backends explicit. |
| Public client | Public client |
| Public client | Browser / API / MCP |
| Public client | One HTTPS entry point |
| Gateway listener | Gateway listener |
| Gateway listener | Terminate TLS |
| Gateway listener | Gateway API routing |
| HTTPRoute match | HTTPRoute match |
| HTTPRoute match | Prefix and exact rules |
| HTTPRoute match | Not every /oauth path |
| API backend | API backend |
| API backend | /api /auth /openapi prefixes |
| API backend | Exact OAuth + AS/OIDC discovery |
| MCP backend | MCP backend |
| MCP backend | /mcp + protected discovery |
| MCP backend | /mcp/health rewrites /healthz |
| Frontend fallback | Frontend fallback |
| Frontend fallback | / catches remaining traffic |
| Frontend fallback | Service :80 -> pod :8080 |
| arrow-1 | HTTPS |
| arrow-2 | select |
| arrow-3 | API |
| arrow-4 | MCP |
| arrow-5 | fallback |
| note-0 | API and MCP Services use :8080; worker has no public route. |
| note-1 | Backend cards list mutually selected destinations, not a serial pipeline. |
| note-2 | Exact OAuth endpoints and discovery variants remain listed in the page. |
| notes | API and MCP Services use :8080; worker has no public route.; Backend cards list mutually selected destinations, not a serial pipeline.; Exact OAuth endpoints and discovery variants remain listed in the page. |
