The PromptPack Deploy Program
Omnia is a Kubernetes-native runtime, but pack authors work in
PromptArena — not kubectl. The deploy
program bridges the two: it lets a PromptPack author push a pack into an Omnia
workspace without hand-writing CRDs, using the promptarena-deploy-omnia deploy
adapter.
This page explains the moving parts — the deploy-profile export, the adapter config schema, and how a deployed pack becomes a running AgentRuntime. For the step-by-step walkthrough, see Deploy a PromptPack to Omnia.
The problem it solves
Section titled “The problem it solves”A pack on its own is inert. To run it in Omnia you need:
- an API endpoint and workspace to deploy into,
- the target workspace configured with a ready service group (the session-api / memory-api backend agents persist to),
- an API credential scoped to that workspace,
- one or more Providers to back the LLM calls, and
- optionally SkillSources for retrieval/tools.
Getting each of these names exactly right by hand is error-prone — a typo in a
Provider name fails the deploy at plan time, and referencing a Provider that
isn’t Ready fails it at runtime. The deploy-profile export exists to hand the
author a pre-filled, validated config block instead.
The deploy profile
Section titled “The deploy profile”The deploy profile is a discovery payload for a single workspace. The
dashboard serves it at GET /api/workspaces/{name}/deploy-profile. It is
discovery only — the endpoint never returns a secret. It contains:
api_endpoint— the dashboard’s external ingress URL, derived from the forwarded host (falling back toOMNIA_DASHBOARD_EXTERNAL_URL).workspace— the target workspace name.providers— the discovery menu of Providers.skills— the discovery menu of SkillSources.
Two filters shape that menu:
Ready-only. Only Providers and SkillSources whose status.phase is Ready
are listed. Non-Ready resources (Unavailable, Error, still syncing) are excluded
because a deployment that references one fails.
LLM-only providers. Only llm-role Providers are exported. Embedding, TTS,
STT, and image Providers are workspace-level services — consumed by memory-api
and similar subsystems — not per-agent extras. Bundling them into an agent’s
spec.providers breaks the pack at its first request, so the export drops them
(#1596). A Provider CRD with no explicit spec.role defaults to llm.
Default-LLM picker and the token
Section titled “Default-LLM picker and the token”The raw discovery payload lists real Provider names. Two things happen on top of it when an author exports:
- Default-LLM picker. The runtime requires exactly one primary LLM bound
under the alias
default. The export UI asks the author to pick one Provider and marks itname: defaultin the adapter config, withrefpointing at the real Provider CRD. - Workspace-scoped token. The profile itself carries no secret, so the
export mints an
omnia_sk_API token scoped to this workspace — it can deploy only here, and it acts with the author’s own role in the workspace. On re-export the dashboard offers to reuse the saved token or regenerate it (revoking the old key), so repeated exports don’t pile up duplicate keys. If the deployment uses a read-only API-key store, the token is left as a placeholder for the author to mint by hand.
Browser-login autoconfigure
Section titled “Browser-login autoconfigure”When the dashboard runs in OAuth mode, the CLI can mint the whole config through
a browser-login flow (the same shape as gcloud auth login) instead of
copy-paste. The Omnia-side contract is four endpoints:
GET /api/cli/authorize— the CLI’s loopbackcallback+stateare stashed; the browser is routed through OIDC login (if needed) to a workspace picker at/cli/select.POST /api/cli/grant— re-checks the author’s editor access, mints a one-time exchange code, and 303-redirects the browser back to the loopback callback. No token crosses the browser — only the code.POST /api/cli/token— the CLI exchanges the code on a back channel. This is the only place a token is issued: it mints a workspace-scoped, short-lived token (default TTL 1 hour,OMNIA_AUTH_CLI_TOKEN_TTL_SECONDS) and returns it together with the deploy profile.
These entry points are public so an unauthenticated CLI can start the flow
(#1593); token creation must be enabled for the exchange to succeed. The precise
CLI command that drives this lives in the promptarena deploy tooling, not in
Omnia.
The adapter config schema
Section titled “The adapter config schema”The export produces the config: block the promptarena-deploy-omnia adapter
consumes:
config: api_endpoint: https://omnia.example.com # dashboard external URL workspace: team-acme # target workspace api_token: omnia_sk_... # workspace-scoped, show-once providers: - { name: default, ref: claude-sonnet, role: llm } skills: - docs-search| Key | Meaning |
|---|---|
api_endpoint |
Dashboard ingress the adapter POSTs to |
workspace |
Workspace name; the server resolves the namespace from the Workspace CR |
api_token |
omnia_sk_ bearer credential, workspace-scoped |
providers[] |
Provider bindings: name is the in-pack alias, ref is the real Provider CRD, role is the Provider role. Exactly one must be aliased default |
skills[] |
SkillSource names to attach |
The providers[] and skills[] names must match resources that actually exist
and are Ready in the workspace — which is exactly what the discovery menu
guarantees when you export rather than hand-write.
From profile to AgentRuntime
Section titled “From profile to AgentRuntime”The adapter uses the token to call the workspace REST API and create the Kubernetes resources a running agent needs:
- a PromptPack (and its backing ConfigMap) holding the compiled pack — see the PromptPack reference;
- an AgentRuntime that references the PromptPack, binds the selected
Providers under
spec.providers(with thedefault-aliased LLM as primary), and attaches the chosen skills.
The AgentRuntime exposes the runtime through
spec.facades[] — a list of facade entries, each
serving one protocol. A pack deployed for browser chat lands as a single
websocket facade on port 8080 (the default); an agent can expose more
surfaces (for example an additional a2a entry) by listing multiple facade
entries. The operator then reconciles the AgentRuntime into a Deployment +
Service, and the pack is live.
The exact translation from adapter config to CRD fields lives in the external
promptarena-deploy-omnia adapter; Omnia’s side is the discovery profile it
exports and the workspace REST API the adapter writes through.
That workspace REST API — served by the dashboard at
POST /api/workspaces/{name}/agents (and the matching PromptPack routes) — is a
verbatim passthrough. It takes the AgentRuntime body the adapter sends and
applies it to the Kubernetes API unchanged: no field translation, no
schema-version adaptation, no server-side defaulting of the spec. The only
validation is the AgentRuntime CRD’s own OpenAPI/CEL schema, enforced by the
apiserver. This keeps the platform decoupled from any one pack format — but it
means the adapter, not Omnia, owns the AgentRuntime schema it emits.
Schema-version contract and upgrades
Section titled “Schema-version contract and upgrades”Because the deploy path is a passthrough and the adapter lives in a separate repo on its own release train, no single component owns the AgentRuntime schema contract at this boundary. The adapter must emit the schema that matches the AgentRuntime CRD + operator version installed in the target cluster. When they drift, the failure mode is asymmetric and easy to misread:
- Adapter behind the cluster (adapter emits an older shape the installed CRD
still accepts, but a newer operator can’t reconcile): the deploy succeeds
(
201 Created) but the agent never comes up — the AgentRuntime sits with an emptystatusand no pods, and the only evidence is a repeatingReconciler errorin the operator log. Nothing fails at deploy time, so this looks like a pack or cluster problem when it is really a version skew. - Cluster ahead of the adapter (CRD already upgraded, adapter still old): the
deploy fails immediately with the apiserver’s validation error (e.g.
422 spec.facades: Required value), surfaced straight back to the adapter. This is the loud, attributable failure — much easier to diagnose than the first case.
Two rules follow:
-
Ship breaking CRD changes in lockstep. A breaking AgentRuntime field change (for example the
spec.facade→spec.facades[]cutover) must land in the in-app deploy wizard and the externalpromptarena-deploy-omniaadapter together with the operator/CRD release — otherwise every adapter-deployed agent silently stops reconciling on upgrade. -
Upgrade the CRDs explicitly.
helm upgradedoes not upgrade CRDs — Helm installs the contents ofcharts/omnia/crds/only on first install and never touches them again. After upgrading the operator you must apply the new CRDs yourself (server-side, because they exceed the client-side apply annotation limit):Terminal window kubectl apply --server-side --force-conflicts -f charts/omnia/crds/Skipping this leaves a new operator binary reconciling objects against an old CRD schema — the exact “created but never reconciles” trap above.
Related
Section titled “Related”- Deploy a PromptPack to Omnia — the walkthrough.
- PromptPack reference — the resource the deploy creates.
- AgentRuntime reference —
spec.facades[]and provider binding.