Skip to Content
Agent computeDeploy an agent
Raw

Deploy an agent to Aetherfy

This tutorial takes you from an empty directory to a deployed Aetherfy agent that answers HTTP requests, then shows you its logs. It uses the afy CLI throughout and asks you to make no design decisions along the way.

You need the afy CLI installed before you start. Installation instructions are on /cli.

Get an Aetherfy API key

Create an API key at https://app.aetherfy.com/dashboard/settings/api-keys . Keys look like afy_live_xxxxx. Copy it when it is shown.

The Aetherfy CLI reads your key from its stored login, and it also honours the AETHERFY_API_KEY environment variable if one is set.

Sign in to Aetherfy with afy login

Run afy login and paste the key when prompted:

afy login

For CI or any non-interactive shell, pass the key directly:

afy login --api-key afy_live_xxxxx

Confirm the CLI is talking to your Aetherfy account:

afy whoami

Create the agent’s files for Aetherfy

Make a directory and add three files. This example is a service agent — a long-lived HTTP server — written with the Python standard library only, so there is nothing to install and nothing that can break during the build.

mkdir hello-agent cd hello-agent

aetherfy.yaml — the configuration Aetherfy reads. It must sit at the root of the directory you deploy:

name: hello-agent runtime: python3.12 type: service memory_mb: 256

Write the runtime version in full. runtime: python is not valid on Aetherfy and fails the deploy; the Python values Aetherfy accepts are python3.11, python3.12, and python3.13.

main.py — the entrypoint. main.py is the default entrypoint for every python3.* runtime on Aetherfy, so you do not need to declare it. A service agent must listen on port 8080, and Aetherfy health-checks it with GET /health on that port:

"""A minimal Aetherfy service agent: answers HTTP requests on port 8080.""" import json import os from http.server import BaseHTTPRequestHandler, HTTPServer PORT = 8080 class Handler(BaseHTTPRequestHandler): def do_GET(self): if self.path == "/health": self._respond({"status": "ok"}) return self._respond( { "message": "hello from Aetherfy", "agent": os.environ.get("AETHERFY_AGENT_NAME", "unknown"), "region": os.environ.get("AETHERFY_REGION", "unknown"), } ) def _respond(self, body): payload = json.dumps(body).encode("utf-8") self.send_response(200) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(payload))) self.end_headers() self.wfile.write(payload) def log_message(self, fmt, *args): # Anything printed to stdout becomes this agent's logs on Aetherfy. print(fmt % args, flush=True) if __name__ == "__main__": print(f"hello-agent listening on 0.0.0.0:{PORT}", flush=True) HTTPServer(("0.0.0.0", PORT), Handler).serve_forever()

requirements.txt — present but empty, because this example imports only the standard library. Aetherfy installs from it if it lists anything:

# No third-party dependencies: this agent uses the Python standard library only.

Letting afy init write the configuration instead

afy init inspects a directory, detects the project type, and generates aetherfy.yaml for you. Every prompt it asks has a matching flag — --name, --runtime, --entrypoint, --type, --region, --memory, --keep-alive, --workspace, and --schedule — and -y / --yes accepts all defaults, which makes it usable in CI:

afy init --name hello-agent --runtime python3.12 --type service --yes

-f / --force overwrites an existing aetherfy.yaml. Note that -y does not imply --force, so afy init -y will not clobber a file you already have.

Deploy the agent to Aetherfy

From inside the directory, run:

afy deploy

afy deploy uploads the current directory, builds an image, launches machines, waits for completion, and streams status as it goes. It prompts once to confirm cost before it starts.

The name: field in aetherfy.yaml is what this deploy targets. With no --agent flag, Aetherfy’s CLI reads name from the file — hello-agent here — and that is the agent the deploy goes to, and the name the agent is created under on this first run. If you pass neither, the command stops with Agent name not found. Use --agent flag or set 'name' in aetherfy.yaml. Changing name later retargets the deploy at a different agent rather than renaming this one; renaming is afy agents rename.

Useful flags on the Aetherfy deploy command:

FlagEffect
--detach / -dReturn as soon as the upload finishes instead of waiting
--agent / -aDeploy to a named agent, overriding the name in aetherfy.yaml
--yes / -ySkip the cost confirmation prompt

Aetherfy does not upload everything in the directory. Files matching .afyignore are excluded, along with built-in defaults including .git, .env, __pycache__, node_modules, venv, .DS_Store, and *.log.

Confirm the Aetherfy agent is running

When the deploy finishes, the deployment reaches the active state and the agent’s status becomes running. Check it from the CLI:

afy agents list

You can see the same thing in the dashboard at https://app.aetherfy.com/dashboard/agents .

If the deploy failed instead, the deployment ends in the failed state and the error is recorded against it. List the history with afy deployments hello-agent to read the failure, and see /agents/runs-and-logs for what each state means.

Read the Aetherfy agent’s logs

Everything your program writes to stdout and stderr becomes the agent’s logs on Aetherfy. The startup line from main.py above appears here:

afy logs hello-agent

Follow the logs as they arrive:

afy logs hello-agent --follow

Show more history, or narrow to a time window and a severity:

afy logs hello-agent --tail 200 --since 1h --level ERROR,WARN

Aetherfy retains logs for 7 days. The full flag list, the per-line and volume caps, and the dropped-line marker are documented on /agents/runs-and-logs.

Preview a change before deploying it to Aetherfy

Aetherfy applies aetherfy.yaml as a merge patch, so fields you leave out keep their existing values rather than resetting. Before a deploy you are unsure about, preview exactly what would change and what would be preserved:

afy agents diff hello-agent

afy agents diff exits non-zero when there are changes, which makes it usable as a CI gate that fails a pipeline on unintended configuration drift.

What to do next with Aetherfy

Next stepPage
Every configuration field and the merge-patch rules/agents/aetherfy-yaml
Turn this into a run-once task on a schedule/agents/scheduled-tasks
How a task reads input, exits, and is retried (it is not)/agents/task-contract
Give the agent API keys and other secrets/agents/secrets
Deploy automatically on every push/agents/github
The rest of the Aetherfy CLI surface/cli/agents
Last updated on