Run the API Server¶
This guide walks through configuring and launching the ai_ops.api HTTP server
from source with uvicorn. For the containerized deployment, see
Getting Started. For the full
endpoint/schema/config listing, see the API Reference.
The server is a FastAPI app (ai_ops.api.api:app) served with uvicorn. Both
ship as dependencies (the api group), so nothing extra to install.
1. Set the required configuration¶
At minimum the server needs a model. Point it at your LLM provider too, unless that's baked into the model id.
# .env (loaded automatically) or your shell environment
AI_OPS_MODEL=hosted_vllm/gemma-3-27b-it # required
LLM_API_BASE=https://your-vllm-domain/v1/ # provider base URL
LLM_API_KEY=your-provider-key # provider key
Everything else has a sensible default. See the configuration reference for the full list.
2. Choose a bind host (and auth)¶
The server binds to 127.0.0.1 by default and, on localhost, will start without
an API key (it just logs a warning). That's fine for local development:
The app enforces the incoming
Hostheader againstAI_OPS_HOST(TrustedHostMiddleware), so keep--hostandAI_OPS_HOSTin agreement or requests get400.
Exposing it beyond localhost¶
If you bind to anything other than localhost, an API key becomes mandatory:
the server refuses to boot without AI_OPS_AUTH_TOKEN. This is a deliberate
policy, never expose the agent on the network unauthenticated.
export AI_OPS_HOST=0.0.0.0
export AI_OPS_AUTH_TOKEN=$(openssl rand -hex 32)
uvicorn ai_ops.api.api:app --host 0.0.0.0 --port 8000
Clients must then send the token on every request:
3. (Optional) Tune the agent¶
The agent's tools, context strategy, temperature, and confirmation timeout come
from agent_config.json in the AI-OPS base directory (~/.local/share/ai_ops/).
Create it only if you want to override the defaults:
{
"tools": ["load_skill", "think", "write_whiteboard", "write_file", "terminal"],
"context_view": { "kind": "layered", "params": { "max_window_tokens": 32768 } },
"command_policies": [ { "kind": "allowlist", "params": { "allowlist": ["nmap", "ffuf"] } } ],
"temperature": 0.4,
"confirmation_timeout_s": 300
}
An unknown tool, context view, or policy name aborts startup with a non-zero exit and a message naming the offender. Keys are documented in the reference; tool and policy specifics live in Add a Tool.
Supplying config and skills¶
When you run from source, agent_config.json and user_skills/ live directly in the base directory (~/.local/share/ai_ops/), so nothing special is needed.
When you run the API in a container, mount them into that directory instead:
docker run --rm -p 8000:8000 --env-file .env \
--volume ai-ops-data:/home/aiops/.local/share/ai_ops \
--mount type=bind,source=/path/to/agent_config.json,target=/home/aiops/.local/share/ai_ops/agent_config.json,readonly \
--mount type=bind,source=/path/to/user_skills,target=/home/aiops/.local/share/ai_ops/user_skills,readonly \
--cap-add=NET_RAW --cap-add=NET_ADMIN --security-opt=no-new-privileges \
ai-ops:api-dev
The container runs as a non-root user, so the mounted paths must be world-readable: 644 for agent_config.json, 755 for the user_skills/
directories. Under SELinux, add ,relabel=shared (or ,relabel=private) to each --mount.
See Add a Skill for the skill format and Configuration for every agent_config.json key.
4. Verify it's up¶
curl http://127.0.0.1:8000/health
# {"status":"ok"}
curl http://127.0.0.1:8000/model
# {"provider":"...","model_id":"...","max_context_length":32768, ...}
5. Drive a conversation¶
The typical client flow is to create a conversation, send a message, and read the event stream:
# create a conversation, capture its short_id
SID=$(curl -s -X POST http://127.0.0.1:8000/conversation | jq .short_id)
# send a message; content and mode go in a JSON body.
# the response is newline-delimited JSON events
curl -N -X POST "http://127.0.0.1:8000/conversation/$SID" \
-H "Content-Type: application/json" \
-d '{"content": "enumerate the target", "mode": "supervised"}'
Each line is one event. In supervised mode, a tool_call with
"requires_confirmation": true means the agent is blocked waiting on you.
Approve or deny it with the same call_id:
When you're done, stop or drop the agent:
curl -X POST "http://127.0.0.1:8000/conversation/$SID/stop" # halt, keep it
curl -X DELETE "http://127.0.0.1:8000/conversation/$SID" # halt and drop
See the API Reference for every endpoint, event kind, and error code.
Notes on persistence¶
By default (AI_OPS_STORAGE_STRATEGY=jsonl) sessions are persisted under
~/.local/share/ai_ops/sessions/, so they survive a restart.
GET /conversation/{short_id} rebuilds a live agent for a stored session on
demand. Set AI_OPS_STORAGE_STRATEGY=in_memory to keep everything ephemeral.