Setup

Run AXL locally

AXL is a server. You run axl-server, it loads your agents from a configuration directory, and you talk to it over HTTP on port 5000. The axl command line tool is a separate binary that talks to that server for you.

What you need first

Redis with the RediSearch module. AXL keeps sessions, memory, tasks, and search indexes there. The redis/redis-stack-server image has what you need:

docker run -d -p 6379:6379 redis/redis-stack-server

A model provider key. You need at least one. AXL will refuse to start without any, and tells you so: No LLM providers configured. Set at least one API key.

A signing keypair for tokens. AXL authenticates callers with RS256 JSON Web Tokens, so it needs a key to verify them:

axl key generate-jwt

That writes a private and public PEM. Keep the private one private.

If you would rather bring up Redis alongside the optional services - document extraction, S3-compatible storage, an identity provider - the repository root has a compose.yml with all of them. It uses its own ports, so set REDIS_URL to match rather than assuming 6379.

What the first start looks like

  • The first start is slower than later ones. AXL embeds a local model for memory and search, and prints Initializing local embedder... while it loads. If you configure no memory and no doc sets, it is skipped entirely.
  • Warnings scroll past. TAVILY_API_KEY not set - web tools disabled and similar lines mean an optional feature is off because you have not configured it. (PII_VAULT_KEY is the exception: with any shielded agent it is required, and the server refuses to start without it.) The server is telling you what it turned off.
  • A line naming your agents is the real "up" signal - one Agent ready per agent, then the listening line.

Start the server

export CONFIG_DIR=/path/to/axl-config
export REDIS_URL=redis://localhost:6379
export ANTHROPIC_API_KEY=sk-ant-...
export JWT_PRIVATE_KEY="$(cat ~/.axl/keys/jwt_private.pem)"
export JWT_PUBLIC_KEY="$(cat ~/.axl/keys/jwt_public.pem)"

axl-server

Those five are the whole minimum. REDIS_URL defaults to redis://localhost:6379 and PORT defaults to 5000, so you can drop those two if they match your setup. Everything else has a working default; the full list is in .

From a source checkout, the command is cargo run --bin axl-server instead.

Start with just a few agents

By default the server loads every agent listed in agents.toml. While you are finding your feet, it is often nicer to boot one or two and leave the rest alone - startup is quicker, and an agent you have no credentials for cannot distract you with warnings. AGENT_CONFIGS takes a comma-separated list of agent directories, relative to CONFIG_DIR, and uses them instead of the agents.toml list. Each entry points at a directory holding an agent.toml, the same paths agents.toml lists:

export AGENT_CONFIGS=agents/acme/acme-support-agent
axl-server

Skills still come from agents.toml, so agents you name here keep working normally. Unset it whenever you want the full roster back.

Check it came up

curl http://localhost:5000/health
{ "status": 200, "msg": "OK", "data": { "status": "healthy", "version": "0.1.0" } }

/health is the one route that does not need a token. Everything under /api/v1 does.

Get a token

axl config init \
  --jwt-private-key ~/.axl/keys/jwt_private.pem \
  --user-id you@example.com

This mints a token signed with your private key and saves it, so the axl command line tool is authenticated from here on. It does not contact the server; it signs locally with the same key the server verifies against.

It also saves the API URL it will use from now on, defaulting to http://localhost:5000/api/v1. If your server is on another port, say so here or every later command will quietly aim at the wrong place:

axl config init --api-url http://localhost:5055/api/v1

Three more values have to agree with the server, and config init cannot check them for you because it never calls it. If your deployment overrides any of these, pass the matching flag or verification fails and every call returns 401:

FlagMust match the server'sDefault
--jwt-kidJWT_KIDaxl-key-1
--issuerJWT_ISSUERaxl
--audienceJWT_AUDIENCEaxl

--tenant is different: it sets the token's azp claim, which the server reads as your tenant rather than checking against a configured value. It defaults to default.

Defaults line up out of the box, so on a fresh local setup you need none of these. axl config show prints what was saved.

Say hello

axl agents list

You should see the agents in your configuration directory. Then talk to one:

axl chat <agent-key>

That opens an interactive session. To ask one question and get one answer back - handy for a first smoke test, or for pasting the result into a ticket:

axl chat <agent-key> -m "Hello, what can you do?"

To do the same over HTTP, see .

When it does not start

What you seeWhat it means
CONFIG_DIR is not setPoint it at the directory holding agents.toml
No LLM providers configuredSet at least one provider API key
A panic mentioning length is lower than 1JWT_PRIVATE_KEY or JWT_PUBLIC_KEY is empty. Run axl key generate-jwt
Connection refused on startupRedis is not reachable at REDIS_URL
401 Missing Authorization headerThe route needs a token. Run axl config init
401 with a token that looks fineA kid, issuer, or audience mismatch. See Get a token
models.toml is requiredCONFIG_DIR points at a directory without one; it is the model registry
PII_VAULT_KEY is unset but N agent(s) have the shield enabledSet PII_VAULT_KEY to CSPRNG key material (e.g. openssl rand -hex 32; the 32-byte key is derived from it) and keep it stable, or disable the shield for every agent
MCP_ALLOWED_HOSTS must be set in productionA production boot needs MCP_ALLOWED_HOSTS (or PUBLIC_BASE_URL, from which it is derived); without one, /mcp accepts only loopback Host headers
The process exits with an Error: after listing some agentsOne agent's configuration could not be loaded. The message names the file - fix it, or narrow the roster with AGENT_CONFIGS while you do
Memory silently does nothingRedis without the RediSearch module. The log says unknown command 'FT.CREATE' and the agent starts with memory: "disabled"
It seems to hang for a whileProbably the embedder loading on a cold start. See What the first start looks like

Read the log first. The server explains itself: it prints one line per agent as it loads, names the file behind any configuration error, and says which optional features it turned off and why.

Next

On this page