Getting started
This walks through running Evo.ai locally, ingesting a folder, and asking a question with citations.
Run the dev stack
The Docker stack brings up Ollama (local models), Qdrant (vectors), and the Evo.ai app together:
bash
docker compose up -d # ollama + qdrant + evo-ai
./scripts/pull_models.sh # pull nomic-embed-text + the default LLMThen open the chat UI at http://localhost:8000/ui.
In development the app runs with DEV_MODE=true, which maps any bearer token to the tenant dev — so the examples below use -H "Authorization: Bearer dev". Outside dev mode, tokens are verified against EvoPlatform's JWKS and the tenant comes from the token's claims (see Multi-tenancy & security).
Ingest a folder
The watched-folder agent uploads a directory tree and (without --once) keeps watching it for changes:
bash
pip install watchdog
python scripts/watch_folder.py ~/my-docs --token dev --onceA SHA-256 manifest means unchanged files are skipped on subsequent runs. See Ingesting data for uploading individual files, ingesting structured records, and document identity.
Ask a question
Send a question to /query. The answer comes back with the source chunks it was grounded in:
bash
curl -s localhost:8000/query -H "Authorization: Bearer dev" \
-H "Content-Type: application/json" \
-d '{"question": "What does the safety manual say about work at height?"}'If the question isn't covered by the tenant's data, the relevance gate refuses before calling the LLM and the response carries gated: true. See Querying.
Point a tenant at a cloud model
By default a tenant uses the server's default model (Ollama in the dev stack). Switch a tenant to any LiteLLM provider at runtime:
bash
curl -s -X PUT localhost:8000/config/model -H "Authorization: Bearer dev" \
-H "Content-Type: application/json" \
-d '{"provider": "anthropic", "model": "claude-sonnet-5", "api_key": "sk-ant-..."}'The key is encrypted at rest. DELETE /config/model reverts the tenant to the server default. See Configuration for the full model and embedding options.