Skip to content

Getting Started

Stand up Felix locally and send your first request. Felix is a self-hostable managed agents harness: YAML manifests (apiVersion: felix/v1) compile into runnable agents with governance, durable execution, and multi-protocol surfaces.

For the mental model, read Concepts after this. For production deploy shape, see Deploy.

Prerequisites

  • Docker + Docker Compose
  • uv (Python 3.14+) for local CLI / non-Compose runs
  • Optional: ANTHROPIC_API_KEY and/or OPENAI_API_KEY, or a local Ollama daemon

Bootstrap (Compose)

  1. Clone and configure

    Terminal window
    git clone https://github.com/felix-run/felix.git && cd felix
    cp .env.example .env
    # set POSTGRES_PASSWORD (and keep FELIX_DATABASE_URL in sync):
    openssl rand -hex 32
  2. Start the lean stack

    Terminal window
    make up
    # or: docker compose up --build

    Brings up api (:8080), worker, scheduler, Postgres+pgvector, and Valkey. Object store defaults to fs under /data (no MinIO required).

    Small hosts: make up-lite. MinIO + S3 extras: make up-full.

  3. Migrate

    Terminal window
    make migrate
    # or: docker compose exec api felix migrate head
  4. Health check

    Terminal window
    curl -s http://localhost:8080/health | jq
    make doctor # from a uv-synced checkout, or: docker compose exec api felix doctor
  5. Export your local API key

    make up runs scripts/dev-key.sh, which writes an API key into .env on first run and prints it. The Compose stack is authenticated by default and publishes on 127.0.0.1.

    Terminal window
    export FELIX_KEY=$(grep -o 'sk-felix-local-[a-f0-9]*' .env | head -1)

Authenticated by default

Compose sets FELIX_AUTH_MODE=api_key, so every example below sends a bearer token. If you instead run without Compose via make dev, the harness starts with FELIX_AUTH_MODE=none bound to loopback and you can drop the authorization header. none is refused on any non-loopback bind.

First request — Felix-native /chat

The bundled default manifest is quick.

Terminal window
curl -s -X POST http://localhost:8080/chat \
-H "authorization: Bearer $FELIX_KEY" \
-H 'content-type: application/json' \
-d '{
"manifest": "quick",
"messages": [{ "role": "user", "content": "What is 7 * 6?" }]
}' | jq

Pass thread_id as a suffix (no : / #); the server prefixes the tenant id:

Terminal window
curl -s -X POST http://localhost:8080/chat \
-H "authorization: Bearer $FELIX_KEY" \
-H 'content-type: application/json' \
-d '{
"manifest": "quick",
"thread_id": "session-1",
"messages": [{ "role": "user", "content": "And times 10?" }]
}' | jq

Streaming:

Terminal window
curl -N -X POST http://localhost:8080/chat/stream \
-H "authorization: Bearer $FELIX_KEY" \
-H 'content-type: application/json' \
-d '{"manifest":"quick","messages":[{"role":"user","content":"Say hi."}]}'

First request — OpenAI-shaped /v1

model is a Felix manifest name (GET /v1/models):

Terminal window
curl -s -X POST http://localhost:8080/v1/chat/completions \
-H "authorization: Bearer $FELIX_KEY" \
-H 'content-type: application/json' \
-d '{
"model": "quick",
"messages": [{ "role": "user", "content": "Say hi." }]
}' | jq

Chat UI (optional)

From felix-run/web, with Compose Felix already on :8080:

Terminal window
git clone https://github.com/felix-run/web.git felix-web && cd felix-web
pnpm install
pnpm chat:dev # Vite :5173, proxies /api → http://127.0.0.1:8080

Offline eval (CI / no API keys)

Terminal window
uv sync --dev
FELIX_DATABASE_URL=memory://local FELIX_OBJECT_STORE=memory FELIX_ALLOW_INSECURE=true \
uv run felix eval -d smoke -m quick -f fixtures/eval/smoke.json --mock

Where to next