Skip to Content
CLIafy deploy & deployments
Raw

afy init, deploy, deployments, redeploy, and rollback

The Aetherfy deployment commands

Five Aetherfy CLI commands cover the path from an empty directory to a running agent and back again.

CommandPurpose
afy init [path]Scan a directory and generate aetherfy.yaml
afy deploy [path]Upload the code, build an image, and deploy it
afy deployments <agent>List the agent’s deployment history
afy redeploy <agent> [version]Rebuild a version from its stored source, with current secrets
afy rollback <agent> [version]Re-deploy a previously built version

A first deployment on Aetherfy is normally two commands:

afy init afy deploy

Generating an Aetherfy manifest with afy init

afy init [path] scans a directory, detects the runtime and entrypoint, and writes an aetherfy.yaml manifest. The path argument is optional and defaults to ..

FlagShortTypeDefaultDescription
--namestringemptyAgent name (skips prompt)
--runtimestringemptyRuntime: python3.11, python3.12, python3.13, node20, node22, node20-ts, node22-ts, bun, dockerfile (skips prompt)
--entrypointstringemptyEntrypoint file, e.g. main.py or index.js (skips prompt)
--typestringemptyAgent type: service or job (skips prompt)
--regionstringemptyRegion: us-east-1, eu-central-1, ap-southeast-1 (skips prompt)
--memoryint0Memory in MB: 256, 512, 1024 (skips prompt)
--keep-aliveboolfalseEnable always-on billing (skips billing prompt)
--workspaceboolfalseEnable VectorDB workspace (skips workspace prompt)
--force-fboolfalseOverwrite existing aetherfy.yaml without asking
--yes-yboolfalseAccept every prompt’s default (non-interactive)
--schedulestringemptySchedule — runs the agent as a scheduled task on a 5-field cron expression in UTC, min every 5 minutes, e.g. '0 3 * * *'

Interactive by default; any flag above skips its prompt.

Two flags in that table read as if they take a value and do not. --workspace is a boolean toggle that answers the “enable a vector workspace?” prompt — it does not accept a workspace name, and afy init --workspace research will read research as the path argument. The workspace an agent joins is named by the workspace: key in aetherfy.yaml, or set later with afy update <name> --workspace <ws>. --keep-alive is the same shape.

The --memory help text lists the three values the prompt offers, not the whole allowed set. memory_mb in the manifest accepts 256, 512, 1024, 2048 and 8192, each still bounded by your plan’s maximum — see the aetherfy.yaml reference and /platform/limits.

# Interactive afy init # Fully specified, non-interactive afy init ./services/scraper \ --name catalogue-scraper \ --runtime python3.12 \ --entrypoint main.py \ --type job \ --region eu-central-1 \ --memory 512 \ --schedule '0 3 * * *' \ --yes

Behaviour of the two boolean shortcuts in the Aetherfy CLI:

FlagEffect
--yes / -yAccepts every prompt’s default. It does not imply --force.
--force / -fOverwrites an existing aetherfy.yaml. Required even alongside -y.

The non-interactive defaults Aetherfy applies under --yes:

SettingDefault
NameThe directory name
Typeservice
Regionus-east-1
Memory256 MB
Always-on billingOff
RuntimeDetected — afy init --yes fails if the runtime cannot be detected

The schedule prompt appears for either type in interactive mode. The resulting schedule: key is what makes the agent a scheduled task; see /agents/scheduled-tasks and the full manifest reference at /agents/aetherfy-yaml.

Deploying to Aetherfy with afy deploy

afy deploy [path] validates the manifest, archives the directory, uploads it to Aetherfy, builds an image, and deploys it. The path argument is optional and defaults to ..

FlagShortTypeDefaultDescription
--detach-dboolfalseReturn immediately after upload without waiting for completion
--agent-astringemptyAgent ID or name (reads from aetherfy.yaml if not specified)
--from-githubstringemptyDeploy from a public GitHub repo: owner/repo[@ref]
--yes-yboolfalseSkip the overage confirmation prompt and proceed (non-interactive)
--createboolfalseCreate the agent from aetherfy.yaml’s type and runtime if it does not exist. Required to create without a terminal; --yes never implies it
# Deploy the current directory afy deploy # Deploy a subdirectory, non-interactively, in CI afy deploy ./services/scraper --yes # Upload and return immediately afy deploy --detach # Target an agent explicitly afy deploy --agent catalogue-scraper # Create the agent if it does not exist yet, then deploy into it afy deploy --create

