initializdocs
Agents

CI-deployed agents

Deploy a pre-built agent image from your own CI pipeline — what "managed by CI" means in the console, network reachability and public exposure, owner attribution, and the claude-agent and strands runtimes' stateful, HTTP-invoked, and per-run observability behaviors.

Instead of letting the platform build an agent's image, you can build it in your own CI pipeline and deploy the finished image to a workspace with the initializ CLI. The platform never sees your repository or the image internals — your pipeline builds, the platform deploys.

See the CLI deploy reference for pipeline setup and the deploy command.

How a CI deploy works

Each deploy upserts by workspace + agent name: the first deploy creates the agent record, and every later deploy for the same name in the same workspace updates it and rolls the running deployment to the new image. This makes the deploy step idempotent — safe to re-run on every push to your release branch. The agent's stable runtime id is part of that identity: redeploying an agent you previously deleted reactivates the same agent record (its history keys stay intact) rather than creating a look-alike duplicate, and a deploy whose runtime agent id is already used by a different live agent in the workspace is rejected instead of silently colliding.

A few behaviors worth knowing:

  • Same-tag redeploys still roll the workload, so re-pushing a mutable tag (like latest) picks up the new image.
  • An image digest can be supplied to pin the exact image content regardless of tag.
  • The deploy carries metadata from your repository — declared skills, model, egress, channels — for display and policy purposes. The actual runtime behavior is whatever is baked into your image.
  • Metadata tags can be declared in the deploy spec (initializ-deploy.yaml, or per-deploy CLI flags) and are applied to the agent's runtime metadata. The deploy spec is the source of truth: each deploy reconciles the tag set wholesale, so removing a tag from the spec removes it from the agent. The reserved created-by and workspace-id tags are always injected by the platform and can't be set from the spec.
  • Raw annotations work alongside tags for keys other tooling reads by exact name (a metrics scraper's prometheus.io/scrape, say): declared in the spec or per-deploy flags, applied verbatim with no namespacing, and reconciled wholesale like tags. Keys under the platform's and Kubernetes' reserved prefixes are rejected, so a raw annotation can never overwrite a platform-owned key. See raw pod annotations.
  • The agent's deployment shape follows the spec on every deploy: network reachability, persistent storage, setup steps, and the HTTP invoke declaration all reconcile from what the spec says — declared settings persist across redeploys, and removing one from the spec removes it from the agent on the next deploy.
  • The agent's Owner — shown in the console's identity view — can be named explicitly in the deploy spec (agent.owner, an email address), since a CI deploy has no interactive user. When it's unset the CLI falls back to the CI platform's author/actor variables, and failing that the platform attributes the agent to the identity that made the deploy call. A deploy that carries no owner never wipes one set earlier. See owner attribution.
  • CI deploys appear in the console with the same build status and progress logs as platform-built agents, and the agent shows up on the Agents list like any other.

What "managed by CI" means

A CI-deployed agent's configuration is owned by its repository, so the console locks everything that would be baked into the image:

  • Locked in the console: skills (including the skill builder and skill edits), model provider, channels, policies, guardrails, and platform-triggered rebuilds. Attempts are rejected — change these in the repo and deploy again from CI.
  • Hidden in the console: the Builds card's roll back and Download agent folder actions — a CI agent's folder lives in the repository its CI builds from, and previous images are restored by deploying again from CI.
  • Still open in the console: environment values and secret rotation. Rotating a credential patches the agent's secret and restarts it — no new CI run needed.

Everything else about operating the agent is unchanged: health and failure diagnostics, the Activity, Logs, and Usage tabs, Diagnose, chatting from the Overview tab, and participation in workflows.

Network reachability and public exposure

A deployed agent is reachable only inside the platform's cluster by default. The deploy spec's ingress.reachability widens that on request, in three scopes:

  • cluster — the default: only other workloads on the platform can call the agent.
  • private — the agent gets an endpoint on the organization's internal network (VPC/VPN reach, not the internet).
  • public — the agent gets an internet-facing endpoint.

Which of private/public are actually available — and the domain and scheme each maps to — is configured per platform environment by the operator; a deploy naming a mode the environment doesn't offer is rejected with the allowed list. The endpoint's hostname defaults to <agent>-<workspace>.<domain> and can be overridden in the spec.

When an A2A agent is exposed, its Agent Card advertises the exposed URL, so off-cluster callers (external orchestrators, partner systems) discover the right address from the card itself; a cluster-scoped agent's card advertises its internal address. Exposure never weakens inbound auth — bearer verification applies to A2A calls regardless of where they come from.

Reachability follows the spec on every deploy: dropping the ingress block (or setting reachability: cluster) withdraws a previously provisioned endpoint. See the ingress block reference for the full field list and fallback behavior.

The claude-agent runtime

Besides the default runtime, CI can deploy a claude-agent — an agent built on the Claude Agent SDK in your own repository, packaged by your CI into a governed image (initializ agent init scaffolds the project — see the CLI reference). Declare type: claude-agent in the deploy spec; the platform then deploys it with the same governance envelope as any other agent (audit events, runtime policy checks, environment secrets). A second governed runtime, strands, works the same way for AWS Strands agents. The runtime-specific behaviors:

  • Managed model access — the deploy spec names a model provider (anthropic or openai) and model; the platform injects the managed gateway endpoint and credential at deploy time, so the image carries no LLM credentials of its own.
  • Optional agent-to-agent exposure — the agent can be exposed to other agents and workflows over the A2A protocol. Inbound calls are bearer-authenticated by default: callers present a platform-issued token, verified against the platform, and only same-workspace callers are accepted. Authentication can be explicitly disabled (a2a.auth: none), and an unrecognized auth value is rejected at deploy rather than shipping an unreachable agent.
  • Like every CI-managed agent, its configuration is owned by the repository; environment and secret rotation stay open in the console.

Governed runtimes can also declare platform MCP connections in the deploy spec: each named server must already be connected on the workspace (unconnected declarations are dropped, fail-closed), and the agent's MCP tool calls run under the same policy checks and audit trail as every other governed tool call.

Strands agents

type: strands deploys an AWS Strands (Python) agent as a second governed runtime, governed exactly like a claude-agent: the same managed model gateway (the spec names anthropic or openai, the platform injects the endpoint and credential), the same optional A2A exposure with bearer authentication by default, the same audit and policy envelope, and the same stateful, HTTP-invoke, and MCP capabilities described in this section. The difference is inside the image — a Strands image is governed by the Python governance package your CI installs as a wheel, instead of the Node loader. See Govern a Strands agent for the developer side and the strands runtime reference for the deploy spec.

Stateful claude-agents

A claude-agent whose deploy spec declares storage volumes is deployed stateful: the platform provisions persistent storage for each replica and mounts it into the agent, so working state — repository clones, git worktrees, caches — survives restarts and redeploys instead of vanishing with the container filesystem. Declared setup steps (initContainers) run before the agent starts, with the agent's own image and environment and the volumes mounted — the typical pattern is cloning a repository into a volume the agent then works in. Removing the volumes from the spec reverts the agent to a stateless deployment on the next deploy. See the storage reference.

HTTP-invoked claude-agents

Not every agent speaks A2A. A claude-agent that serves a plain HTTP route of its own — a webhook receiver, a manual-trigger endpoint — declares it in the deploy spec's http block, and the platform treats the agent as HTTP-invoked (an agent is A2A or HTTP-invoked, never both). The console then shows the endpoint URL and path on the agent's Settings and renders an invoke form — typed fields when the spec carries an input schema, a raw JSON body otherwise.

When an HTTP-invoked agent is exposed beyond the cluster, the platform authenticates every call to the declared invoke path before it reaches the agent: callers present a platform-issued token, the platform verifies it (any valid token of the agent's organization is accepted — including an operator invoking from the console), and each verification lands in the agent's audit trail. Routes the agent serves besides the declared path — health checks, webhooks that carry their own signature verification — pass through untouched, so self-authenticating integrations keep working. See the HTTP invoke reference.

What the platform records for every run

A governed agent — claude-agent or strands — reports into the same observability surfaces as any platform-built agent, per run, not per process:

  • One timeline per run. Each A2A task (and each run of a long-running worker) appears as its own invocation timeline in the agent's Activity and the Security events view, rather than every run folding into one endless process-level stream. Lifecycle events — inbound auth (with the calling user's identity), session start, request, response, completion — bracket every run, including failed ones: a task that errors still closes its timeline with the failure recorded.
  • A populated executions list. Every task is pushed to the platform's session store, so the agent's execution list and per-run transcript in the console fill in just like a platform-built agent's.
  • End-to-end correlation. The A2A task id is handed to the skill handling the task and stamped on the run's audit events, so everything a task did — model calls, tool calls, the response — correlates under one id from the caller's request to the last event.
  • Accurate token accounting. Every model call's usage is recorded with full token detail, including cached input tokens — totals count cache reads and writes, not just the uncached delta — and each call is attributed to its model and provider, so the Usage tab buckets claude-agent inference correctly instead of showing a blank provider.
  • Model-id portability. An agent hard-coded to Bedrock-style Anthropic model ids runs unchanged against the platform's managed Anthropic gateway — the ids are translated automatically, so adopting the managed gateway needs no source change.
  • Optional payload capture, at parity across runtimes. By default audit events carry hashes and lengths of prompts and tool payloads, never content. Enabling the deploy spec's audit.capture attaches bounded raw prompts, completions, and tool arguments/results as evidence on the same events, rendered identically in the console for claude-agent, strands, and platform-built agents — and the console's capture indicator reflects the agent's real setting either way it was enabled.

On this page