MiroFish-Offline (vendored)
MiroFish-Offline is the multi-agent crowd-simulation engine MAF calls into for the
crowd_simulation arena. We vendor it (no fork) at vendor/MiroFish-Offline/ and
bring it up via a MAF-side compose file, without editing anything inside the
submodule.
- Upstream: https://github.com/nikmcfly/MiroFish-Offline
- Vendored at:
vendor/MiroFish-Offline/ - Compose file at MAF root:
docker-compose.mirofish.yml
What this stack runs
| Service | Container name | Image / build | Host port (default) | Container port |
|---|---|---|---|---|
| MiroFish (Flask + Vue dev) | maf-mirofish |
built from vendor/MiroFish-Offline/Dockerfile |
5101 (backend), 3001 (frontend) |
5001, 3000 |
| Neo4j 5.18 community | maf-mirofish-neo4j |
neo4j:5.18-community |
7474 (browser), 7687 (bolt) |
7474, 7687 |
The vendor's ollama service is not brought up — we redirect at the env-var
layer to Ollama Cloud (see below).
Bring it up / down
# From MAF repo root:
docker compose -f docker-compose.mirofish.yml up -d
docker compose -f docker-compose.mirofish.yml ps
docker compose -f docker-compose.mirofish.yml logs -f mirofish
# Tear down (keeps Neo4j data volumes):
docker compose -f docker-compose.mirofish.yml down
# Tear down + wipe Neo4j data:
docker compose -f docker-compose.mirofish.yml down -v
The first up -d builds the MiroFish image and runs npm ci && uv sync inside the
container. Allow ~5–10 min on a cold cache.
URL the MAF adapter should use
http://localhost:5101
Point MirofishCrowdSource at MIROFISH_BASE_URL=http://localhost:5101. From inside
another compose stack on the same Docker network use http://maf-mirofish:5001.
API surface (all served by the Flask backend, see vendor/MiroFish-Offline/backend/app/__init__.py):
| Method | Path | Notes |
|---|---|---|
| GET | /health |
returns {"status": "ok", ...} (HTTP 200) |
| * | /api/graph/* |
knowledge graph build / query |
| * | /api/simulation/* |
OASIS simulation run + status |
| * | /api/report/* |
post-simulation report agent |
Ollama Cloud redirect (env-var only — no edits inside vendor/)
MiroFish was built against a local Ollama at http://localhost:11434. The MAF
compose file overrides this entirely via environment variables in
docker-compose.mirofish.yml. The vendor/MiroFish-Offline/backend/ code reads
all of these via os.environ.get(...) — see
vendor/MiroFish-Offline/backend/app/config.py and
vendor/MiroFish-Offline/backend/app/storage/embedding_service.py. We never patch
the vendored files; Compose injects the override values.
| MiroFish var | Default in vendor | MAF override (Ollama Cloud) |
|---|---|---|
LLM_BASE_URL |
http://localhost:11434/v1 |
https://ollama.com/v1 (OpenAI-compat) |
LLM_API_KEY |
ollama (any non-empty) |
${OLLAMA_API_KEY} from MAF .env |
LLM_MODEL_NAME |
qwen2.5:32b |
gpt-oss:20b-cloud |
OPENAI_API_BASE_URL |
http://localhost:11434/v1 |
https://ollama.com/v1 |
OPENAI_API_KEY |
ollama |
${OLLAMA_API_KEY} |
EMBEDDING_BASE_URL |
http://localhost:11434 |
https://ollama.com (native /api/embed) |
EMBEDDING_MODEL |
nomic-embed-text |
nomic-embed-text (verify availability) |
The trick: LLM_BASE_URL must point at the OpenAI-compatible Ollama Cloud shim
(https://ollama.com/v1) because MiroFish's LLMClient uses the openai Python
SDK. EMBEDDING_BASE_URL points one path up at https://ollama.com because the
embedder calls the native /api/embed endpoint directly (it appends the path
itself — see embedding_service.py).
Required env vars (read by MAF's compose)
Set in MAF .env (see .env.example):
OLLAMA_API_KEY=... # required — your Ollama Cloud key
NEO4J_USER=neo4j # optional, default neo4j
NEO4J_PASSWORD=mirofish # optional, default mirofish
MIROFISH_BACKEND_PORT=5101 # optional, host port for Flask
MIROFISH_FRONTEND_PORT=3001 # optional, host port for Vue dev server
MIROFISH_NEO4J_HTTP_PORT=7474 # optional
MIROFISH_NEO4J_BOLT_PORT=7687 # optional
MIROFISH_LLM_BASE_URL=https://ollama.com/v1
MIROFISH_LLM_MODEL=gpt-oss:20b-cloud
MIROFISH_EMBEDDING_BASE_URL=https://ollama.com
MIROFISH_EMBEDDING_MODEL=nomic-embed-text
Health check
curl -fsS http://localhost:5101/health
# → {"service":"MiroFish-Offline Backend","status":"ok"}
Neo4j browser: http://localhost:7474 (login: neo4j / mirofish).
Port-collision notes
The vendor's compose binds 3000 / 5001 / 11434 directly. On this host 3000, 5001,
and 11434 are already taken (paperclip, dev fomo2 backend, local Ollama). The MAF
compose remaps host ports to 3001 / 5101 (Neo4j keeps its defaults because they
were free). All host ports are overridable via the MIROFISH_*_PORT env vars
above.
Caveats
nomic-embed-textmay or may not be available on Ollama Cloud — confirm against your account on first run. If not available, swapMIROFISH_EMBEDDING_MODELto a cloud-supported embedding model, or temporarily run a local Ollama and setMIROFISH_EMBEDDING_BASE_URL=http://host.docker.internal:11434.- The MiroFish image runs
npm run dev, which spins both the Vue dev server (port 3000 in-container) and the Flask backend (5001 in-container) viaconcurrently. Only the backend matters to the MAF adapter; the Vue frontend is exposed for manual debugging. - Do not edit anything under
vendor/MiroFish-Offline/. All MAF-side customization lives indocker-compose.mirofish.yml. Rungit status -- vendor/MiroFish-Offline/after any compose change to confirm.