The order of operations is: validate aetherfy.yaml, archive the project directory as a gzipped tarball, upload, build the image, deploy.

afy deploy is one of the Aetherfy commands that exits 1 on failure, so it is safe to rely on its status in a pipeline. That includes a deployment that fails after the upload, and a wait that runs out before the deployment finishes; afy redeploy and afy rollback exit the same way.

Deploying to an Aetherfy agent that does not exist yet

A deploy whose target agent has no record on Aetherfy answers [404] ... (AGENT_NOT_FOUND). Rather than stopping there, afy deploy can create the agent and continue into it — but only with consent, which it takes one of exactly two ways.

ContextBehaviour
Terminal, no --yes, no --createAsks Agent '<name>' doesn't exist. Create it as <type>/<runtime> (from aetherfy.yaml)? [y/N], defaulting to No
--createThe flag is the consent. Creates without asking, in a terminal or not
No terminal, or --yes present, without --createNever asks and never creates. The deploy fails with AGENT_NOT_FOUND

--yes and --create are separate consents and neither implies the other: --yes answers the overage cost prompt, --create answers the missing-agent question. A CI deploy of a brand-new agent always needs --create, and needs --yes as well whenever the deploy would cross the plan allowance — which is why the CI recommendation below is to pass --yes unconditionally.

The type and runtime the agent is created with come from aetherfy.yaml and are never inferred. A manifest missing either key, or carrying a type: that is neither service nor job, is refused with a message naming the key to add — the deploy does not fall back to a default. A --agent value in UUID form is also refused: it names a record that is expected to exist, so the CLI will not create an agent named after an ID.

The agent is created with the same POST /agents that afy create issues, so creating up front and consenting mid-deploy produce the same record. Note that on the create path the archive is uploaded twice — once for the attempt that discovers the agent is missing, and once for the deploy that follows the create.

Files excluded from an Aetherfy deploy archive

The archive respects a .afyignore file in the project directory. On top of whatever it contains, the Aetherfy CLI always excludes these built-in defaults:

Pattern
.git
.gitignore
.env
.env.*
__pycache__
*.pyc
*.pyo
.pytest_cache
.mypy_cache
node_modules
.npm
venv
.venv
env
.DS_Store
Thumbs.db
*.log
.afyignore

Because .env and .env.* are excluded unconditionally, environment values must reach the agent as Aetherfy secrets rather than as files — see /cli/secrets.

An example .afyignore:

tests/ fixtures/ *.ipynb docs/

Deploying to Aetherfy directly from a public GitHub repository

--from-github owner/repo[@ref] deploys from a public GitHub repository without a local clone.

afy deploy --from-github myorg/my-agent afy deploy --from-github myorg/[email protected] afy deploy --from-github myorg/my-agent@8f2c1b0d9e4a7c3f5b1d6e8a0c2f4b6d8e0a2c4f
DetailValue
Ref defaultmain
Accepted refsBranch, tag, or a full 40-character commit SHA
Local requirementgit must be installed locally
Repository visibilityPublic only

For private repositories and push-triggered deploys, use the Aetherfy GitHub App instead — see /cli/github.

Aetherfy plan overage confirmation on deploy

If a deployment would push your account’s usage beyond the plan allowance, the Aetherfy CLI asks for confirmation before proceeding.

  • --yes accepts the prompt and proceeds non-interactively.
  • Without --yes in a non-interactive shell the command fails and tells you to re-run with --yes.

CI pipelines that deploy to Aetherfy should therefore always pass --yes:

export AETHERFY_API_KEY=afy_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx afy deploy --yes

Plan allowances are documented at /platform/limits.

Aetherfy runs one deployment per agent at a time. Starting a second while the first is still building or deploying returns HTTP 409 DEPLOYMENT_IN_PROGRESS. This is worth handling in CI, where two pushes in quick succession are the normal way to hit it: wait for the first to reach a terminal state, or cancel it with afy cancel <agent> before starting another.

