# Ask AI and machine-readable docs (https://docs.initializ.ai/docs/ask-ai)
These docs are built to be read by AI as well as by people.
## The Ask AI assistant [#the-ask-ai-assistant]
The **Ask AI** button on any docs page opens an assistant that answers
questions about the platform. It answers **only from these docs**: every
answer is grounded in retrieved doc sections and cites its sources with
links that jump to the exact section. If the docs don't cover a question,
it says so and suggests the closest pages instead of guessing.
Ask AI may be disabled in some deployments. When the docs index is
temporarily unavailable, the assistant declines to answer rather than
answering without sources.
## MCP endpoint for AI clients [#mcp-endpoint-for-ai-clients]
The docs expose a read-only [MCP](https://modelcontextprotocol.io) server
over Streamable HTTP at `/api/mcp`, so AI tools can search these docs with
the same retrieval the Ask AI assistant uses.
Add it to Claude Code:
```bash
claude mcp add --transport http initializ-docs https://docs.initializ.ai/api/mcp
```
Available tools:
| Tool | What it does |
| -------------- | ------------------------------------------------------------------------------------- |
| `search_docs` | Semantic search; returns ranked sections with a `url` that links to the exact heading |
| `get_doc_page` | Returns the full markdown of one page by its `/docs/...` path |
## Markdown and index surfaces [#markdown-and-index-surfaces]
* Append `.md` to any page URL to get its raw markdown (for example
`/docs/cli.md`).
* [`/llms.txt`](/llms.txt) — a curated index of every page with a one-line
description, grouped by section.
* [`/llms-full.txt`](/llms-full.txt) — the full content of all pages in one
document.
* Every page header has **Copy Markdown** and **Open in** actions for
ChatGPT, Claude, and other tools.
# Overview (https://docs.initializ.ai/docs)
The initializ AI Platform (AIP) is an agent-centric platform for building,
deploying, and governing AI agents and multi-agent workflows in your own
environment.
## Where to start [#where-to-start]
## Platform areas [#platform-areas]
# Building and deploying (https://docs.initializ.ai/docs/agents/building-and-deploying)
When you create an agent (or apply a skill edit), the platform builds a
container image for it and deploys it into your workspace. You don't run
anything yourself — the console shows the whole process live.
## Build progress [#build-progress]
Right after create, the screen switches to a progress view that polls the
build and streams its logs:
| Phase | Meaning |
| ---------------------- | -------------------------------------------------------- |
| Building | The agent image is being generated and built. |
| Deployed / Starting up | The image was deployed; the agent is starting. |
| Running | The agent is up and healthy — terminal success state. |
| Degraded | The agent deployed but is not fully healthy. |
| Failed | The build or deployment failed — terminal failure state. |
The log panel pins to the newest line as the build streams. If a build runs
unusually long, the view notes it is *still deploying* — you can leave and
check back from the agent's detail page, which refreshes live while the
agent is settling.
From the terminal states you can jump to the agent, create another, or (on
failure) go back and adjust the configuration before retrying.
## Health states [#health-states]
Every agent shows a status chip on the Agents list and its detail page:
**running**, **deployed**, **degraded**, or **failed** (plus in-progress
states while building). Health is read live from the running deployment,
not from a stored snapshot, so the chip reflects what is actually
happening right now.
## Failure diagnostics [#failure-diagnostics]
When an agent is degraded or failed, the detail page shows an actionable
callout — not just a status chip:
* **Runtime failures** include per-container diagnostics: image pull
errors, crash loops with the last exit reason, and unschedulable pods.
* **Build-stage failures** have no running containers to inspect, so the
callout falls back to the stored build error explaining which step
failed.
The same diagnostics appear as marked lines in the create screen's log
stream, so a failure is visible without leaving the create flow.
## Diagnose [#diagnose]
The **Diagnose** button on the agent detail page gathers the agent's
evidence in one click — live health, the build error, recent audit events,
and a log tail — and returns a diagnosis with a probable cause, suggested
remediation, and citations. Every citation resolves to the same data shown
in the Activity and Logs tabs, so nothing is claimed that you can't verify
yourself. Diagnose is prominent when a failure callout is showing, and
still available when health is green — behavior problems like policy
denials or wrong outputs exist without any infrastructure failure.
## Observing a running agent [#observing-a-running-agent]
The agent detail page has tabs for day-to-day operation:
* **Overview** — chat with the agent directly and browse its sessions.
* **Activity** — the agent's runtime audit event stream, grouped by run,
with an in-place event drawer. Retained even after an agent is deleted.
* **Logs** — a bounded raw tail of the agent container for the cases
events can't explain (stack traces, print debugging). Choose the tail
size, refresh on demand, search with match highlighting, and read the
**previous instance** to see the output of a container that crashed and
restarted.
* **Usage** — the agent's model and token usage.
* **Settings** — egress, skill editing, environment variables, and
deletion. See [Secrets and environment](/docs/agents/secrets-and-environment).
## Rebuilds and restarts [#rebuilds-and-restarts]
Two different update paths, with very different costs:
* **Skill or egress changes** rebuild the agent image and redeploy it —
this takes a few minutes and goes through the same progress view as the
first build.
* **Environment value changes** patch the agent's secret and restart it —
no rebuild, effective in seconds.
# Channels and providers (https://docs.initializ.ai/docs/agents/channels-and-providers)
## Channels [#channels]
Channels are how an agent is reached once it's running.
Every platform-built agent exposes an **HTTP agent endpoint** inside your
workspace. This is the channel the platform itself uses: the console's
Overview tab chats with the agent through it, and
[workflows](/docs/workflows) dispatch steps to it. There is nothing to
configure — the endpoint, its authentication, and its registration for
workflow use are managed for you.
Optionally, an agent can also have a **Slack channel**: people talk to the
agent in Slack, and tool-approval prompts are delivered there too. Enable
it on the create (or skill-edit finalize) screen and provide:
* an **app token** (`xapp-…`) and a **bot token** (`xoxb-…`) — use a
dedicated Slack app per agent; don't reuse an app or bot token across
agents, and invite the bot to every Slack channel it should work in;
* optionally, a list of **allowed bot IDs** if other bots should be able
to talk to the agent.
Both tokens are handled as secrets: vaulted at deploy, masked in the
console, and never readable back. When editing, leaving a token blank
keeps the stored value.
For agents deployed from CI, channels are declared in the repository and
baked into the image — the console shows them but doesn't edit them. See
[CI-deployed agents](/docs/agents/ci-deployed-agents).
## Model providers [#model-providers]
Each agent has its own model provider and model, chosen on the create
screen from the set your platform offers — for example an OpenAI-compatible
provider or Anthropic, each with a curated model list. Platform
administrators control which providers and models appear.
Model access is fully managed:
* Requests run through the platform's **managed gateway** — you never
enter provider API keys or base URLs, and actual model credentials never
reach the console or your browser.
* The gateway endpoint and authentication are shown read-only in the
*Managed by the platform* panel on the create screen.
The provider and model are picked at create time; editing an agent's skill
later doesn't change its model. The agent's current model is shown on its
detail page and on the Agents list.
# CI-deployed agents (https://docs.initializ.ai/docs/agents/ci-deployed-agents)
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](/docs/cli/deploy) for pipeline setup and the
deploy command.
## How a CI deploy works [#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.
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.
* 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 [#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.
* **Still open in the console**: environment values and
[secret rotation](/docs/agents/secrets-and-environment). 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](/docs/workflows).
# Creating an agent (https://docs.initializ.ai/docs/agents/creating-an-agent)
Agents are created from **Build → Agents → New agent** in the console. The
create flow has two steps: choose (or generate) the agent's skill, then
configure the agent around it.
Agent creation is scoped to the currently selected workspace. If your
organization has no workspace yet, the console walks you through creating
one first.
## Step 1 — choose how the agent starts [#step-1--choose-how-the-agent-starts]
The entry screen offers two paths:
* **Describe the agent** — type what the agent should do in plain English
(for example, *"Watch our status page every 5 minutes and post to
\#incidents when a service goes down"*) and click **Generate skill**. This
opens the conversational skill builder, which drafts a skill — including
instructions and any scripts — that you refine in a chat before moving
on. See [Skills](/docs/agents/skills) for the full builder flow. This
path is available when your platform's builder service is configured;
otherwise it shows as *coming soon*.
* **Start from a skill** — pick a tile from the skill catalog. Skills are
grouped by category (developer, SRE, research, utilities, and so on) and
searchable; each tile shows its description, how many variables it needs,
and any extra egress it declares.
Either way you land on the same configure screen, prefilled from the
skill's declared schema.
## Step 2 — configure the agent [#step-2--configure-the-agent]
The configure screen collects everything the agent needs before its first
build:
* **Agent name** — how the agent is referenced across the platform,
including in workflows.
* **Model** — a provider and model, picked from the set your platform
offers. Requests run through the managed gateway, so there are no API
keys or URLs to enter. See
[Channels and providers](/docs/agents/channels-and-providers).
* **Environment variables** — values the skill needs at runtime. Variables
flagged as secrets are masked and vaulted; required variables must be
filled before you can create. You can add extra variables beyond what
the skill declares.
* **Additional egress** — domains the agent may reach beyond the
platform-managed base set. Hosts required by any governed tools you
select are added automatically and shown read-only.
* **Tools** — governed tool dependencies from your organization's tool
registry. Selecting a tool that requires a token adds a corresponding
secret variable to fill in.
* **Trigger** — whether the agent is **human-triggered** or **scheduled /
autonomous**. An autonomous agent has no requesting person, which
changes how its tools are allowed to act.
* **Slack channel** — optionally let people talk to the agent in Slack and
receive tool-approval prompts there. This needs a dedicated Slack app
per agent (an app token and a bot token).
* **Observability** — two toggles, both off by default: **capture audit
payloads** (record redacted tool and model inputs/outputs in audit
events) and **context compression** (reversibly compress bulky tool
outputs to save context).
A read-only **Managed by the platform** panel alongside the form shows what
you never have to configure: the model endpoint, authentication, and the
pre-approved base egress domains.
## Create and watch the build [#create-and-watch-the-build]
Click **Create agent**. The build and deployment start immediately and the
screen switches to a live progress view with streaming logs — see
[Building and deploying](/docs/agents/building-and-deploying) for the
phases, health states, and what to do if something fails.
# External agents (https://docs.initializ.ai/docs/agents/external-agents)
Agents that run entirely outside the platform can still be first-class
participants in it. Registering an external agent by URL puts it on the
Agents list and makes it available to [workflows](/docs/workflows), with
the platform attaching the right credential on every call.
Registration is card-driven: the platform fetches the agent's **A2A agent
card** and uses what the card declares — name, description, skills, and
authentication requirements — instead of asking you to describe the agent
by hand.
## Registering an agent [#registering-an-agent]
From **Build → Agents → Register A2A agent**:
1. **Enter the agent's URL** — its base URL (the card is read from
`/.well-known/agent-card.json`) or a direct link to the card file —
and click **Fetch card**. The console previews the card: name,
description, version, and declared skills. If the card itself is
protected, configure the credential first and fetch again.
2. **Configure authentication.** The card's declared security schemes are
rendered as the credential form:
* **API key** — collected and sent under the header name and location
the scheme declares.
* **HTTP bearer / HTTP basic** — a token, or a username and password.
* **OAuth 2.0 / OpenID Connect** — the platform doesn't execute these
flows; provide a pre-issued access token, sent as a bearer token.
* **Mutual TLS** and other schemes are not supported for platform
dispatch.
If the card declares no schemes you can configure a credential
manually, and you can always register with **no credential** — though
if the card declares auth, unauthenticated calls will likely fail.
3. **Register.** The credential is sent server-side only and sealed by the
platform — it is attached to every call made to the agent, but is
**never readable back**; the console only ever shows the credential
*type* (and header name for API keys), never the value.
## After registration [#after-registration]
Registered external agents appear in their own **External agents** section
on the Agents list, showing the endpoint URL, the configured auth type,
and the registration date. From there they can be deregistered.
In the workflow builder, external agents appear in the agent picker
alongside platform-built agents and are dispatched by their card name,
with the sealed credential attached automatically on each call.
The platform dispatches to the agent's registered URL but doesn't manage
its lifecycle — deployment, scaling, and upgrades of an external agent
remain yours. To rotate its credential, deregister and register again.
# Agents (https://docs.initializ.ai/docs/agents)
An agent is the core unit of the platform: a deployable AI service that
carries out a task using one or more **skills**, talks to a **model
provider** through the platform's managed gateway, and is reachable over
one or more **channels**. Every agent is deployed into a **workspace**, and
runs under the security **policies and guardrails** that apply to that
workspace and your organization.
Concretely, an agent bundles:
* **Skills** — the instructions, scripts, and tool dependencies that define
what the agent does. Pick a skill from the catalog or generate one by
describing it in plain English.
* **Model provider and model** — chosen per agent at create time from the
set your platform offers. Credentials and endpoints are managed by the
platform; you never handle model API keys.
* **Channels** — how the agent is reached: the built-in HTTP endpoint used
by the console and by workflows, and optionally Slack.
* **Environment variables and secrets** — values the skill needs at
runtime. Secrets are vaulted at deploy time and are never readable back.
* **Policies and guardrails** — an egress allowlist per agent, plus the
organization and workspace security policies the platform applies
automatically.
Agents you create in the console are built into container images and
deployed by the platform. You can also deploy pre-built images from your
own CI pipeline, or register agents that run entirely outside the platform.
Once running, every agent can be tested from the console, observed through
its Activity, Logs, and Usage tabs, and composed into
[workflows](/docs/workflows).
## In this section [#in-this-section]
# Policies and guardrails (https://docs.initializ.ai/docs/agents/policies-and-guardrails)
Agents don't run open-ended: every agent operates under an egress
allowlist and under the security policies of its workspace and your
organization.
## Egress allowlist [#egress-allowlist]
Each agent has an allowlist of domains it may reach:
* **Base egress** — a platform-managed set of pre-approved domains every
agent gets (shown read-only on the create screen). You never maintain
these.
* **Skill egress** — domains the agent's skill declares it needs.
* **Tool egress** — hosts of governed tools the agent uses, added
automatically so a tool you selected is never blocked by the allowlist.
* **Additional egress** — domains you add yourself at create time or
later.
Anything outside the allowlist is blocked at runtime, and blocked calls
show up as events on the agent's Activity tab and in
[Security Events](/docs/security).
To fix a blocked domain after deployment, open the agent's **Settings**
tab and edit the egress allowlist — applying the change rebuilds and
redeploys the agent.
## Organization and workspace policies [#organization-and-workspace-policies]
On top of the per-agent allowlist, the platform compiles your
organization's and workspace's security policies and applies them to every
agent automatically — deny rules, limits on allowlist size and tool count,
and usage quotas. You don't attach these per agent; they follow the
workspace the agent is deployed into, and policy updates propagate to
running agents without a rebuild.
When a policy or quota denies something — a blocked domain, a denied tool
call, a task refused because a spending or token quota was hit — the
denial is recorded as an audit event and surfaced on the agent's Activity
tab and the Security screens. See [Security](/docs/security) for defining
policies and quotas at the organization and workspace level.
## Guardrails [#guardrails]
Guardrails are part of an agent's baked configuration, set alongside its
skills and policies when the agent is built. Like skills, provider, and
channels, they are locked in the console for
[CI-deployed agents](/docs/agents/ci-deployed-agents), whose configuration
is owned by the repository.
Related runtime protections you control per agent from the create screen:
* **Tool approval** — tools that require human approval route their
approval prompts to the agent's Slack channel.
* **Audit payload capture** — when enabled, raw tool inputs/outputs and
model messages are recorded in audit events, secret-redacted and
size-capped. Off by default.
# Secrets and environment (https://docs.initializ.ai/docs/agents/secrets-and-environment)
Agents get their configuration through environment variables declared by
their skill — API tokens, endpoints, tool credentials. The platform treats
these values with a strict rule: **secrets are write-only**. They are
injected into the agent at build/deploy time, stored only in the agent's
sealed secret, and can never be read back through the console or the API.
## Setting values at create [#setting-values-at-create]
The configure screen lists every variable the skill declares. Variables
flagged as secrets are masked as you type; required ones must be filled
before the agent can be created. Values travel server-side only — never in
URLs — and secret values are never persisted outside the agent's own
sealed secret. Tokens for governed tools and Slack ride the same path.
You can also add your own variables beyond the skill's schema at create
time.
## Rotating values [#rotating-values]
Open the agent's **Settings** tab, **Environment variables** section. Every
variable shows masked (`•••• set`) — click **Edit variables** to enter new
values:
* Values are write-only: **leave a field blank to keep the current
value**. Enter a value only for what you're rotating.
* **Save & restart** patches the agent's secret and restarts it. No
rebuild — the change is live in seconds.
This is the everyday path for credential rotation, and it stays available
even for [CI-deployed agents](/docs/agents/ci-deployed-agents), whose
other configuration is locked in the console.
## The skill owns the keys [#the-skill-owns-the-keys]
The *set* of variables — which keys exist, which are required, which are
secret — is owned by the agent's skill, not editable from Settings. To add
or remove a variable, [edit the skill](/docs/agents/skills) (for
AI-generated skills), which rebuilds the agent. During a skill edit, any
newly declared secret must be given a value before the rebuild; existing
stored values are kept when left blank.
There is no way to recover a secret value from the platform. If you lose
a credential, rotate it at its source and enter the new value in
Settings.
# Skills (https://docs.initializ.ai/docs/agents/skills)
A skill defines what an agent does. It bundles plain-language
**instructions**, optional **scripts**, the **environment variables** it
needs (with secrets flagged), the **egress domains** it must reach, and any
governed **tool dependencies**. An agent is created around a skill, and the
skill's declarations drive the configure screen: which variables you're
asked for, which egress is added, which tool tokens are collected.
## The skill catalog [#the-skill-catalog]
The create flow's entry screen lists the platform's skill catalog. Skills
are grouped by category — developer, SRE, research, utilities — and can be
searched by name or description. Each tile shows the skill's description,
how many variables it declares, and how many egress domains it needs.
Picking a tile takes you straight to the configure screen prefilled from
that skill.
Catalog skills ship with the platform and are read-only — you configure
their variables and egress per agent, but you don't edit their contents.
## The conversational skill builder [#the-conversational-skill-builder]
Instead of picking from the catalog, you can describe the agent in plain
English and let the builder draft a skill. From the create entry screen,
type what the agent should do and click **Generate skill**.
The builder is a split-screen chat:
* On the left, a conversation with the builder. It may ask clarifying
questions before drafting; each of your messages refines the draft.
Suggestion chips propose common refinements like adding error handling
with retries, running on a schedule, or adding a notification step.
* On the right, a live preview of the drafted skill — the instructions
document and any generated scripts — with the parts changed by the last
turn highlighted.
The builder prefers the runtime's built-in tools over generating duplicate
scripts, answers knowledge questions directly instead of wrapping them in
a skill, and requires live data to come from tools rather than model
knowledge.
When the draft looks right, continue with **Create agent** — the configure
screen prefills from the draft exactly as it would from a catalog skill,
and the skill is attached to the agent at create.
The conversational builder is available when your platform's builder
service is configured. If it isn't, the describe box shows as *coming
soon* and the catalog remains the create path.
## Editing a deployed agent's skill [#editing-a-deployed-agents-skill]
Agents whose skill was AI-generated can be edited after deployment. On the
agent's **Settings** tab, click **Edit skill** — this opens the same
conversational builder, seeded from the agent's current skill. Fix a
script, add a step, allow another domain, then review and apply.
Applying an edit goes through a finalize screen that reviews the agent's
configuration for the edited skill — variables (including values for any
newly declared secrets), egress, tools, trigger, and channels — and applies
everything in **one rebuild**: the agent's image is rebuilt and redeployed,
which takes a few minutes. Environment values already stored on the agent
are kept unless you enter new ones.
Catalog skills can't be edited this way — their contents come from the
platform's registry. To change what a catalog-skill agent does, create a
new agent with a generated skill.
# agent (https://docs.initializ.ai/docs/cli/agent)
`initializ agent` groups the commands that inspect and manage deployed
agents. The deploy subcommand has [its own page](/docs/cli/deploy); this page
covers `list`, `get`, `logs`, and `secrets set`.
All subcommands accept the [global flags](/docs/cli#global-flags) and operate
in the workspace resolved from `--workspace` / `INITIALIZ_WORKSPACE_ID` / the
config file / the token's workspace scope.
## Resolving agents by name or id [#resolving-agents-by-name-or-id]
Commands that take `` accept either form: values starting with
`agt-` are treated as agent ids and fetched directly; anything else is
matched by exact name against the workspace's agent list. An unmatched name
exits with code 4 (not found).
## initializ agent list [#initializ-agent-list]
Lists the workspace's agents.
```bash
initializ agent list
```
```
ID NAME STATUS MANAGED BY IMAGE
agt-42 support-agent running ci registry.initializ.ai/acme/support-agent:sha-1a2b3c4
agt-57 triage-agent running platform
```
`MANAGED BY` is `ci` for agents deployed via
[`initializ agent deploy`](/docs/cli/deploy) and `platform` for agents built
in the console. `IMAGE` is the last deployed image tag (empty when the agent
has no build record). `agent list` has no flags of its own; use `-o json` for
the full records.
## initializ agent get [#initializ-agent-get]
Shows one agent.
```bash
initializ agent get
```
```bash
initializ agent get support-agent
```
```
ID agt-42
NAME support-agent
STATUS running
MANAGED BY ci
MODEL openai/gpt-4o
LAST DEPLOY success
IMAGE registry.initializ.ai/acme/support-agent:sha-1a2b3c4
```
`MODEL` is `provider/model` from the agent's forge configuration. When the
last deploy failed, an `ERROR` row shows the server-side error. `agent get`
has no flags of its own.
## initializ agent logs [#initializ-agent-logs]
Prints the deploy progress log — the platform's streamed create/deploy log
for the agent — or, with `--runtime`, the agent pod's own logs.
```bash
initializ agent logs [--runtime]
```
### agent logs flags [#agent-logs-flags]
| Flag | Shorthand | Default | Description |
| ----------- | --------- | ------- | -------------------------------------------------- |
| `--runtime` | | `false` | The agent pod's own logs instead of the deploy log |
### agent logs examples [#agent-logs-examples]
```bash
# Why did the last deploy fail?
initializ agent logs support-agent
# What is the running agent printing?
initializ agent logs support-agent --runtime
```
Logs are written verbatim to stdout.
## initializ agent secrets set [#initializ-agent-secrets-set]
Rotates secret values on a deployed agent. The given keys are updated in the
agent's Kubernetes Secret and the pods are rolled — no redeploy needed.
Values are never persisted by the platform.
```bash
initializ agent secrets set KEY=VALUE [KEY2=VALUE2 …] --agent
```
A bare `KEY` (no `=VALUE`) reads the value from the CLI's own environment,
keeping secrets out of `argv` and shell history. A bare key that is not set
in the environment fails with exit code 2.
Secrets stay editable for CI-managed agents — this is the sanctioned way to
rotate credentials without a redeploy, even though skills, provider,
channels, policies, and guardrails are locked to the repo.
### agent secrets set flags [#agent-secrets-set-flags]
| Flag | Shorthand | Default | Description |
| --------- | --------- | ------- | --------------------------- |
| `--agent` | | | Agent name or id (required) |
### agent secrets set examples [#agent-secrets-set-examples]
```bash
# Value taken from the CI/shell environment (recommended):
export OPENAI_API_KEY=sk-…
initializ agent secrets set OPENAI_API_KEY --agent support-agent
# Multiple keys, explicit values:
initializ agent secrets set SLACK_BOT_TOKEN=xoxb-… WEBHOOK_SECRET=whsec-… --agent agt-42
```
```
updated OPENAI_API_KEY on support-agent; pods are rolling
```
The confirmation goes to stderr. With `-o json`, a machine-readable result is
also written to stdout:
```json
{
"agent_id": "agt-42",
"updated": ["OPENAI_API_KEY"]
}
```
# auth (https://docs.initializ.ai/docs/cli/auth)
`initializ auth` authenticates the CLI against the platform. Both subcommands
validate the token **server-side** — signature and revocation — not just a
local JWT decode.
CI pipelines usually skip `auth login` entirely and set `INITIALIZ_TOKEN`,
`INITIALIZ_ORG_ID`, and `INITIALIZ_API_URL` as environment variables. See
[Authentication](/docs/cli#authentication).
## initializ auth login [#initializ-auth-login]
Stores a platform access token (non-interactive). The token is validated
server-side, then written together with the API URL, org id, and workspace id
to `~/.initializ/config.yaml` (created with `0600` permissions).
```bash
initializ auth login [--token-stdin] [--token ] --org --api-url
```
Tokens are minted by an org/workspace admin via the console with role
`developer` or `workspace_admin`.
Behavior:
* The token can come from `--token`, `--token-stdin`, or `INITIALIZ_TOKEN` —
if none is set, the command fails with exit code 2.
* If no workspace id was configured, the workspace scoped into the token (if
any) is saved to the config file.
* Prefer `--token-stdin` over `--token` so the token stays out of shell
history.
### auth login flags [#auth-login-flags]
| Flag | Shorthand | Default | Description |
| --------------- | --------- | ------- | ---------------------------------------------------------- |
| `--token-stdin` | | `false` | Read the token from stdin (first line, whitespace-trimmed) |
All [global flags](/docs/cli#global-flags) apply; `--api-url`, `--org`,
`--token`, and `--workspace` are the relevant ones here.
### auth login example [#auth-login-example]
```bash
echo "$INITIALIZ_TOKEN" | initializ auth login \
--token-stdin \
--org org_a1b2c3 \
--api-url https://api.initializ.ai
```
```
logged in as ci-bot@acme.com (org org_a1b2c3), config written to /home/dev/.initializ/config.yaml
```
The confirmation line goes to stderr and is suppressed by `--quiet`.
## initializ auth whoami [#initializ-auth-whoami]
Validates the token server-side and prints the resolved identity. This checks
the token's signature **and** its revocation status — the fast-fail preflight
for CI pipelines. An invalid or revoked token exits with code 3.
```bash
initializ auth whoami
```
`auth whoami` takes no flags of its own beyond the
[global flags](/docs/cli#global-flags).
### auth whoami output [#auth-whoami-output]
Text output is a table of the verified identity (the `USER` row shows the
email when present, otherwise the user id; `WORKSPACE` appears only when a
workspace is in scope):
```
USER ci-bot@acme.com
ORG org_a1b2c3
WORKSPACE ws_a1b2c3de
API https://api.initializ.ai
```
With `-o json` the raw verification response is printed:
```bash
initializ auth whoami -o json
```
```json
{
"valid": true,
"user_id": "usr_9f8e7d",
"org_id": "org_a1b2c3",
"email": "ci-bot@acme.com",
"workspace_id": "ws_a1b2c3de",
"error": ""
}
```
### Preflight pattern for pipelines [#preflight-pattern-for-pipelines]
```bash
# Fails the job early (exit 3) if the token is invalid or was revoked.
initializ auth whoami
initializ agent deploy -f initializ-deploy.yaml --image "$IMAGE" --wait
```
# agent deploy (https://docs.initializ.ai/docs/cli/deploy)
`initializ agent deploy` submits a CI-built agent image to the platform. It
composes a deploy request from `initializ-deploy.yaml`, `forge.yaml`, the
repo's `SKILL.md` files, and the `forge build` output directory
(`.forge-output`), then submits it. The platform renders the Kubernetes
manifests and rolls the agent — the image must already be pushed to the
workspace Environment's registry by your CI job.
```bash
initializ agent deploy -f initializ-deploy.yaml [--image [] [--wait]
```
Key semantics:
* **Upsert** on (workspace, agent name): the first deploy creates the agent,
later deploys update it.
* `--image` overrides the spec's `image`, so CI-templated tags need no
`yq`/`sed` rewriting of the manifest.
* With `--wait` the command polls until the rollout finishes — exit code 5 on
failure, 6 on timeout. This is the CI-friendly mode.
## agent deploy flags [#agent-deploy-flags]
| Flag | Shorthand | Default | Description |
| ------------------ | --------- | ----------------------- | -------------------------------------------------- |
| `--file` | `-f` | `initializ-deploy.yaml` | Path to the deploy spec |
| `--image` | | | Image ref to deploy (overrides the spec's `image`) |
| `--wait` | | `false` | Poll until the rollout finishes |
| `--timeout` | | `0` (→ 10m) | Max time to wait (Go duration, e.g. `15m`) |
| `--poll-interval` | | `0` (→ 5s) | Status poll interval |
| `--skip-env-check` | | `false` | Don't fail on missing required env vars |
All [global flags](/docs/cli#global-flags) apply. The target workspace is
resolved in this order: `--workspace` / `INITIALIZ_WORKSPACE_ID` / config
file, then the spec's `agent.workspace`, then the workspace baked into the
token. If none resolves, the command fails with exit code 2.
## The deploy spec (initializ-deploy.yaml) [#the-deploy-spec-initializ-deployyaml]
The spec lives in the agent's git repo next to `forge.yaml`. Fully annotated:
```yaml
apiVersion: initializ.ai/v1
kind: AgentDeploy
agent:
# Display/lookup name on the platform. Deploys are an UPSERT keyed on
# (workspace, name). Defaults to forge.yaml's agent_id when omitted.
name: support-agent
# Agent runtime type. v1 supports "forge" (the default).
type: forge
# Workspace id (ws_…). Optional — falls back to --workspace,
# INITIALIZ_WORKSPACE_ID, then the workspace baked into the token.
# workspace: ws_a1b2c3de
# Image your CI just built & pushed to the registry configured on the
# workspace's Environment. --image overrides this.
image: registry.initializ.ai/acme/support-agent:latest
forge:
# Path to forge.yaml, relative to this file. Default: ./forge.yaml
path: ./forge.yaml
# forge build output — the CLI reads the image's declared env-var union
# from build-manifest.json (or k8s/secrets.yaml). Default: ./.forge-output
outputDir: ./.forge-output
# Environment variables for the agent container.
env:
- name: LOG_LEVEL
value: info
- name: OPENAI_API_KEY
value: ${OPENAI_API_KEY} # interpolated from the CI environment
secret: true # lands only in the agent's Kubernetes Secret
- name: FEATURE_FLAG_X
value: ${FEATURE_FLAG_X}
optional: true # silently omitted when ${FEATURE_FLAG_X} is unset
# Optional container port when the agent doesn't listen on forge's default 8080.
# port: 9000
# Optional runtime sizing; omitted fields use platform defaults.
resources:
replicas: 1
requests: {cpu: 250m, memory: 256Mi}
limits: {cpu: "1", memory: 1Gi}
# Extra egress domains merged additively with forge.yaml's
# egress.allowed_domains and skill-declared egress domains.
egress:
additionalDomains:
- api.stripe.com
# Default deploy behavior (flags always win).
deploy:
wait: true
timeout: 10m
```
Validation rules (violations exit with code 2): `apiVersion` must be
`initializ.ai/v1` when set, `kind` must be `AgentDeploy` when set,
`agent.type` must be `forge` when set, `port` must be 0–65535, and every
`env` entry needs a non-empty `name`.
### Env value interpolation [#env-value-interpolation]
`env[].value` supports `${VAR}` interpolation **from the CI process
environment only** — secret values live in the CI secret store, never in the
file. Interpolation applies exclusively to `env[].value`; the rest of the
document (image, name, egress) stays literal, so what gets deployed is
auditable from the file plus the `--image` flag alone.
* An unresolvable `${VAR}` reference fails the deploy with exit code 2 —
unless the entry is marked `optional: true`, in which case it is omitted
from the request entirely.
* `$$` escapes a literal `$`; a bare `$` (not followed by `{`) is literal.
* `secret: true` routes the value into the agent's Kubernetes Secret only —
the platform never persists it.
### The env-var contract check [#the-env-var-contract-check]
The CLI knows which env vars the image **requires** — the union of skill
requirements, channel vars, and model-provider keys computed at
`forge build` time — and fails fast (exit 2) when a required var is neither in
`env:` nor provided as a secret. Source-of-truth order:
1. `.forge-output/build-manifest.json` — the `env_required` / `env_optional`
lists (structured; present in recent forge versions).
2. `.forge-output/k8s/secrets.yaml` — the `stringData:` keys; a key preceded
by a `# optional` comment line counts as optional (older forge versions).
3. `SKILL.md` frontmatter (`requirements.env.required` / `optional` /
`one_of`) when no `.forge-output` is present. `one_of` groups are treated
as optional so they display without causing false failures.
`--skip-env-check` downgrades a missing required var from a local exit-2
failure to a platform-side warning (the platform re-checks anyway).
### Skill discovery [#skill-discovery]
The CLI lifts display and policy metadata (name, description, category,
declared env requirements, egress domains) from the repo's skill files,
mirroring forge's own discovery rules: `skills/*.md`, `skills/*/SKILL.md`,
plus the file named by `forge.yaml`'s `skills.path` (default `SKILL.md`).
### What is read from forge.yaml [#what-is-read-from-forgeyaml]
From `forge.yaml` the CLI lifts: `agent_id` (required — also the default
agent name), `version`, `framework`, `model.provider` / `model.name`,
`egress.mode` / `egress.allowed_domains`, `channels`, `skills.path`, audit
capture settings, and compression. The exact file bytes are also uploaded for
provenance. Unknown fields never break a deploy.
### CI provenance [#ci-provenance]
When running under GitHub Actions or GitLab CI, the CLI auto-detects
provenance metadata (provider, commit SHA, run URL) from the standard CI env
vars and attaches it to the deploy for display on the platform.
## Waiting for the rollout [#waiting-for-the-rollout]
With `--wait` (or `deploy.wait: true` in the spec) the command polls the
agent's deploy status until it is terminal:
* Statuses progress through `building` to `success` or `failed`; each
transition is printed to stderr (suppressed by `--quiet`).
* Poll interval defaults to **5s** (with jitter so parallel CI jobs don't
stampede the API); override with `--poll-interval`.
* Timeout resolution: `--timeout` flag, else the spec's `deploy.timeout`,
else **10m**. On expiry the command exits with code **6**.
* A `failed` status exits with code **5** and prints the server-side error
(or points you at `initializ agent logs`).
* Transient errors (network, 5xx) are tolerated up to 5 consecutive polls;
auth or not-found errors abort immediately.
Without `--wait`, the command prints the deploy id to stdout and returns as
soon as the platform accepts the request (the rollout continues
asynchronously).
## Deploy output [#deploy-output]
Text mode (progress on stderr, result on stdout):
```
deploying support-agent (image registry.initializ.ai/acme/support-agent:sha-1a2b3c4) to workspace ws_a1b2c3de…
accepted: agent agt-42 deploy dep-777
status: building
status: success
deployed agt-42 (registry.initializ.ai/acme/support-agent:sha-1a2b3c4)
```
With `-o json` and `--wait`, one JSON document goes to stdout:
```json
{
"agent_id": "agt-42",
"deploy_id": "dep-777",
"status": "success",
"image": "registry.initializ.ai/acme/support-agent:sha-1a2b3c4",
"warnings": []
}
```
Without `--wait`, `-o json` prints the acceptance response
(`agentId`, `deployId`, `status`, `created`, `warnings`); text mode prints
just the deploy id.
## Complete GitHub Actions workflow [#complete-github-actions-workflow]
```yaml
name: deploy-agent
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install forge
run: |
curl -fsSL https://github.com/initializ/forge/releases/latest/download/forge-Linux-x86_64.tar.gz \
| tar xz && sudo mv forge /usr/local/bin/
# forge build generates .forge-output/ (Dockerfile, build-manifest.json,
# k8s templates) — the CLI reads the env-var contract from it.
- name: forge build
run: forge build
- uses: docker/login-action@v3
with:
registry: registry.initializ.ai
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- uses: docker/build-push-action@v6
with:
context: .forge-output
push: true
tags: registry.initializ.ai/acme/support-agent:sha-${{ github.sha }}
- name: Install initializ CLI
run: |
curl -fsSL https://github.com/initializ/cli-next/releases/latest/download/initializ_linux_amd64.tar.gz \
| tar xz && sudo mv initializ /usr/local/bin/
- name: Deploy to initializ
env:
INITIALIZ_API_URL: https://api.initializ.ai
INITIALIZ_TOKEN: ${{ secrets.INITIALIZ_TOKEN }}
INITIALIZ_ORG_ID: ${{ vars.INITIALIZ_ORG_ID }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
initializ auth whoami
initializ agent deploy -f initializ-deploy.yaml \
--image "registry.initializ.ai/acme/support-agent:sha-${{ github.sha }}" \
--wait --timeout 10m
```
# CLI (https://docs.initializ.ai/docs/cli)
The `initializ` CLI deploys **forge agents whose images are built by your own
CI** to the initializ AI Platform. The platform never accesses your git
repository — the CLI runs inside the CI checkout, reads `forge.yaml`, skill
metadata, and `forge build` output, and sends the platform everything it needs
alongside the image reference.
```
CI job: forge build → docker build+push (workspace registry) → initializ agent deploy --wait
```
Agents deployed this way are **CI-managed** on the platform: skills, model
provider, channels, policies, and guardrails cannot be edited in the console
(the repo owns them; the platform returns 403 on such edits). Environment
variables and **secrets remain editable** — via
[`initializ agent secrets set`](/docs/cli/agent#initializ-agent-secrets-set)
or the console.
## Install [#install]
Binaries are published as goreleaser artifacts on the GitHub releases of
`initializ/cli-next` (multi-arch archives + checksums):
```bash
curl -fsSL https://github.com/initializ/cli-next/releases/latest/download/initializ_linux_amd64.tar.gz \
| tar xz && sudo mv initializ /usr/local/bin/
```
Container-native CI can use the released image
`ghcr.io/initializ/cli-next:` instead of installing a binary.
## Authentication [#authentication]
An org or workspace admin mints a workspace-scoped access token (role
`developer` or `workspace_admin`) via the console. The CLI authenticates every
request with that token.
Configuration is resolved with precedence **flag > environment variable >
config file** — for every setting, everywhere.
In CI, skip `auth login` entirely and set environment variables:
| Env var | Meaning |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `INITIALIZ_API_URL` | Platform API base URL |
| `INITIALIZ_TOKEN` | The access token (store it as a CI secret) |
| `INITIALIZ_ORG_ID` | Organization id (`org_…`) |
| `INITIALIZ_WORKSPACE_ID` | Workspace id (`ws_…`); optional if the token is workspace-scoped |
| `INITIALIZ_AUTH_URL` | Override for the token-verification base URL — only needed when token verification is not served behind the same gateway as the rest of the platform API |
Tokens are revocable server-side.
[`initializ auth whoami`](/docs/cli/auth#initializ-auth-whoami) verifies the
token (signature **and** revocation) — use it as a pipeline preflight so a
revoked token fails fast with exit code 3.
On a laptop, [`initializ auth login`](/docs/cli/auth#initializ-auth-login)
writes the resolved configuration to `~/.initializ/config.yaml` (created with
`0600` permissions because it holds the token). A missing config file is never
an error — env vars and flags can carry the whole configuration (CI mode).
## Global flags [#global-flags]
These persistent flags are available on every command:
| Flag | Shorthand | Default | Description |
| ------------- | --------- | ------- | ------------------------------------------------------------------- |
| `--api-url` | | | Platform API base URL (env `INITIALIZ_API_URL`) |
| `--auth-url` | | | Override for the token verifier base URL (env `INITIALIZ_AUTH_URL`) |
| `--token` | | | Platform access token (env `INITIALIZ_TOKEN`) |
| `--org` | | | Organization id (env `INITIALIZ_ORG_ID`) |
| `--workspace` | | | Workspace id (env `INITIALIZ_WORKSPACE_ID`) |
| `--output` | `-o` | `text` | Output format: `text` or `json` |
| `--quiet` | `-q` | `false` | Suppress progress output |
With `-o json`, exactly one JSON document is written to stdout — progress and
log lines go to stderr — so `initializ … -o json | jq` is always safe.
## Exit codes [#exit-codes]
The CLI has a fixed exit-code contract that CI pipelines can script against:
| Code | Meaning |
| ---- | -------------------------------------------------------------------------------------------- |
| `0` | Success (with `--wait`: the rollout finished) |
| `1` | Unexpected error |
| `2` | Usage / spec validation error (bad YAML, unset `${VAR}` reference, missing required env var) |
| `3` | Authentication failure (invalid or revoked token; HTTP 401/403) |
| `4` | Not found (agent or workspace) |
| `5` | Deploy failed server-side (`--wait` observed a `failed` status) |
| `6` | `--wait` timed out |
## initializ version [#initializ-version]
Prints the CLI version, stamped at release time:
```bash
initializ version
```
```
initializ v0.3.0 (commit 1a2b3c4, built 2026-07-01)
```
Development builds print `initializ dev (commit none, built unknown)`.
# Deployment (https://docs.initializ.ai/docs/deployment)
This section describes where the initializ AI Platform can run and what your
environment needs before installation.
## In this section [#in-this-section]
* [Deployment targets](/docs/deployment/targets) — supported environments.
* [Prerequisites](/docs/deployment/prerequisites) — what you need before
installing.
# Prerequisites (https://docs.initializ.ai/docs/deployment/prerequisites)
Have the following in place before installation. Each item is a
*requirement* — the concrete setup steps for your choices are covered in
the onboarding runbook.
## Kubernetes cluster [#kubernetes-cluster]
* A cluster you administer, with permission to create namespaces,
deployments, services, network policies, and secrets.
* A load balancer or gateway capable of terminating HTTPS for the
platform's hostnames.
## DNS and TLS [#dns-and-tls]
* A DNS domain (or subdomain) for the platform's hostnames — the console
and the platform API each get one.
* A TLS certificate covering those hostnames (a wildcard certificate for
the chosen subdomain is the simplest option).
## Identity provider (OIDC) [#identity-provider-oidc]
* An OIDC-compliant identity provider — **Okta is a verified choice** —
with:
* a confidential (server-side) client for the console, and
* access tokens that carry the user's **email** claim (the platform keys
access on verified email).
* Users are authenticated by your IdP; platform roles are granted inside
the platform by an organization admin.
## Database [#database]
* A MongoDB-compatible database reachable from the cluster. **MongoDB and
Amazon DocumentDB are supported**; DocumentDB deployments have specific
connection-string requirements covered during onboarding.
## Container registry [#container-registry]
* An OCI registry the cluster can pull from, used for the agent images the
platform builds. **Amazon ECR is supported with IAM-based (credential-less)
access**; any registry with push/pull credentials also works.
## LLM endpoint [#llm-endpoint]
* An OpenAI-compatible endpoint reachable from the cluster for agents and
platform AI features: a model gateway you operate (for example Kong), a
provider's API directly, or a managed gateway provided with the platform.
* If your cluster restricts egress, allow outbound access to the endpoint
you choose.
## Optional integrations [#optional-integrations]
* **Slack** — a Slack app (bot + app-level tokens) if you want agents
reachable in Slack or Slack-based approval flows.
# Deployment targets (https://docs.initializ.ai/docs/deployment/targets)
The platform is **self-hosted**: it runs in your own cloud account or data
center, on infrastructure you control. Your data, agents, and model traffic
stay inside your environment.
## Kubernetes [#kubernetes]
The platform deploys onto a Kubernetes cluster you administer. Any
conformant cluster works; **Amazon EKS** is a verified target used in
production customer deployments, typically together with Amazon DocumentDB
and Amazon ECR.
Agent workloads run in the same cluster: each workspace gets its own
namespace, and agents are deployed into their workspace's namespace with
network policies applied.
## Sizing [#sizing]
A small cluster is enough to start — the platform's own services are
lightweight; capacity is driven by how many agents you run and the
resources their workloads need. Sizing guidance for your expected agent
count is part of onboarding with your initializ contact.
## What initializ provides [#what-initializ-provides]
* Container images for every platform release, pulled from a registry you
are granted access to.
* Installation manifests and configuration reference for your target.
* An onboarding runbook specific to your environment (cloud provider,
identity provider, database, and registry choices).
See [Prerequisites](/docs/deployment/prerequisites) for what your
environment needs before installation.
# Gateway (https://docs.initializ.ai/docs/gateway)
The **Gateway** area of the console governs the two ways agents reach the
outside world: language models (model routing) and external tools (MCP
servers). Both are org-level concerns — they apply across workspaces.
Both Gateway screens ship **disabled by default** and may not be enabled in
your deployment. The underlying behavior they describe — a single managed
model endpoint, tools admitted through the org registry — applies either
way.
## In this section [#in-this-section]
# MCP servers (https://docs.initializ.ai/docs/gateway/mcp-servers)
MCP (Model Context Protocol) servers are **external tool servers**: services
that expose tools an agent can call at runtime — ticketing systems, chat
platforms, internal APIs.
The **Gateway → MCP Servers** screen is disabled by default and may not be
enabled in your deployment. When enabled, it is the org-level catalog for
registering the MCP servers your agents may reach — endpoint plus
credentials, following the console's convention that credentials are
write-only (encrypted at rest, never displayed after saving).
## How tools reach agents today [#how-tools-reach-agents-today]
An agent doesn't get tools by talking to an arbitrary server — tools flow
through two gates:
* **The skill declares them.** A skill lists the tools it uses; the
conversational skill builder proposes them from what's admitted. See
[Skills and tools](/docs/agents/runtime/skills-and-tools).
* **The org Tool Registry admits them.** **Security → Tool Registry** is the
org-level catalog of admitted binary and MCP tools that skills may use.
A tool that isn't in the registry isn't available to skills.
At runtime the agent's egress policy applies on top: outbound calls are
restricted to the agent's allowlist, and blocked calls are audited as
security events (see [Security](/docs/security)).
## Registering an external agent instead [#registering-an-external-agent-instead]
If the external system you want to integrate is itself an agent (it speaks
the A2A protocol), don't model it as a tool server — register it under
**Build → Agents → Register**. The console reads the agent's card, renders
its declared authentication schemes (API key, bearer/basic, or a pre-issued
token) as the credential form, and the registered agent becomes available to
workflows alongside platform-built agents.
# Model routing (https://docs.initializ.ai/docs/gateway/model-routing)
Agents never talk to a model provider with their own credentials. Every model
call — from the conversational skill builder and from deployed agents alike —
goes through **one LLM endpoint** configured for the platform.
The **Gateway → Model Routing** screen is disabled by default and may not be
enabled in your deployment. Until it is enabled, routing is configured by
your platform operator at deployment time (see
[Deployment](/docs/deployment)); this page describes the behavior that
configuration produces.
## One endpoint for all model traffic [#one-endpoint-for-all-model-traffic]
The platform's LLM endpoint is OpenAI-compatible and can be:
* The platform's **managed model gateway**, which fronts one or more
providers.
* A **gateway or proxy you already run** (for example, an enterprise LLM
gateway).
* A **provider's API directly**.
The endpoint's credentials live with the platform, not with individual
agents — creating an agent never involves pasting a model API key.
## Providers and models agents can choose [#providers-and-models-agents-can-choose]
When someone creates an agent, the create screen offers a **provider picker**
and, per provider, a **model picker**. That offered set comes from the
deployment's routing configuration:
* Behind a gateway, multiple providers can be enabled and every enabled
provider's models appear in the picker.
* Pointed directly at a single provider's API, the picker is locked to that
provider regardless of what else is configured.
The choice is fixed at creation: editing an agent's skill later does not
change its provider or model. The agent's detail page shows the model as
"managed by the platform" — endpoint, auth, and routing are not editable per
agent.
## Where routing shows up elsewhere [#where-routing-shows-up-elsewhere]
* **Usage** reports consumption broken down by model, so routing decisions
are visible in spend.
* **Security policies and quotas** can cap model usage per org, workspace,
or agent — a routed call that exceeds a quota is denied and audited (see
[Security](/docs/security)).
# First login (https://docs.initializ.ai/docs/getting-started/first-login)
A freshly installed platform has an organization but no workspaces, and a
workspace needs an environment to provision its namespace into. The console
therefore walks the **first organization admin** through creating both before
showing anything else.
## Who sees the onboarding [#who-sees-the-onboarding]
When an **org admin** signs in and the organization has zero workspaces, the
console renders a two-step setup flow in place of the normal shell. There is
no way around it — nothing else in the console is useful until a workspace
exists.
Members (non-admins) who sign in before setup is complete see the normal
console with a **"No workspace access"** empty state instead: members cannot
create workspaces, so the screen tells them to ask an organization admin to
add them to a workspace and refresh.
## Step 1 — create the in-cluster environment [#step-1--create-the-in-cluster-environment]
The first environment must be **in-cluster**: it runs on the platform's own
cluster, so no kubeconfig is needed. You only choose a name (the default is
`In-cluster`).
If an environment already exists (for example, one was created during
installation), the onboarding skips straight to the workspace step.
Remote clusters (bring your own kubeconfig) can be added later under
Cloud → Environments (see
[Workspaces and environments](/docs/getting-started/workspaces-and-environments)) —
only the *first* environment is required to be in-cluster.
## Step 2 — create the first workspace [#step-2--create-the-first-workspace]
Next you name the first workspace. Creating it provisions one Kubernetes
namespace on the environment's cluster — the flow shows "Provisioning
namespace…" while this happens.
On success the console selects the new workspace as your Build scope and
lands you on **Build → Overview**. From here you can invite teammates
([Organization → Settings](/docs/organization/settings)) and
[create your first agent](/docs/getting-started/your-first-agent).
## After onboarding [#after-onboarding]
The two-step flow never appears again once a workspace exists. Additional
workspaces are created from the workspace picker in the sidebar ("+ New
workspace" — org admins only), and additional environments from
Cloud → Environments.
# Getting started (https://docs.initializ.ai/docs/getting-started)
This section walks you through your first session on the initializ AI
Platform — from signing in to a running agent.
## Signing in [#signing-in]
You sign in to the console with your organization's identity provider (OIDC —
for example Okta). The identity provider only authenticates you; access to an
organization on the platform is granted separately by an organization admin.
If you sign in and see a screen telling you to contact your administrator, you
have no organization membership yet — ask an admin to invite you under
[Organization → Settings](/docs/organization/settings).
If your admin hasn't finished initial setup yet, see
[First login](/docs/getting-started/first-login) for what to expect.
## Where you land [#where-you-land]
]
After signing in you land on **Home** — an org-level launchpad with:
* A personalized greeting and a single **ask box** as the front door.
* **Jump back in** — your recent agents and workflows.
* A slim strip of org-wide stats (agents, executions in the last 24 hours).
The left sidebar groups the console into **Build** (workspace-scoped: agents,
workflows, activity), **Security**, **Usage**, **Cloud**, **Gateway**, and
**Organization**. Sections your deployment has disabled are hidden entirely,
so your sidebar may show fewer items than the docs describe.
## The ask box and the command palette [#the-ask-box-and-the-command-palette]
The ask box on Home and the command palette (press ⌘K, or
Ctrl+K on Windows/Linux) share one input with three
jobs:
* **Navigate** — type a screen name ("policies", "environments") and jump
straight to it.
* **Find** — search your entities (agents, workflows) by name.
* **Ask** — phrase a question or a goal ("create an agent that triages
tickets", "why was my request blocked?") and the platform's intent router
answers with links to the right screen, or hands you off into a create flow
with your goal pre-filled.
Question-like input promotes the Ask row to the top; otherwise navigation
matches come first.
## Workspaces in one minute [#workspaces-in-one-minute]
Everything you build lives in a **workspace**:
* Agents and workflows belong to exactly one workspace.
* A workspace is backed by one Kubernetes namespace, provisioned on the
cluster of the **environment** the workspace is bound to.
* The Build section of the console is always scoped to one workspace at a
time; the workspace picker at the top of the sidebar switches that scope.
Read [Workspaces and environments](/docs/getting-started/workspaces-and-environments)
for the full model.
## Next steps [#next-steps]
# Workspaces and environments (https://docs.initializ.ai/docs/getting-started/workspaces-and-environments)
Two constructs organize everything on the platform: **workspaces** (where you
build) and **environments** (where the resulting workloads run).
## Workspaces — the working scope [#workspaces--the-working-scope]
A workspace is the unit of tenancy for building:
* Every agent and workflow belongs to exactly one workspace.
* Each workspace is one Kubernetes namespace, provisioned on the cluster of
the environment it is bound to.
* Workspace membership controls who can see and build in it (see
[Roles at a glance](#roles-at-a-glance) below).
The **Build** section of the console (Overview, Agents, Workflows, Activity,
Settings) is always scoped to a single workspace.
### Switching workspaces [#switching-workspaces]
The workspace picker at the top of the sidebar selects your Build scope.
Changing it re-scopes only the Build screens — Security, Usage, Cloud,
Gateway, and Organization are org-level and unaffected. The picker also hosts
the **"+ New workspace"** action, which only org admins see (workspace
creation is org-admin-only).
**Build → Overview** is the workspace's landing page: deployment status,
recent activity, usage, and the environment the workspace is bound to (with a
**Change** action to re-bind it to another catalog entry).
## Environments — where workloads run [#environments--where-workloads-run]
**Cloud → Environments** is the org-level catalog of clusters and registry
credentials. Workspaces bind to an entry from this catalog and provision
their namespace on that entry's cluster.
An environment entry has:
* **Name** — how it appears in the catalog (e.g. `prod-eastus`).
* **Cluster type** — *in-cluster* (runs on the platform's own cluster, no
kubeconfig needed; at most one such entry exists, and the first environment
must be in-cluster) or *remote* (reached via a kubeconfig you paste in).
* **Cluster name** and **registry URL** — where agent images are pushed and
pulled from.
* **Registry pull secret** (`dockerconfigjson`) — optional credentials for
the registry.
Credentials (kubeconfig, registry secret) are write-only: they are encrypted
at rest and never shown again after saving. Edit forms leave them blank —
they are only resent if you type a new value.
## Roles at a glance [#roles-at-a-glance]
Access has two tiers, both managed under
[Organization → Settings](/docs/organization/settings):
* **Org admin** — everything, org-wide: create workspaces and environments,
manage members, policies, and tokens.
* **Org member** — can sign in; what they can do is determined by their
workspace grants.
* **Workspace admin** — manages one workspace (its agents, settings, and
workspace-level policy).
* **Developer** — builds within one workspace.
Workspace-scoped grants (workspace admin, developer) automatically make the
user an org member. Org admins can access every workspace.
## Next step [#next-step]
With a workspace selected, you're ready to
[create your first agent](/docs/getting-started/your-first-agent).
# Your first agent (https://docs.initializ.ai/docs/getting-started/your-first-agent)
This page is the short version of the build loop. For every option in depth,
see [Creating an agent](/docs/agents/creating-an-agent).
## Before you start [#before-you-start]
You need a workspace selected in the sidebar's workspace picker. If you have
none, see [First login](/docs/getting-started/first-login).
## Create the agent [#create-the-agent]
Go to **Build → Agents** and start a new agent. You can begin two ways:
* **Describe what it should do** — the conversational skill builder turns
your goal into a skill (instructions, tools, entry point) that you refine
by chatting.
* **Start from a skill** — pick a ready-made skill from the catalog.
You also pick the **provider and model** from the set your deployment offers.
This choice is create-only — editing the skill later doesn't change the
model. The model endpoint and its credentials are managed by the platform;
you never paste a model API key into an agent.
The ask box on Home works as a shortcut: type a goal like "create an agent
that summarizes support tickets" and the console hands you into this create
flow with the goal pre-filled.
## Watch the build [#watch-the-build]
When you deploy, the platform builds a container image for the agent and
rolls it out into your workspace's namespace. The create screen streams the
build progress log live, so you see each stage — and if something fails, the
same stream carries the failure diagnostics.
After creation, the agent's detail page shows its live status; a failed build
or rollout surfaces a callout with the phase, message, and diagnostics.
## Try it [#try-it]
Open the agent from **Build → Agents**. The **Console** tab on the agent
detail page is where you run it: type a message, and a chat session starts
against the deployed agent. Past sessions are listed so you can pick up where
you left off.
A separate **Build → Playground** screen exists for experimenting across the
gateway catalog, but it is disabled by default and may not be enabled in your
deployment. The agent Console tab is the default way to try an agent.
## See what happened [#see-what-happened]
Two places show the trail your run left behind:
* The agent's **Activity** tab — the agent's runtime audit events, grouped
by execution, with a drawer for event details. A **Logs** tab shows a
bounded tail of the agent's container logs, and a **Diagnose** action
produces a cited diagnosis from health, build, events, and logs.
* **Build → Activity** — the workspace-wide feed: timestamp, event type,
message, and actor for everything that happened in the workspace.
## Keep going [#keep-going]
# Organization (https://docs.initializ.ai/docs/organization)
The **Organization** area of the console is where org admins administer the
tenant itself: who belongs to the organization (and with what role), and the
API tokens that let the CLI and CI pipelines act on its behalf.
## In this section [#in-this-section]
# Organization settings (https://docs.initializ.ai/docs/organization/settings)
**Organization → Settings** manages who belongs to your organization and what
they can do. Your identity provider only *authenticates* users — membership
here is what ties an authenticated identity to the organization and grants it
anything.
Only org admins can change membership; everyone else sees the roster
read-only.
## Your organization ID [#your-organization-id]
The screen shows the organization's ID with a copy action. You need it when
authenticating the [CLI](/docs/cli/auth) (`--org `) and for
programmatic API access alongside an
[API token](/docs/organization/tokens).
## Inviting a member [#inviting-a-member]
Invite a user by **email** — it must match the email their identity provider
asserts, because membership is keyed by email. Choose a role:
* **Org admin** — everything, org-wide.
* **Org member** — org access only; workspace grants determine what they can
build.
* **Workspace admin** — manages one workspace; you pick the workspace as
part of the invite.
* **Developer** — builds within one workspace; also workspace-scoped.
Workspace-scoped grants automatically make the user an org member. The invite
takes effect the next time the user signs in — there is no email
notification to accept.
## Managing existing members [#managing-existing-members]
Each member row is read-only until you click its edit (pencil) action:
* **Change the org role** — switch a member between admin and member; save
applies it immediately.
* **Revoke workspace access** — remove an individual workspace grant from
the member without touching their org membership.
* **Remove the member** — removes them from the organization entirely; they
can still authenticate with the identity provider but will land on the
"no organization" screen.
## How roles map to workspaces [#how-roles-map-to-workspaces]
Within a workspace, a member appears as either **Workspace admin** or
**Developer**. Org admins are not listed per workspace — they implicitly
have access to every workspace, including creating new ones. For how these
roles shape day-to-day work, see
[Workspaces and environments](/docs/getting-started/workspaces-and-environments).
# API tokens (https://docs.initializ.ai/docs/organization/tokens)
**Organization → API Tokens** manages long-lived tokens scoped to your
organization. They exist so non-interactive clients — the
[CLI](/docs/cli), CI pipelines, scripts — can authenticate without a
browser sign-in.
A request authenticates by sending the token as a bearer credential together
with the organization ID:
```text
Authorization: Bearer
```
Every service verifies the token in-process — signature *and* revocation —
on each request.
## Creating a token [#creating-a-token]
A token is created with:
* **Name** — how it appears in the list.
* **Role** — what the token may do:
*Developer* (build within a workspace), *Workspace admin* (manage one
workspace), or *Org admin* (everything, org-wide).
* **Workspace** — required for the two workspace-scoped roles; org-admin
tokens have no workspace.
* **Expiry** — no expiry, 30 days, 90 days, or 1 year.
The token value is shown **exactly once**, at creation. Copy it immediately
and store it in your secret manager — the console cannot display it again.
For CI, prefer a **developer** or **workspace-admin** token scoped to the
workspace the pipeline deploys into, with an expiry — not an org-admin token.
See [CLI authentication](/docs/cli/auth) for wiring it up
(`initializ auth login`, or `INITIALIZ_TOKEN` / `INITIALIZ_ORG_ID` /
`INITIALIZ_API_URL` in CI).
## Reading the token list [#reading-the-token-list]
Each row shows the token's name, status (`active` or `revoked`, with revoked
tokens struck through), its workspace scope if any, and its created /
last-used / expires timestamps — last-used is your signal for spotting
abandoned tokens worth revoking.
## Revoking [#revoking]
Revoking a token is a one-way status flip: it is rejected everywhere on the
very next request. The row stays in the list (struck through) for the record.
Revoke immediately if a token leaks — and treat any token that has ever
appeared in a log, shell history, or ticket as leaked.
## Handling tokens safely [#handling-tokens-safely]
* Treat tokens like passwords: never commit them, never paste them into
chat or issue trackers.
* Pass them via environment variables or stdin (`initializ auth login --token-stdin`) so they stay out of shell history.
* Prefer expiring tokens and rotate before expiry; use one token per
pipeline so a leak has a small blast radius.
# Security events (https://docs.initializ.ai/docs/security/events)
Every deployed agent emits audit events as it runs: session lifecycle, tool
executions, network egress decisions, LLM calls, guardrail checks, and quota
denials. Workflow executions emit their own lifecycle events alongside the
events of every agent they dispatch. Build-time policy checks emit events too,
so a policy violation caught before deployment shows up in the same stream as
one caught at runtime. All of it lands in one unified event store with one
query path — the Events screen under **Security → Events**.
## Anatomy of an event [#anatomy-of-an-event]
Every event carries a common envelope plus an event-type-specific payload:
* **`event_type`** — what happened, named `_` (see below).
* **`ts`** and a producer **`seq`** — emit time plus a per-producer sequence
number. Timelines order by wall-clock time and use `seq` to break ties
within the same second.
* **Identity and correlation** — org, workspace, the emitting entity
(`entity_type` of `agent`, `workflow`, or `assistant` plus `entity_id`), the
**invocation** (one agent task) and, for workflow runs, the **execution**
that groups every agent's events for the run.
* **`outcome`** — one of `ok`, `allowed`, `denied`, `blocked`, `masked`,
`modified`, `cancelled`, `error`, or `info`. Lifecycle events that carry no
allow/deny semantic resolve to `info`.
* **`severity`** — `info`, `warning`, `blocking`, or `critical`.
* **`fields`** — the event-type-specific detail (for example, an
`llm_call` carries model, provider, and token counts; an `egress_blocked`
carries the blocked domain and the rule that matched).
## Event naming [#event-naming]
Event types follow the `_` convention: the prefix names the
entity or gate, the verb names what happened. Examples: `tool_exec`,
`egress_blocked`, `guardrail_check`, `workflow_started`,
`task_admission_denied`. The
prefix is meaningful — it encodes the altitude of the gate. `task_admission_denied`
is a per-task admission decision, distinct from per-tool or per-LLM-call gates
that may sit alongside it. The runtime's vocabulary grows over time; the
platform accepts and stores well-formed new types, and the console falls back
to the raw type name as the label until a friendly one exists.
## Notable event types [#notable-event-types]
| Event type | Meaning |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `session_start` / `session_end` | An agent session opened / closed. |
| `invocation_complete` / `invocation_cancelled` | An agent task finished / was cancelled. |
| `tool_exec` | A tool call started or returned (start and end phases). |
| `llm_call` / `llm_call_cancelled` | A model call returned / was cancelled. Carries model, provider, and input/output token counts. |
| `egress_allowed` / `egress_blocked` | An outbound network request was permitted / denied by the egress policy. |
| `guardrail_check` | A guardrail evaluated content; the decision (`allowed`, `masked`, `blocked`) becomes the outcome. |
| `channel_denied_by_policy` | A channel was refused by the effective policy. |
| `policy_violation_at_build_time` | A build-time policy check (egress, tools, channels) rejected an agent configuration. |
| `task_admission_denied` | A task was refused by a token quota. Fields carry `scope`, `window`, `reason`, `reset_at`, and `cached` (whether the deny was replayed from the runtime's local cache). |
| `auth_verify` / `auth_fail` | Inbound agent authentication succeeded / failed. |
| `auth_step_up_required` | A step-up authentication demand was raised. |
| `credential_issued` / `credential_revoked` / `credential_failed` | Credential lifecycle (metadata only — never the credential material). |
| `intent_alignment` / `intent_drift` | Intent alignment checks and detected drift. |
| `task_deferred` / `task_deferred_decision` / `task_deferred_timeout` | Deferred-task lifecycle. |
| `context_compressed` / `context_expanded` / `context_pattern_suggested` | Context-compression telemetry, including tokens saved per compression. |
| `policy_loaded` / `agent_card_published` / `audit_export_status` | Runtime lifecycle and audit-sink health (informational). |
| `workflow_started` / `workflow_step_started` / `workflow_step_completed` / `workflow_step_failed` / `workflow_complete` / `workflow_cancelled` | Workflow execution lifecycle, emitted with `entity_type` `workflow`. |
By default the Events screen filters to the **security-relevant** subset —
`egress_blocked`, `policy_violation_at_build_time`, `channel_denied_by_policy`,
`guardrail_check`, `auth_fail`, and `task_admission_denied` — so you see
enforcement signal rather than the full operational firehose. The filter is
adjustable when you need the rest.
## The Events screen [#the-events-screen]
**Security → Events** shows the stream scoped to your selected workspaces,
defaulting to the last 24 hours and the security-relevant event types.
* **Filtering** — by event type, outcome, agent, time range, and workspace
scope. A search box matches rule keys, domains, and tool names — this is
also where deep links from the Posture screen land, pre-seeded with the rule
you clicked.
* **Spike detection** — a banner flags time buckets where event volume spikes
well above baseline, so bursts of denials stand out before you scroll.
* **Grouping by run** — contiguous events from the same run are grouped, so a
single invocation reads as one collapsible unit instead of interleaved rows.
* **Event detail** — selecting a row opens a drawer with the full envelope and
the event-type-specific fields, including the decision that was made and the
policy attribution behind it.
## Pivoting to a full run [#pivoting-to-a-full-run]
From any event you can pivot to everything correlated with it:
* **Invocation timeline** — every event from one agent invocation, in order.
* **Execution timeline** — every event from every agent in one workflow
execution, ordered by wall-clock time with the producer sequence breaking
ties within the same second. This is the investigator's pivot from a single
suspicious event to "what else happened in that run" without leaving the
security console.
The same event stream also powers the Activity tab on each agent's detail page,
so builders and security reviewers look at the same records.
# Security (https://docs.initializ.ai/docs/security)
Every agent and workflow on the platform emits a stream of security-relevant
audit events — tool executions, network egress decisions, LLM calls, guardrail
checks, and quota denials. The Security area of the console is where you read
that stream, define the policies that produce the denials, watch enforcement
trends, and manage token spend budgets.
The model is layered:
* **Events** are the raw, per-invocation record of what agents did and what the
platform allowed, blocked, or masked.
* **Policies** (org-level and workspace-level) define what is denied, what is
allowed, which guardrails are required, and the numeric ceilings agents run
under. Publishing a policy propagates it to running agents.
* **Posture** rolls the event stream up into enforcement trends: block rates,
the rules doing the work, quota hits, and policy rules that never fire.
* **Usage and quotas** track token spend and executions, and let org admins set
windowed token budgets that gate agent invocations before they start.
The Security area also hosts the **Tool Registry** — the org-scoped catalog of
admitted tools that skills are allowed to reference; unregistered tool
references are rejected when a skill is saved and when an agent builds.
## Section map [#section-map]
# Policies (https://docs.initializ.ai/docs/security/policies)
Security policies are the platform's central governance surface: they define
what agents may not do (deny lists), what they are limited to (allow lists),
which guardrails they must run (required), and the numeric ceilings they
operate under (limits). Policies exist at two scopes — **org** and
**workspace** — and every agent runs under the combination of both.
## What a policy controls [#what-a-policy-controls]
A policy document has four blocks:
| Block | Contents | Combination rule across layers |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- |
| **Deny list** | Egress domains, tools, models (provider + name), channels, and denied command patterns | Union — any layer can forbid |
| **Allow list** | Egress domains, models, channels, regions | Intersection — every non-empty layer must permit |
| **Required** | Guardrails (each with a mode of `block`, `redact`, or `log_only` and a fail mode) plus a structured guardrails overlay (PII, moderation, security detection, custom rules, approval gates) | Union with mandatory injection — agents cannot decline a required guardrail |
| **Limits** | `max_egress_allowlist_size`, `max_tool_count`, `max_concurrent_invocations` | Smallest non-zero value wins; zero means no cap at that layer |
Two details worth calling out:
* **Denied command patterns** block shell commands across every tool call in
an invocation. Each entry is a regular expression with an optional
operator-facing deny message. Patterns are validated when you publish,
because the agent runtime fails closed on a bad pattern — an invalid regex
would stop agents from starting.
* **Required guardrails** are forced to fail-closed when required by org or
workspace policy, regardless of what the agent declares — required behavior
must not silently degrade.
An empty allow list at a layer means "no restriction from this layer", not
"allow nothing" — the intersection then falls through to the next layer that
does restrict.
## The effective policy [#the-effective-policy]
What an agent actually enforces is the **effective policy**: the org policy
and the workspace policy (and the agent's own declaration, where one exists)
resolved with the four combination rules above. The console shows the
effective view with **origin tags** on every entry — each deny entry, required
guardrail, and binding limit records which layer(s) put it there ("this rule
is here because of org policy"), so you never have to mentally re-run the
resolver. For denied command patterns, when the same pattern appears at more
than one layer, the org-level deny message takes precedence.
## Versions, history, and rollback [#versions-history-and-rollback]
Publishing a policy is versioned:
* Every publish increments the policy's version counter and stores an
immutable snapshot of the previous state.
* An audit trail records who changed what and when — actor, action (create,
update, rollback), from-version, to-version, and a diff summary.
* You can diff any two versions and **roll back** to an earlier version;
rollback is itself a new published version with its own audit entry.
## Who can edit [#who-can-edit]
| Policy scope | Who can publish |
| ---------------- | -------------------------------------------------- |
| Org policy | Org admin only |
| Workspace policy | Workspace admin of that workspace, or an org admin |
Everyone else sees policies read-only. The console enforces this in the editor
(the Edit control only appears for eligible roles) and the platform enforces
it again on every write, so the console gate is a convenience, not the
security boundary.
The org policy is edited under **Security → Policies**; workspace policies are
edited in each workspace's settings. The editor starts read-only — enter edit
mode, make changes, and publish. Policy templates are available as starting
points.
## How changes reach running agents [#how-changes-reach-running-agents]
Publishing a policy propagates the compiled **deny lists**, **caps**
(egress-allowlist size and tool count), and the **required-guardrails
overlay** to every workspace. Deployed agents enforce the propagated policy
through the platform policy their runtime loads — you do not redeploy agents
to pick up a deny-list change.
Propagation is asynchronous: after publishing, the Policies screen shows a
propagation status banner tracking the rollout across workspaces, so you can
confirm the new version has landed everywhere before relying on it.
Not everything travels on that path:
* **Allow lists and the concurrency limit** are enforced when agents are
configured, built, and deployed — build-time policy checks reject
configurations that violate them and emit `policy_violation_at_build_time`
events into the [event stream](/docs/security/events).
* **Token spend budgets** are separate from policy: they are enforced at task
admission, not propagated, and are managed under
[Usage and quotas](/docs/security/usage-and-quotas).
Because deny entries propagate to running agents while allow lists apply at
build and deploy time, a newly added deny rule takes effect quickly across the
fleet, but a loosened allow list only benefits agents at their next build or
deploy.
# Posture (https://docs.initializ.ai/docs/security/posture)
**Security → Posture** answers "is my policy actually doing anything, and
what is it doing?" It aggregates the security-relevant
[event stream](/docs/security/events) over a selected time window and turns it
into enforcement trends, with every number one click away from the underlying
events.
## Window and scope [#window-and-scope]
Posture shares its time-range presets with the Usage screen — last 1 hour,
24 hours, 7 days, or 30 days — and respects your workspace scope selection.
Every KPI is computed for the selected window **and** the preceding window of
equal length, so each figure carries a window-over-window delta.
Posture aggregates the most recent security-relevant events in the window (up
to 200 per window). On very high-volume orgs, treat the rollups as a
representative sample of recent enforcement rather than an exhaustive count —
and use the Events screen for exact investigation.
## What counts as a denial [#what-counts-as-a-denial]
A denial is any event whose outcome is `denied`, `blocked`, or `modified` — a
guardrail that modified the payload counts as a block, while `masked` is
treated as a soft outcome. Everything else in the window counts as allowed for
trend purposes.
Each denial is attributed to a rule key, in order of preference: the matched
rule id, then the declared domain (for egress denials), then a synthetic
`quota::` key for quota denials, and finally
`allowlist-default` for fail-closed denials that no named rule produced.
## What the screen shows [#what-the-screen-shows]
* **KPI strip** — total security-relevant events, denied, allowed, and the
block rate (denied / total), each with its delta versus the previous window.
* **Allowed-vs-denied trend** — bucketed over the window (5-minute buckets at
1 hour, hourly at 24 hours, coarser at 7 and 30 days) so enforcement bursts
are visible at a glance. A spike banner flags buckets far above baseline.
* **Top policy rules** — the five named rules with the most denials, labeled
with the dominant event type behind each. Quota keys are excluded here.
* **Top quota hits** — the five `quota::` keys with the most
admission denials, shown as "scope · window" (for example `agent · daily`).
Quota denials are kept **distinct from policy denials** so a strict token
budget doesn't sweep the policy table and mask real policy signal.
* **Top agents by denial** — the five agents with the most blocked events,
split into policy-blocked versus quota-blocked counts.
* **Dead-rule analysis** — named entries in the published org policy (deny and
allow list domains, tools, channels) that never fired in the window. These
are cleanup candidates: rules that cost review attention but produce no
enforcement signal. Limits and guardrails aren't part of this analysis —
they aren't rules that fire by name.
## Drilling into events [#drilling-into-events]
Every rollup row deep-links into **Security → Events** with the time window
and workspace scope preserved and the search box pre-seeded with the rule key,
domain, or tool you clicked — so the path from "this rule fired 40 times" to
the 40 actual events is one click. From there, each event opens into its
detail drawer and can pivot to the full invocation or workflow execution
timeline.
# Usage and quotas (https://docs.initializ.ai/docs/security/usage-and-quotas)
The **Usage** screen tracks what your agents spend; **token quotas** cap it.
Both are derived from the same audit event stream that powers
[Security events](/docs/security/events): token metrics come from each
`llm_call` event's input/output token counts, and executions count completed
invocations.
## The Usage screen [#the-usage-screen]
Usage is scoped by your workspace selection and a time-range preset — last
1 hour, 24 hours, 7 days (the default), or 30 days. Every figure is computed
for the selected window and the preceding window of equal length, so KPIs
carry window-over-window deltas.
* **KPI strip** — total tokens (input + output), executions (completed
invocations), average tokens per run, and active agents (agents that made
LLM calls in the window).
* **Trend chart** — hourly buckets of input tokens, output tokens, and
executions over the window.
* **Input/output split** — the balance of prompt versus completion spend.
* **Rollups** — top agents by tokens (shown by agent name, including deleted
agents so historical spend still resolves), per-workspace totals in the
org-wide view, and spend by provider and by model.
* **Compression savings** — tokens saved by context compression, by tool,
from the runtime's compression telemetry.
Rollup rows deep-link into Security Events with the same time range, so "which
agent burned 2M tokens" pivots directly to that agent's event stream. An
agent's detail page shows the same usage panel narrowed to that agent.
## Token quotas [#token-quotas]
Token quotas are windowed token budgets that gate agent work **before it
starts**. A quota is defined per scope, and each scope can carry up to three
windowed limits:
| Scope | Applies to |
| ----------- | ------------------------------ |
| `org` | All token spend across the org |
| `workspace` | All agents in one workspace |
| `agent` | One agent |
| Window | Resets |
| --------- | ---------------------------------- |
| `hourly` | At the top of each hour (UTC) |
| `daily` | At 00:00 UTC |
| `monthly` | On the 1st of the month, 00:00 UTC |
Windows are fixed (calendar-aligned), not rolling. A window left empty means
"no limit at this granularity from this scope" — evaluation falls through to
the next broader scope's limit, or admits if no scope sets one. A quota with
every window empty stores nothing and is rejected; delete the quota instead.
## What happens at admission [#what-happens-at-admission]
When an agent invocation starts, the platform evaluates the configured quotas
in most-restrictive-first order — **agent → workspace → org** — comparing each
scope's consumed tokens in the current window against its limit. The first
exhausted window denies.
On deny:
* The agent's task is **refused** — it does not run.
* The runtime emits a **`task_admission_denied`** audit event whose fields
carry the denying `scope`, the `window`, the `reason`, the `reset_at` time
when the window reopens, and `cached` (whether the deny was replayed from
the runtime's local decision cache rather than a fresh check).
* The [Posture screen](/docs/security/posture) surfaces these as **quota
hits**, deliberately kept distinct from policy denials.
Admission is checked once per invocation, not per LLM call. A task admitted
just under the limit runs to completion even if it crosses the budget mid-run.
Treat quotas as a circuit breaker on runaway spend, not a hard ceiling — size
them with that structural overshoot in mind.
## Managing quotas [#managing-quotas]
Only **org admins** can create, update, or delete token quotas — including
workspace- and agent-scoped ones. Token budgets are an org-wide control
surface; workspace admins manage their workspaces but do not set spend caps
for them. Anyone with access can view the configured limits.
The org-level quota is edited on the **Usage** screen; workspace-scoped
budgets are edited in workspace settings. Editors follow the console's
read-only-until-Edit convention, and the platform enforces the org-admin
requirement on every write regardless of what the console shows.
Note that token quotas are independent of security policies: they are enforced
at admission time and are **not** part of
[policy propagation](/docs/security/policies) — publishing a policy does not
touch quotas, and vice versa.
# Agents in workflows (https://docs.initializ.ai/docs/workflows/agents-in-workflows)
A workflow node can dispatch to two kinds of agents, and both appear in the
same picker when you build a pipeline.
## Platform-deployed agents [#platform-deployed-agents]
Agents built and deployed in the workspace join the picker under their
friendly name — but only while they are **deployed and running**. An agent
that exists but is not live cannot actually receive a dispatch, so it is
filtered out of the picker. Deploy the agent first, then add it to the
pipeline.
## External agents [#external-agents]
Agents running outside the platform can participate too, once they are
registered in the workspace with their endpoint and (optionally) a credential.
They appear in the picker suffixed with **(external)**, and the platform
attaches the registered credential on every dispatch to them. See
[External agents](/docs/agents/external-agents) for how registration works.
## When an agent is removed [#when-an-agent-is-removed]
Workflows keep a reference to each agent they dispatch to. If one of those
agents is deregistered, every workflow that references it is marked
**orphaned**:
* Orphaned workflows stay visible and editable in the list and detail pages —
nothing is deleted.
* Runs are **refused** with an explanatory error until the pipeline is fixed.
* The workflow reactivates automatically when either the pipeline is edited so
every node points at an available agent, or an agent with the same name is
registered again.
The console surfaces this state with an `orphaned` status chip and a banner on
the workflow detail page explaining how to recover. Conversely, an edit that
introduces an unknown agent orphans the workflow on save — the status always
reflects whether every node is currently resolvable.
Before removing an agent, check what depends on it: the platform exposes a
usage lookup listing the workflows that dispatch to a given agent, and the
console uses it as a delete preflight.
## Scheduled runs [#scheduled-runs]
Workflows support recurring execution. Choose a frequency when creating the
workflow (hourly, daily, weekly, or monthly), or add, change, and remove the
schedule later by updating the workflow — under the hood the schedule is a
cron expression with a time zone, so API clients can set any recurrence, not
just the console presets.
Behavior to know:
* Scheduled runs create ordinary executions — they appear in the executions
list and are monitored exactly like manual runs.
* The console presets fire at 09:00 UTC for daily, weekly (Monday), and
monthly (1st of the month); hourly fires on the hour.
* Removing the schedule (or deleting the workflow) removes the recurring
trigger; no further automatic runs start.
* An invalid cron expression is rejected at save time.
The workflows list shows each workflow's schedule (`manual` when none), so you
can see at a glance which ones run on their own.
# Workflows (https://docs.initializ.ai/docs/workflows)
A workflow is a multi-step pipeline of agents. Each step (node) dispatches to
one agent in your workspace; the output of one step can feed the input of the
next, so a single run can chain research, drafting, triage, or any sequence of
agent tasks into one execution.
Workflows live in a workspace, next to the agents they orchestrate. You can
build one by hand on the pipeline canvas, or describe a goal in plain language
and let the platform plan the steps and wiring for you. Once saved, a workflow
runs on demand from the console or on a recurring schedule, and every run is
recorded as an execution with per-step status, outputs, and runtime events.
## Key concepts [#key-concepts]
* **Pipeline** — the ordered set of nodes a workflow executes. Each node names
the agent it calls and the message it sends.
* **Input placeholders** — a node's message can reference run-time values:
`$userinput.` resolves from the inputs you provide when starting a run,
and `$.` resolves from an earlier step's output.
* **Execution** — one run of a workflow. Executions record inputs, per-step
status and output, errors, and the runtime events emitted by each agent.
* **Schedule** — an optional recurrence (hourly, daily, weekly, monthly). A
scheduled workflow runs automatically; an unscheduled one runs manually.
## In this section [#in-this-section]
# Planning a workflow (https://docs.initializ.ai/docs/workflows/planning-a-workflow)
The console creates workflows from a goal: you describe what you want to
happen, and the planner proposes a pipeline of agents from your workspace. The
proposal lands on an editable canvas, so you always review — and can fully
rework — the plan before saving.
Open **Build → Workflows** and click **Create workflow**. The screen has three
parts: the goal prompt, the pipeline canvas, and the name/schedule form.
Select a workspace from the Build picker first. The planner only composes
agents from the selected workspace, and the saved workflow belongs to it.
## Describe your goal [#describe-your-goal]
Type a goal in plain language — for example, "Summarize new support tickets
and draft replies" — and click **Generate workflow**. The planner looks at the
agents available in your workspace and returns a proposed pipeline: which
agents to call, in what order, and how each step's message is wired to user
inputs and to previous steps' outputs.
Two outcomes are possible:
* **A pipeline is generated** — the proposed nodes appear on the canvas below,
ready to edit.
* **No pipeline could be generated** — the planner returns a message
explaining why (for example, no suitable agents exist for the goal). You can
refine the goal and try again, or build the pipeline manually on the canvas.
If the planner backend is unreachable, the screen tells you so and manual
building still works — goal planning is a convenience, not a requirement.
## Edit the pipeline [#edit-the-pipeline]
The canvas is fully editable whether you started from a generated plan or from
scratch: add agents, remove nodes, drag to connect, and rewire the order. The
agent picker offers the workspace's deployed agents plus any registered
external agents (see
[Agents in workflows](/docs/workflows/agents-in-workflows)).
Each node's message can carry input placeholders that resolve at run time:
* `$userinput.` — a value the person (or schedule) starting the run
provides. Every distinct key becomes a required input field on the Run
panel.
* `$.` — a value from an earlier node's output, which is how data
flows from one step to the next.
A node can also carry its message values baked in, in which case the run needs
no input for that step.
## Name, schedule, and save [#name-schedule-and-save]
Below the canvas, give the workflow a name (required) and optionally a
schedule:
* **No schedule (manual run)** — the workflow only runs when someone starts it.
* **Hourly / Daily / Weekly / Monthly** — the platform creates a recurring
trigger that starts a run automatically (daily/weekly/monthly fire at 09:00
UTC; weekly on Monday, monthly on the 1st).
Click **Save workflow**. The workflow is created in the active state and the
console takes you to its detail page, where you can run it immediately. The
schedule can be changed or removed later by updating the workflow.
Saving does not run the workflow. Nothing executes until you start a run or
the schedule fires — see
[Running and monitoring](/docs/workflows/running-and-monitoring).
# Running and monitoring (https://docs.initializ.ai/docs/workflows/running-and-monitoring)
Every run of a workflow is recorded as an **execution**. Starting a run
returns immediately with an execution id — the pipeline itself executes
asynchronously — and the console drops you straight onto the execution page,
which refreshes itself while the run is in progress.
## Starting a run [#starting-a-run]
On the workflow detail page (**Build → Workflows → your workflow**), click
**Run**. What happens next depends on the pipeline's declared inputs:
* If the pipeline references `$userinput.` placeholders, the Run panel
opens with one field per key. All declared keys are required — running with
a missing key would send the literal unresolved placeholder to an agent, so
the console collects them first.
* If the pipeline declares no user inputs, the run starts immediately. An
optional panel still lets you pass extra fields as raw JSON if an agent
expects them.
* A **JSON** toggle on the panel lets you supply the whole input object by
hand for irregular shapes.
Scheduled workflows start runs the same way, automatically, at the configured
recurrence — those executions appear in the same list as manual ones.
A run is refused (with an explanatory error) when the workflow is not
active — most commonly because it is **orphaned**: an agent it dispatches to
was removed. See
[Agents in workflows](/docs/workflows/agents-in-workflows) for how to
recover.
## The executions list [#the-executions-list]
The workflow detail page lists all of its executions with started time,
status, completed time, and duration. Click any row to open the execution
page. Execution statuses you will see:
* **Running** — the pipeline is still dispatching steps.
* **Completed** — every step finished and the run closed normally.
* **Failed / error states** — a step errored; the run stops and the error is
recorded on the execution.
* **Onhold / aborted** — the run was held or cancelled before finishing.
## Inside an execution [#inside-an-execution]
The execution page shows the run end to end:
* **Header** — execution id, start/completion timestamps, and a live status
chip. While the run is in progress the page re-fetches automatically every
few seconds, so you can watch it without reloading.
* **Error banner** — if the run failed, the recorded error appears at the top.
* **Inputs** — the exact input object the run started with.
* **Agent timeline** — one row per pipeline step, in order. Each row shows the
agent, its status, its timestamp, its output (when the agent returned one),
and its error (when it failed). Because the execution snapshots its pipeline
at start, the timeline shows every step from the beginning: the currently
executing step pulses as **running**, steps not yet dispatched render as
**queued**, and finished steps carry their real reported status.
* **Runtime events** — the chronological audit trail emitted by every agent
during this run: tool calls, LLM calls, egress decisions, and denials, each
tagged with the emitting agent. This is the same event stream the Security
section reads, correlated to the run by execution id.
## Diagnosing failures [#diagnosing-failures]
When a run fails, work top-down:
1. Read the execution-level error banner — it names what stopped the run.
2. Find the first failed row in the agent timeline; its inline error message
is the agent's own report.
3. Check the runtime events around that timestamp — a blocked egress call, a
denied tool, or a failed LLM call is usually visible there.
4. If the failure was an unresolved input, re-run with the missing
`$userinput` key filled in; the placeholder substitution happens before any
step dispatches, so such runs fail immediately without touching an agent.
## Follow-up questions and file inputs [#follow-up-questions-and-file-inputs]
Two additional capabilities are available on the platform API:
* **Execution chat** — each execution keeps a conversation thread, so a
client can ask follow-up questions about a run's results and retrieve the
message history for that execution.
* **File uploads** — for workflows whose inputs include files, the API issues
short-lived upload URLs so files can be uploaded directly to storage and
referenced by the run.
Both are exposed to API clients; the console does not currently surface a
screen for them.
# Sharing (https://docs.initializ.ai/docs/workflows/sharing)
Workflows can be shared with other users by email address. Sharing gives the
recipient visibility into the workflow — the shared list they see resolves to
the live workflow definitions, so they always see the current version, and
workflows that are later deleted drop out of it automatically.
Sharing is currently an API capability: the endpoints below are live on the
platform, but the console does not yet expose a sharing screen.
## Share a workflow [#share-a-workflow]
A workflow is shared by its id, with a target email and the workspace it
belongs to. The platform enforces two checks before recording the share:
* The **sharer** must be a member of the workflow's workspace — you cannot
share out of a workspace you do not have access to.
* The workflow must exist in the organization.
Each share is a (workflow, email) pair. Sharing the same workflow with the
same email twice is detected and reported as already shared rather than
duplicated. Every successful share is recorded in the workspace activity feed
("workflow *name* shared by *user* with *email*"), so there is an audit trail
of who granted access.
## See who a workflow is shared with [#see-who-a-workflow-is-shared-with]
For any workflow, the platform returns the deduplicated list of email
addresses it has been shared with. Only users with access to the workflow's
workspace can query this list.
## Workflows shared with you [#workflows-shared-with-you]
The inverse lookup also exists: given an email address, the platform returns
all workflows shared with it. Shares pointing at workflows that no longer
exist (or were deleted) are silently skipped, so the result only contains
workflows the recipient can actually open.
## Revoke a share [#revoke-a-share]
Removing a share is done per (workflow, email) pair: the recipient's email is
removed from the workflow's share list and they no longer see it among their
shared workflows. Revoking does not touch the workflow itself or its
execution history.
# Approvals (https://docs.initializ.ai/docs/agents/runtime/approvals)
Some actions are legitimate but too risky to automate — deleting cloud
resources, running a destructive command, filing changes in an external
system. For these, the agent runtime supports deferred approval: the agent
pauses mid-task on a designated tool call, asks a human, and only proceeds
if the human approves.
## How an approval works [#how-an-approval-works]
Specific tools on an agent can be marked as requiring approval. When the
agent is about to call one of them:
1. The task is **paused** — not failed. Anyone checking the task's status
sees it in a `deferred` state.
2. A notification is delivered to the configured approver destination
(typically a Slack channel) describing what the agent wants to do —
the tool name and a summary of its arguments.
3. An approver decides:
* **Approve** — the tool runs and the task resumes as if it had never
paused. The conversation continues normally.
* **Reject** — the approver is prompted for a reason; the tool call
fails with that reason, and the task ends in a failed state.
* **No decision in time** — each approval has a timeout (minutes, not
hours). If it expires, the call is automatically denied and the task
fails. Silence never means yes.
Every step is captured as [audit events](/docs/agents/runtime/audit-events):
the pause, the decision (with the approver's identity and note), or the
timeout.
## Approving from Slack [#approving-from-slack]
When approvals are routed to a Slack channel the agent is connected to,
the notification arrives as an interactive message with **Approve** and
**Reject** buttons. Approving resolves the request immediately; rejecting
opens a short dialog asking for a justification, which is recorded with
the decision. After the decision, the message updates to show the outcome
and who made the call.
Unless a specific approver list is configured, anyone who can see the
message in the channel can decide. Treat the approval channel's
membership as a privileged grant: route approvals to a tightly scoped
private channel, not a broad one with guests and integrations.
For stricter control, an agent can carry an approver allowlist — a set of
email addresses that are the only identities allowed to resolve its
approvals. A decision from anyone else is refused and the request stays
pending for a listed approver. This fails closed: an approver whose
identity cannot be verified is treated as unauthorized.
## What users of the agent see [#what-users-of-the-agent-see]
From the requesting user's point of view, the agent simply takes longer on
that step. If they are chatting with the agent through a channel, the
conversation resumes seamlessly on approval. On rejection, the agent
receives the failure — including the approver's reason — and can explain
to the user why the action was not taken.
Approval windows are deliberately short. For conversations arriving
through a chat channel, the runtime holds the request open for a bounded
window (about six minutes); an approval that lands after the window is
too late and the step fails. Design approval flows for a responsive
on-call audience, not a queue reviewed hours later.
## When to use approvals [#when-to-use-approvals]
* Actions that are dangerous but sometimes correct — use an approval so a
human confirms the specific instance.
* Actions the agent should never take — do not use an approval; block them
outright with the agent's policies and guardrails.
* Auditability requirements — approvals attach a named human decision to
the action, which appears in the platform's
[Security area](/docs/security).
# Audit events (https://docs.initializ.ai/docs/agents/runtime/audit-events)
Everything security-relevant an agent does is recorded. The agent runtime
emits a structured audit event for each notable action — every tool call,
every allowed or blocked outbound request, every authentication decision,
every quota denial — and streams them to the platform, where they appear
in the [Security area](/docs/security) filtered by organization,
workspace, and agent.
## What gets recorded [#what-gets-recorded]
The audit stream covers the full lifecycle of agent activity:
* **Task lifecycle** — a session starting and ending, and each model call
with its token usage (the basis for usage and cost reporting).
* **Tool activity** — every tool the agent invokes, with timing and
input/output sizes.
* **Egress decisions** — each outbound request, allowed or blocked, with
the domain and the policy mode that decided it.
* **Policy and guardrail decisions** — content that was masked, warned
on, or blocked, and commands denied by organization-wide policy.
* **Approvals** — a paused tool call, the human decision (with approver
identity), or the timeout.
* **Admission denials** — requests turned away because a cost or usage
quota was exhausted at the agent, workspace, or organization level.
* **Authentication** — every inbound request accepted or rejected, and
by which identity.
Events are metadata by default: tool names, domains, durations, token
counts, sizes — not prompt text, tool arguments, or results. Payload
capture is a deliberate, per-agent opt-in for debugging or compliance
needs, with secret-shaped values redacted.
## Event naming [#event-naming]
Event types follow a `_` shape: the prefix names the thing
the event is about, the verb what happened to it. The prefix matters — it
encodes where in the pipeline the decision was made.
| Event | Meaning |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tool_exec` | The agent executed a tool |
| `egress_blocked` | An outbound request was stopped by the egress allowlist |
| `egress_allowed` | An outbound request passed the egress allowlist |
| `task_admission_denied` | A new task was refused before execution because a quota (cost or token limit) was exhausted — with the scope, the window (hourly, daily, monthly), and when it resets |
| `task_deferred` | A tool call was paused for [human approval](/docs/agents/runtime/approvals) |
| `guardrail_check` | A guardrail masked, warned on, or blocked content |
| `llm_call` | A model call completed, with token usage |
For example, `task_admission_denied` is distinct from a per-tool or
per-call denial: the `task_` prefix tells you the gate fired before any
work started, not midway through a tool.
## Correlation and attribution [#correlation-and-attribution]
Every event carries identifiers that make the stream navigable:
* A **correlation ID** groups all events of one invocation — the
authentication, the model calls, the tool calls, and the completion
form a single timeline.
* **Sequence numbers** within an invocation let consumers detect missing
or reordered events.
* **Workflow identifiers** tag events produced during a
[workflow](/docs/workflows) run, so cost and activity roll up to the
specific workflow, stage, and step that caused them.
* **Tenancy fields** stamp each event with the organization and
workspace the agent is deployed in.
Events are also chained — each one carries a hash of the previous one —
so gaps or tampering in the stream are detectable.
## Where events surface [#where-events-surface]
Agents publish their audit stream to the platform, and the
[Security area](/docs/security) is where you consume it: browse and
filter security events, see posture rollups such as top quota hits and
policy denials, and review usage derived from the token counts on model
call events. You do not need to access an agent's logs directly — the
platform view is the operational surface.
# Egress control (https://docs.initializ.ai/docs/agents/runtime/egress-control)
An agent that can call any tool can, in principle, send data anywhere. The
agent runtime closes that risk with egress control: by default a deployed
agent has **no outbound network access at all**, and every external host
it may reach must be on its allowlist.
## Deny-all by default [#deny-all-by-default]
Each agent carries its own egress policy, fixed at build time. The default
posture is deny-all: no outbound connections except localhost. From there,
the platform builds the agent's allowlist from what the agent actually
needs:
* **Explicit domains** you configure for the agent.
* **Skill and tool requirements** — a skill or tool that declares the API
hosts it talks to gets those domains added automatically.
* **Platform services** — the model gateway, channel platforms (for
example Slack), and the platform's own verification endpoints are
included so the agent can function.
Allowlist entries match exactly (`api.example.com`) or by wildcard
(`*.example.com` matches subdomains). Anything not matched is blocked.
## Layers of enforcement [#layers-of-enforcement]
The same allowlist is enforced at several levels, so there is no gap
between what the agent's code does and what its scripts or subprocesses
do:
* **In-process enforcement** — every HTTP request made by the agent's own
tools (such as `http_request` or `web_search`) is checked against the
allowlist before it leaves the process.
* **Subprocess enforcement** — skill scripts and approved command-line
binaries (for example `curl`) are routed through a local proxy that
applies the same allowlist rules.
* **Network-level enforcement** — in the agent's deployment environment, a
network policy generated from the same allowlist restricts traffic at
the infrastructure level, backstopping the in-process controls.
Beyond domain matching, the runtime defends against common bypass
techniques: disguised IP address formats are rejected, DNS answers are
re-validated before connecting (preventing DNS-rebinding tricks), cloud
metadata addresses are always blocked, and credentials are stripped when a
request is redirected to a different origin.
## What happens on a blocked call [#what-happens-on-a-blocked-call]
When the agent (or one of its scripts) tries to reach a host that is not
allowlisted:
* The request fails immediately with a clear "egress blocked" error naming
the domain — the connection is never attempted.
* The agent sees the failure as a tool error and can report it or try a
different approach; it cannot retry its way around the policy.
* An `egress_blocked` [audit event](/docs/agents/runtime/audit-events) is
emitted with the blocked domain, and it surfaces in the platform's
[Security area](/docs/security) so operators can see exactly which agent
tried to reach what, and when.
Allowed calls are recorded too (as `egress_allowed` events), giving a
complete picture of an agent's outbound behavior.
If an agent legitimately needs a new external API, the fix is to add the
domain to the agent's configuration (or use a skill that declares it)
and redeploy — the allowlist is part of the agent, not a runtime toggle.
# Agent runtime (https://docs.initializ.ai/docs/agents/runtime)
Every agent you deploy on the platform is a self-contained service. The
build process compiles your agent's instructions, skills, tools, channel
connections, and security policy into a single container image, and a
shared agent runtime executes all of it. You never operate the runtime
directly — the console and CLI manage it for you — but understanding what
it does helps you reason about what your agents can and cannot do.
## What the runtime provides [#what-the-runtime-provides]
When an agent receives a request (from a user, a channel like Slack, or a
workflow step), the runtime drives an LLM-powered loop: it presents the
agent's available tools to the model, executes the tool calls the model
makes, feeds results back, and returns the final response. Around that
loop it enforces the controls you configure on the platform:
* **Skills and tools** define what the agent is capable of doing.
* **Egress control** restricts which external hosts the agent may reach —
deny-all by default.
* **Approvals** can pause sensitive tool calls until a human approves them.
* **Memory** keeps multi-turn conversations coherent and can persist
knowledge across sessions.
* **Scheduling** runs recurring tasks without a user prompting the agent.
* **Audit events** record everything security-relevant the agent does and
stream it to the platform's [Security area](/docs/security).
Because all of this is baked into the agent at build time, two agents in
the same workspace can have completely different capabilities and network
permissions — each agent's policy travels with it.
## In this section [#in-this-section]
# Memory and scheduling (https://docs.initializ.ai/docs/agents/runtime/memory-and-scheduling)
Two runtime capabilities make agents useful beyond single questions:
memory, which keeps conversations coherent and lets agents accumulate
knowledge, and scheduling, which lets agents run recurring work without
anyone prompting them.
## Conversation sessions [#conversation-sessions]
Every conversation with an agent is a session. The runtime persists
session state automatically, so a multi-turn exchange — over chat, a
channel like Slack, or a workflow — picks up where it left off, even
across agent restarts or multiple replicas of the same agent.
Two housekeeping behaviors are worth knowing:
* **Sessions expire when idle.** A session untouched for a while (about
30 minutes by default) is discarded, and the next message starts fresh.
This is deliberate: it prevents a session polluted by accumulated
errors from degrading the agent indefinitely.
* **Long conversations are compacted.** When a conversation approaches
the model's context limit, the runtime summarizes the oldest half of
the exchange and continues with the summary in place of the raw
messages. The agent keeps the gist of earlier turns without hitting a
hard wall.
## Long-term memory [#long-term-memory]
Optionally, an agent can be given long-term memory that persists across
sessions. When enabled:
* Knowledge distilled during conversations (including content flushed
during compaction) is written to the agent's memory store.
* The agent gains `memory_search` and `memory_get` tools, letting it
recall relevant facts from past sessions using combined semantic and
keyword search, with newer memories weighted above older ones.
This turns an agent from a stateless responder into one that improves its
context over time — for example, remembering the conventions of a system
it has triaged before.
## Scheduled runs [#scheduled-runs]
Agents can execute tasks on a recurring schedule — a daily report, an
hourly check, a weekly summary. A schedule pairs a cron-style expression
(`@daily`, `@hourly`, `every 15 minutes`) with a task prompt, and
optionally a delivery destination so results post to a channel like Slack
or Telegram when the run completes.
Schedules come from two places:
* **Configuration** — defined when the agent is set up, as part of its
deployment.
* **The agent itself** — agents have built-in schedule tools, so a user
can say "check this every morning and post the result here" in a
conversation, and the agent creates the schedule, capturing the current
channel as the delivery target. Agents can also list and remove the
schedules they created (configured schedules cannot be deleted by the
agent).
## Scheduling behavior [#scheduling-behavior]
* **No overlap** — if a run is still in progress when the next trigger
fires, the new run is skipped rather than stacked.
* **Durability** — in platform deployments, schedules are backed by the
cluster's native job scheduling, so they survive agent restarts.
* **Traceability** — every fire, completion, and skip is emitted as an
[audit event](/docs/agents/runtime/audit-events) (for example
`schedule_fire` and `schedule_complete`), so scheduled activity is as
observable as user-driven activity.
Scheduled runs execute under the same security policy as everything
else the agent does — the egress allowlist, guardrails, and quota
checks all apply. A schedule is not a bypass.
# Skills and tools (https://docs.initializ.ai/docs/agents/runtime/skills-and-tools)
Tools are the individual actions an agent can take — make an HTTP request,
search the web, read a file. Skills are the layer above: a skill packages
instructions, one or more tools, and optionally executable scripts into a
reusable capability you attach to an agent.
## What a skill is [#what-a-skill-is]
A skill bundles three things:
* **Instructions** — a description of what the skill does, when it should
fire, and how the agent should carry out the task (steps, output format,
safety constraints).
* **Tool definitions** — the named actions the skill exposes, each with a
description of its inputs and outputs.
* **Optional scripts** — executable code that backs the skill's tools.
Script-backed tools become real, directly callable tools; skills without
scripts contribute their full instructions to the agent's system prompt
instead, guiding how the agent uses the tools it already has.
A skill also declares its requirements — the external hosts it needs to
reach and the credentials it needs — so the platform can wire up egress
permissions and secrets automatically when you attach the skill to an
agent. You pick skills from the platform's skill catalog or create your
own in the console; see [Agents](/docs/agents) for the authoring flow.
## Built-in tools [#built-in-tools]
Every deployed agent ships with a core set of tools, independent of which
skills you attach. The most important ones:
| Tool | Purpose |
| -------------------------------------------------- | ---------------------------------------------------------------- |
| `http_request` | Call external HTTP APIs (subject to egress control) |
| `web_search` | Search the web for recent information |
| `web_fetch` | Fetch a web page and read its content as clean text |
| `json_parse`, `csv_parse` | Parse structured data |
| `math_calculate`, `datetime_now`, `uuid_generate` | Small utility operations |
| `file_read`, `file_write`, `file_edit` | Work with files in the agent's own working directory |
| `file_create` | Produce a downloadable file and deliver it to the user's channel |
| `read_skill` | Load the full instructions of an attached skill on demand |
| `schedule_set`, `schedule_list`, `schedule_delete` | Manage the agent's own recurring schedules |
| `memory_search`, `memory_get` | Recall long-term memory (when enabled) |
File tools are confined to the agent's working directory — path traversal
outside it is rejected — and every network-touching tool goes through the
agent's [egress allowlist](/docs/agents/runtime/egress-control).
## Custom and integration tools [#custom-and-integration-tools]
Beyond the built-ins, an agent's tool set can grow in three ways:
* **Skill tools** — each script-backed tool a skill defines is registered
as a first-class tool under its own name, alongside the built-ins.
* **Integration adapters** — webhook and OpenAPI adapters turn external
service endpoints into callable tools, and connected MCP servers
contribute their tools automatically under a per-server namespace.
* **Command execution** — a hardened command tool can run a pre-approved
list of binaries (for example `git` or `kubectl`) with no shell, strict
argument validation, and isolated environment variables. Only binaries
explicitly allowed for that agent can run.
Development-only tools (local shells, debug consoles) exist for testing
but are stripped from production agent builds automatically. A deployed
agent only carries the tools it was configured with.
## How the agent chooses tools [#how-the-agent-chooses-tools]
The runtime advertises the agent's tools to the model with their
descriptions and input schemas, and the model decides which to call turn
by turn. Skills add a routing layer on top:
1. Attached skills are listed to the agent in a catalog of names and
descriptions.
2. When a request matches a skill's description, the agent loads that
skill's full instructions and follows them — preferring the skill over
its own default behavior.
3. If no skill matches, the agent answers using its base instructions and
built-in tools.
This is why a skill's description matters: it is the trigger the agent
matches against. A description that states *when* the skill applies ("when
the user asks for a weather forecast…") routes far more reliably than a
bare label ("weather skill").
Every tool call the agent makes is recorded as an
[audit event](/docs/agents/runtime/audit-events), and sensitive tools can
be gated behind [human approval](/docs/agents/runtime/approvals).