Agent CLI
The agent CLI ships with the AIMO agent image and Python package. It registers a new agent, runs the long-lived start worker that receives jobs, and manages database connections (encrypted at rest via the AIMO API, or kept in the agent process alone).
Typical invocation: python -m aimo.agent.cli inside the agent container. With the backend package installed and console scripts enabled, the same entry point is available as aimo-credentials.
Registration tokens and aimo_agent.sh are described in Registration.
Requirements
- The image for your environment. Each AIMO environment publishes its own agent image (
rg.nl-ams.scw.cloud/aimo/agent:latestfor production,…/aimo/agent-dev:latestfor the dev environment), built together with that environment's server and preset with its host and TLS mode. The web UI's commands and theaimo_agent.shthatregisterwrites name the right one;AIMO_AGENT_IMAGE_REFis that name as the image knows it (shown in upgrade instructions). - Pinning a build.
:latestalways points at the build published together with the currently deployed server. Every build is also kept under an immutable tagp<protocol>-<yyyymmdd>-<sha>(for examplep1-20260914-5c0f879): thepnumber is the agent protocol the server requires an exact match on, so only same-ptags are interchangeable, and the date orders them. To run a fixed build, exportAIMO_AGENT_IMAGE=<image>:<tag>before./aimo_agent.sh start; no need to edit the script. When the server refuses an agent whose protocol it no longer speaks, its message names the protocol version it requires; pull the current image and restart. Each image reports the tag it was built as (AIMO_AGENT_BUILD) to the server at connect, and the Build column of the agents table shows it. - HQ host.
AIMO_AGENT_HOSTis preset in the image to its environment's API host; set it only to reach AIMO through another address (for examplelocalhost:8000against a local stack). Host only, no path:/api/v1and/api/v1/agents/channelare fixed in the agent code. - TLS.
AIMO_AGENT_USE_TLSis preset alongside the host:truemeans REST over https and the channel over wss,falsemeans http and ws. Override it together with the host; it must match how the server is reachable from the agent (not inferred from the hostname). - Authentication. Connection commands use the agent JWT. Set
AIMO_AGENT_UUIDandAIMO_AGENT_PRIVATE_KEY_B64for a registered agent.AIMO_AGENT_PASSPHRASEis the secret connection credentials are encrypted with; if it is unset, the private key stands in for it, so set one you manage. - Job channel. The
startsubcommand uses the sameAIMO_AGENT_HOSTandAIMO_AGENT_USE_TLSfor the WebSocket (see above). - Forward proxy. Behind a forward proxy, set
HTTPS_PROXYto itshttp://URL (credentials in it are fine): the REST calls and the WebSocket channel both go through it, and hosts listed inNO_PROXYare reached directly. The variables have to be set inside the container: Docker's client proxy settings (proxiesin~/.docker/config.json) put them in every container it starts, or add-e HTTPS_PROXY -e NO_PROXYto thedocker runinaimo_agent.sh. Pulling the image goes through the Docker daemon's own proxy settings, which are configured separately.
See Operations for job behavior once the agent is connected.
start: run the agent
Starts the agent: connects to the job channel, accepts the job types AIMO dispatches, and runs them against your databases using stored credentials. If the channel drops, the agent reconnects with backoff, and results produced meanwhile are queued and sent once it is back. Every couple of hours an idle agent reopens the channel on its own to pick up a fresh token.
Options
--timeout/-t: an optional positive number of seconds. If set, the process exits after that much continuous idle time with no jobs queued or running; the timer resets when a job finishes. A zero or negative value is rejected. Omit to run until stopped.--connection-name,--connection-type,--connection-url,--connection-param FIELD=VALUE: a connection whose credentials stay in this agent process.--connection-nameis its handle: AIMO finds the connection by it, whatever the connection is called in the UI, and stores only the handle, its type and that an agent holds it: no URL and no password, not even as ciphertext.--connection-paramgives any other credentials field by name, repeatable (BigQuery'sservice_account_json, or the parameter form instead of a URL, such ashost,userandpassword). Before the job channel opens, the agent tests the credentials and probes the database's optional features, then holds the connection: AIMO creates it when the account has none of that handle, gives it to this agent when it has no agent (its agent was deleted; its tables and history stay), and refuses with the reason when another agent operates it or it is another database type. A database that does not answer yet does not stop the agent, since jobs wait for it; an AIMO that cannot be reached is retried with backoff.
The same connection can come from the environment: AIMO_AGENT_CONNECTION__NAME, AIMO_AGENT_CONNECTION__TYPE, AIMO_AGENT_CONNECTION__URL and AIMO_AGENT_CONNECTION__PARAMS__<FIELD>, all of them or none: flags, when given, replace the environment's connection whole. A flag is visible to every user of the host in its process list and stays in the shell history, so give a password through the environment, set from a file that only you can read, never typed at a prompt. An aimo_agent.sh written by register from this version on passes the first three variables to the container; an older one needs register again, or the three -e lines added by hand.
bash
# connection.env holds the three AIMO_AGENT_CONNECTION__ lines; chmod 600 connection.env
set -a; . ./connection.env; set +a
./aimo_agent.sh startJobs for such a connection need the process that holds it. An agent started without it fails those jobs as the database being unavailable, naming the connection. The agent selector in the UI cannot move a held connection: delete its agent and start the other one with the same --connection-name. edit on it takes credentials that AIMO then stores, encrypted, in place of the hold, keeping the connection's tables and history.
Typical use. A long-lived container or service; some deployments use a short idle timeout for ephemeral agents.
register: register a new agent
One-time pairing with AIMO. Generates an Ed25519 keypair, sends the public key with your registration token, confirms the keypair works by fetching a JWT, then writes aimo_agent.sh.
Arguments. Pass the registration token as the single positional argument after register.
On success you get an agent UUID and an aimo_agent.sh helper script. The script exports AIMO_AGENT_UUID, the base64 private key (AIMO_AGENT_PRIVATE_KEY_B64), an AIMO_AGENT_PASSPHRASE, plus AIMO_AGENT_HOST and AIMO_AGENT_USE_TLS, and wraps a docker run of the agent image. All connection credentials are encrypted with the passphrase. A new agent gets a random one: inspect the script and replace it with your own. A new key for an agent registered before keeps the passphrase its stored connections are encrypted with: the one in AIMO_AGENT_PASSPHRASE when it is set, otherwise the one in the aimo_agent.sh being replaced when that script is the same agent's.
The script is written to /app/data when that mount exists (inside the agent container), otherwise the current directory; set AIMO_AGENT_REGISTER_OUTPUT_DIR to override. If the file cannot be written, registration still succeeds and the script contents are printed for you to save manually.
Connection commands: add, list, show, edit, test, delete
Manage encrypted connections through the API (under /api/v1/agent/connections). Connection ciphertext is stored server-side against this agent's JWT; the plaintext credentials never leave the agent. show, edit, test and delete take an optional connection name as -c NAME: pass one to act on it directly, or omit it to pick interactively from the list.
| Command | Purpose |
|---|---|
add | Takes the name, the database type and the credentials as --name, --type and --param FIELD=VALUE (repeatable), and asks for whatever is missing, secrets hidden. With all of them given it needs no terminal, so it runs in a script or a docker run without -it; without a terminal, a missing required field ends it with that field named. Encrypts the credentials, tests the connection by decrypting that blob, and posts the ciphertext only if the test passes. add --help lists each type's fields, the required ones starred. |
list | Lists stored connections (name, type, id). |
show | Shows non-secret fields for a connection (sensitive values masked); decrypts internally only as needed. |
edit | Updates name, type or credentials; tests them, probes the database, re-encrypts and puts the result. With --param FIELD=VALUE, only the fields given change and nothing is asked: edit -c sales --param password=... rotates a password. On a connection an agent process holds, the credentials given are stored in place of the hold. |
test | Opens the stored connection and verifies reachability and basic metadata (schemas, table count). |
delete | Deletes a connection after a yes/no confirmation. |
Security. Operations require a valid agent JWT. See Security for ciphertext handling and masking.
Quick reference
text
python -m aimo.agent.cli start [--timeout SECONDS]
[--connection-name NAME --connection-type TYPE [--connection-url URL] [--connection-param FIELD=VALUE ...]]
python -m aimo.agent.cli register <REGISTRATION_TOKEN>
python -m aimo.agent.cli add [--name NAME] [--type TYPE] [--param FIELD=VALUE ...]
python -m aimo.agent.cli list
python -m aimo.agent.cli show [-c NAME]
python -m aimo.agent.cli edit [-c NAME] [--param FIELD=VALUE ...]
python -m aimo.agent.cli test [-c NAME]
python -m aimo.agent.cli delete [-c NAME]Related
- Architecture: network layout and trust boundaries.
- Operations: job types the running agent executes.
- Monitors: definitions jobs use when querying your data.