Partially successful multi-region Aetherfy deployments

A deployment that succeeds in some regions and not others is reported by the Aetherfy CLI as:

Deployment is serving but DEGRADED — N/M regions ready.

The agent is serving traffic from the regions that came up. Check afy status <name> for the per-region detail, and afy logs <name> for the failure reason in the regions that did not.

Listing Aetherfy deployment history

afy deployments <agent> lists the agent’s deployments, newest first. It takes one required argument and has no flags of its own; it honours the global -o json.

afy deployments catalogue-scraper afy deployments catalogue-scraper -o json
ColumnMeaning
VersionThe version number — the value you pass to afy rollback
StateDeployment state, with a glyph
ReleaseOn a run, the version of the release it executed — which is not the run’s own Version. A dash on a release
CreatedWhen the deployment was created
ErrorFailure reason, when there is one

State glyphs used by the Aetherfy CLI:

GlyphState
●active
✗failed
○superseded
·queued
⟳building
⟳deploying
↩rolled_back

When the newest deployment failed, the Aetherfy CLI prints a suggested rollback command underneath the table, and — when the build stage is what failed — the build output under a Build output: heading. That block is the tail of what the failing step printed, so it says which step failed rather than repeating the short reason in the Error column. afy deploy prints the same block when a deploy it is watching fails.

Nothing is printed when the deployment failed somewhere other than the build — a region that never came up, or a cancellation — because there is no build output to quote.

Rolling back an Aetherfy deployment

afy rollback <agent> [version] re-deploys a previously built version.

FlagShortTypeDefaultDescription
--detach-dboolfalseReturn immediately without waiting for completion

Called with only the agent name, it prints the deployment history so you can choose a version:

afy rollback catalogue-scraper

Called with a version, it rolls back to it:

afy rollback catalogue-scraper 3

The version is a bare integer. afy rollback catalogue-scraper v3 is rejected by the Aetherfy CLI with Version must be a positive integer.

PropertyBehaviour
Build stepSkipped — the target version’s already-built image is re-deployed directly
Valid targetsA version whose image, or whose code archive, is still stored: active, superseded and rolled_back versions, and a failed one that got as far as an image (it failed while launching or in its health check)
Invalid targetsA failed build, which has neither. No rollback is accepted while a deployment is queued, building or deploying

Because the build is skipped, a rollback on Aetherfy is substantially faster than a fresh afy deploy of the same code.

Redeploying an Aetherfy agent to apply secrets

afy redeploy <agent> [version] re-runs a version’s build from the source archive Aetherfy stored for it.

FlagShortTypeDefaultDescription
--detach-dboolfalseReturn immediately without waiting for completion

This is the CLI counterpart of the dashboard’s Redeploy button, and it is not a rollback. Aetherfy injects secrets while the machine is built, so a secret you store with afy secrets set reaches a running service only on its next build. Rollback re-deploys an existing image and cannot apply one; redeploy rebuilds and does.

Called with only the agent name, it rebuilds the active deployment — the one whose environment a newly stored secret is missing from:

afy redeploy catalogue-scraper

Called with a version, it rebuilds that version instead:

afy redeploy catalogue-scraper 3

As with afy rollback, the version is a bare integer.

PropertyBehaviour
Build stepRuns — that is what injects current secrets
ConfigurationUnchanged; the archive is not re-read for memory, regions or any other setting
Valid targetsVersions whose stored source archive still exists
Archive retentionThe ten most recent successful deployments; a failed build’s archive is deleted

afy redeploy is not a retry for a failed build. Aetherfy deletes the code archive as soon as a build fails, so nothing remains to rebuild — and re-running the same build would fail the same way. Fix the code and run afy deploy again, or push to the linked repository. A deployment that built successfully but failed to launch keeps its archive, so that one can be redeployed.

A type: job agent needs no redeploy to pick up a new secret, but not because every run is a new machine — a task agent reuses its machine between runs. Aetherfy records which secret set each machine was created from, and refuses to send a run to a machine whose set no longer matches; it creates a current machine for that run instead. The value is applied, at the price of a cold start on every run until you redeploy. Services keep their environment until they are rebuilt, which is what this command does.

Last updated on