This guide gets the application running on your machine. You can use Docker for a full stack or run the API locally against existing services.
The API needs a chat and embedding provider. Before installing anything, choose:
-
I want to use OpenAI or Anthropic only (no local Ollama)
→ SetCHAT_PROVIDER=openaioranthropic,EMBED_PROVIDER=openai, and add your API keys in.env. You do not need to install Ollama. Skip every “Ollama” step in this guide. -
I want to use local Ollama (or Ollama + cloud later)
→ Follow the Ollama steps below (install Ollama, pull models). You can still switch to OpenAI/Anthropic later by changing.env.
| Choice | What you need | Install Ollama? |
|---|---|---|
| OpenAI or Anthropic only | CHAT_PROVIDER=openai or anthropic, EMBED_PROVIDER=openai, API keys in .env. |
No — skip all Ollama steps. |
| Ollama (local) | Run Ollama on the host or in Docker; no API key. | Yes — see “Ollama” steps below. |
If you are not sure, choose OpenAI/Anthropic only to get started without installing Ollama. You can switch to Ollama later by setting CHAT_PROVIDER=ollama and EMBED_PROVIDER=ollama and then installing Ollama.
- Docker and Docker Compose — for running the full stack (Postgres, Qdrant, Redis, API, optional Nginx and Celery).
- Python 3.11+ — if you run the API or scripts on the host (we recommend
uvorpip). - Ollama — only if you chose Ollama (local) above. Otherwise skip Ollama entirely.
This is the simplest way to run everything.
git clone https://github.com/your-username/local-ai-agent.git
cd local-ai-agent
cp .env.example .envEdit .env and set at least:
- POSTGRES_PASSWORD — use a strong password (e.g.
change_me_secure_passwordfor local dev only).
Other variables have sensible defaults. See .env.example for the full list.
docker compose up -dThis starts:
- PostgreSQL (port 5433 on host)
- Qdrant (6333)
- Redis (6379)
- PgBouncer (connection pool for Postgres)
- Nginx (API on port 8080)
- RAG API (behind Nginx)
- Celery worker (async ingestion)
- Next.js web UI (port 3002, configurable via
WEB_PORT)
API at http://localhost:8080 (or the port in API_PORT). Web UI at http://localhost:3002. Key URLs: docs README or API reference.
If you are using OpenAI/Anthropic only, skip this step. Otherwise the API needs an embedding model and a chat model. You can run Ollama on the host or in Docker.
On the host (typical):
-
Install and start Ollama (e.g.
ollama serve). -
In
.env, leaveOLLAMA_HOSTashttp://host.docker.internal(or the default) so the API in Docker can reach it. -
Pull the models:
ollama pull nomic-embed-text ollama pull llama3.2
In Docker:
docker compose --profile with-ollama up -dThen set in .env: OLLAMA_HOST=http://ollama. Pull models inside the container:
docker compose exec ollama ollama pull nomic-embed-text
docker compose exec ollama ollama pull llama3.2If REQUIRE_AUTH=true (default), you need an API key for protected endpoints. Run the script inside Docker so it connects to the right database:
docker compose run --rm api-service python -m scripts.create_tenant "My Tenant" my-tenantOr from the host (use port 5433, the published Postgres port):
POSTGRES_PORT=5433 uv run python -m scripts.create_tenant "My Tenant" my-tenantUse the printed API key in the X-API-Key header for all requests. To use the key from the web UI, set NEXT_PUBLIC_AGENT_API_KEY=<your key> in .env and rebuild the web container:
docker compose build --no-cache web && docker compose up -d web --no-depsFor local dev you can set REQUIRE_AUTH=false in .env and restart the API to skip the key entirely.
- Upload: Use the Swagger UI at http://localhost:8080/docs → POST /upload/document, or see User guide.
- Search:
POST /searchwith{"query": "your question", "limit": 10}. - Full pipeline:
POST /querywith{"query": "Compare chapter 1 between editions"}.
Use this when you want to develop or debug the API on your machine while using Docker only for dependencies.
docker compose up -d postgres qdrant redisEnsure .env points at these (e.g. POSTGRES_HOST=localhost, POSTGRES_PORT=5433, QDRANT_HOST=localhost, REDIS_HOST=localhost). If Postgres is exposed on 5433, use that port in .env.
uv sync
# or: pip install -e ".[dev]"uv run uvicorn src.api.main:app --host 0.0.0.0 --port 8000The API will be at http://localhost:8000. Open http://localhost:8000/docs for Swagger. The API will create tables and a default tenant on startup.
If you are using OpenAI/Anthropic only, skip this step. Otherwise run Ollama on the host (e.g. ollama serve) and set in .env:
OLLAMA_HOST=http://localhostOLLAMA_PORT=11434
Pull the same models as above (nomic-embed-text, llama3.2).
| Variable | Purpose | Default |
|---|---|---|
| POSTGRES_* | Database connection | localhost:5432 (use 5433 if Docker publishes that) |
| QDRANT_* | Vector store | localhost:6333 |
| REDIS_* | Cache, rate limit, Celery broker | localhost:6379 |
| OLLAMA_HOST | Where the API finds Ollama | http://localhost (host) or http://ollama (Docker) |
| CHAT_PROVIDER | Chat LLM provider | ollama (also: openai, anthropic) |
| EMBED_PROVIDER | Embedding provider | ollama (also: openai) |
| OPENAI_API_KEY | OpenAI key (when provider=openai) | — |
| REQUIRE_AUTH | Require X-API-Key | true |
| API_PORT | Nginx published port | 8080 |
| WEB_PORT | Next.js web UI port | 3002 |
For chat and embeddings you can switch to OpenAI or Anthropic; see Models and observability.
- API won't start: Check Postgres, Qdrant, Redis are reachable. Run
docker compose logs api-service --tail 80. - Which port? Docker + Nginx = 8080. Local API = 8000.
- 401 "Invalid or missing API key": Create a tenant:
docker compose run --rm api-service python -m scripts.create_tenant "My Tenant" my-tenant. For the web UI setNEXT_PUBLIC_AGENT_API_KEYin.envand rebuild:docker compose build --no-cache web && docker compose up -d web --no-deps. create_tenantauth failed: Postgres in Docker publishes on port 5433. UsePOSTGRES_PORT=5433or run inside Docker (step 4).- CORS errors: Handled by FastAPI. Nginx must not add duplicate CORS headers.
- 413 on upload: Increase
client_max_body_sizeindocker/nginx.conf/upload/block. - 504 timeout on upload: Documents are processed asynchronously via Celery. Ensure the worker runs:
docker compose up -d celery-worker. - Empty search results: Upload documents first. Verify you use the correct tenant API key.
- Tenant lost after restart: Use
docker compose stop/startinstead ofdocker compose down. - UI shows wrong provider: Check
CHAT_PROVIDERin.env, restart the API, refresh browser.
More: Developer guide, Operations.