Tutorial 0 — Environment Setup¶
Packages:
mas-runtime,mas-ctl,mas-lab(installed for you — Docker ortask install) Time: ~10 min (Docker fast path) · ~20 min (developer path) Goal: Install MAS Lab, configure LLM access, and run your firstmas-ctlcommands before Tutorial 1.
Choose your path¶
| Path | Best for | You need |
|---|---|---|
| Fast path — Docker only | Users, demos, benchmarks | Docker, git, OPENAI_API_KEY for live LLM runs |
| Path A — Docker (full) | Same as fast path + CLI patterns, mounts, task helpers |
Docker, optional go-task |
| Path B — Developers | Patching runtime, ctl, or lab | Python ≥ 3.11, uv, task, direnv recommended |
Both paths use the same manifests and tutorials. Developers can still use Docker
for the UI (task start) while editing Python sources on the host.
Infrastructure defaults (standard:openai, standard:ollama, bundles, trace cache)
are documented in § Infrastructure below —
not in the root README, because they only matter once you are setting up a run.
Fast path — Docker only¶
No uv, no task, no direnv. You will configure LLM access, build the Docker
images, and run a few mas-ctl commands to confirm the install.
1 — Prerequisites¶
- Docker Desktop or Docker Engine
git clone https://github.com/outshift-open/mas-lab.git && cd mas-lab
2 — How LLM access works (read this first)¶
Three separate concerns — never mix secrets into YAML:
| Piece | What it is | Where it lives |
|---|---|---|
| Infra manifest | Non-secret endpoint config (API base URL, allowed models, api_key_env name) |
infra_refs in config.yaml or --infra-ref on CLI |
| Credential | API key or token | docker/.env (Docker) or gitignored .env (developers) |
| Flavour | Runtime environment bundle (local = default in library-standard) |
mas_ctl.flavour / mas_lab.flavour in workspace, or manifest |
Copy-ready examples (Tutorial 0 directory):
cp docs/tutorials/00-environment-setup/config.openai.example.yaml config.yaml
cp docs/tutorials/00-environment-setup/.env.example docker/.env # Docker path
# Edit docker/.env — set OPENAI_API_KEY=sk-...
config.openai.example.yaml sets:
mas_ctl.flavour: localandmas_lab.flavour: local(library-standard defaults)infra_refs: [standard:openai]— resolves to the bundled OpenAILLMProxymanifest
Schema: docs/schemas/config.schema.yaml.
Machine-wide path defaults: copy config.example.yaml to
$XDG_CONFIG_HOME/mas/config.yaml (default: ~/.config/mas/config.yaml).
3 — Build images¶
cd docker
docker compose build backend # CLI + controller API
# UI (optional): docker compose build ui
Tags: mas-lab-backend:local (required), mas-lab-ui:local (optional UI). First backend build takes several minutes.
Clean rebuild (remove old images first):
task docker-rebuild
# or: docker compose down --rmi local && docker rmi mas-lab-backend:local mas-lab-ui:local
# && docker compose build --no-cache
4 — Verify the CLI (offline)¶
These commands confirm that Docker can run mas-ctl and read tutorial manifests.
They do not call an LLM, so you can run them before adding an API key.
docker compose -f docker/compose.yaml run --rm --no-deps cli mas-lab config
docker compose -f docker/compose.yaml run --rm --no-deps cli mas-ctl validate \
docs/tutorials/01-building-an-agent/agent.yaml
Live LLM (after OPENAI_API_KEY is in docker/.env; use gpt-4o-mini on corporate proxies):
MAS_CTL_MODEL=gpt-4o-mini docker compose -f docker/compose.yaml run --rm --no-deps cli mas-ctl chat \
docs/tutorials/01-building-an-agent/agent.yaml \
-q "What is the capital of France?"
Corporate / OpenAI-compatible proxy — set infra_refs: [standard:llm-proxy] in
config.yaml (or MAS_INFRA_REFS=standard:llm-proxy) and
LLM_PROXY_API_BASE in .env / docker/.env. See
.env.example.
Offline mock (no network — uses mock infra overlay from Tutorial 1):
docker compose -f docker/compose.yaml run --rm --no-deps cli mas-ctl chat \
docs/tutorials/01-building-an-agent/agent.yaml \
-o docs/tutorials/01-building-an-agent/overlays/mock-llm.yaml \
-q "What is 2+2?"
| CLI | What it does |
|---|---|
mas-ctl validate <agent.yaml> |
Schema + refs without running |
mas-ctl chat <agent.yaml> -q "…" |
Single agent, one turn |
mas-ctl run-mas <mas.yaml> -q "…" |
Full MAS workflow |
mas-runtime list-bundles |
Installed infra bundles (standard:openai, …) |
mas-lab config |
Effective data paths and overrides |
On mas-ctl, -o / --overlay applies a manifest overlay (not an output path).
To write the trace elsewhere, use --events-file /path/to/events.jsonl.
5 — Trace cache and finding results¶
| Store | Default location | Purpose |
|---|---|---|
| Trace cache | $XDG_CACHE_HOME/mas/traces/ (default ~/.cache/mas/traces/) |
Content-addressed LLM traces — re-runs skip cached completions |
| Lab outputs | $XDG_DATA_HOME/mas/labs/<lab>/<experiment>/… |
Benchmark trees: …/itemN/rN/traces/events.jsonl, results/ |
| CLI chat traces | Next to manifest: traces/events.jsonl unless --events-file set |
Ad-hoc mas-ctl chat runs |
Confirm paths:
mas-lab config
Override output location
| Tool | Flag | Effect |
|---|---|---|
mas-lab benchmark run |
-o / --output-dir PATH |
Write this experiment under PATH instead of the global labs tree |
mas-lab benchmark run |
--trace-cache PATH |
Separate trace cache (bypass shared cache) |
mas-ctl chat |
--events-file PATH |
Write events.jsonl to PATH |
| Env | MAS_LABS_ROOT, MAS_TRACE_CACHE, MAS_RUNS_ROOT |
Override globals (see mas-lab config) |
Workspace paths: keys in config.yaml mirror $XDG_CONFIG_HOME/mas/config.yaml
when you want per-project defaults (schema: paths.labs_dir, paths.cache_dir,
paths.runs_dir).
6 — Start the web UI¶
The browser UI is the easiest way to browse manifests and benchmark results after install. It uses the same Docker stack as the CLI.
cd docker && docker compose up -d
# or from repo root: task start
| Service | URL |
|---|---|
| Web UI | http://localhost:8080 |
| Controller API | http://localhost:8090/api/health |
What to try: open an experiment under labs/ or docs/tutorials/, validate it,
and inspect results/ from a completed run. Guide: Web UI.
7 — Next¶
→ Tutorial 1 — Building an Agent — prefix commands with
docker compose -f docker/compose.yaml run --rm --no-deps cli when staying on Docker.
Path A — Docker users¶
Everything in the fast path, plus how mounts and config work.
Volume mounts¶
| Container | Host (default) | Purpose |
|---|---|---|
/workspace |
Repository root (.. from docker/) |
labs/, infra/, tutorials |
/data |
docker/data/ |
Trace cache, benchmark outputs |
Override in docker/.env:
MAS_WORKSPACE_MOUNT=/path/to/your/project
MAS_DATA_MOUNT=/path/to/persistent-data
The sample workspace file is at examples/sample-workspace/config.yaml.
Copy it to your project root as config.yaml, or set
MAS_WORKSPACE_ROOT=examples/sample-workspace when working from this checkout.
Configuration priority (inside Docker)¶
/workspace/config.yaml ← project copy (highest; optional on host mount)
/opt/mas-lab/config.yaml ← baked sample when mount has no project file
docker/.env ← OPENAI_API_KEY
/data/ ← trace cache & benchmark outputs
MAS_WORKSPACE_ROOT=/workspace is set in the container. The runtime does not
read a host $XDG_CONFIG_HOME/mas/config.yaml when that env var is set.
One-off CLI commands¶
cd docker
# Benchmark (uses trace cache under /data)
docker compose run --rm cli mas-lab benchmark run \
labs/design-space.lab/01-design-patterns/experiment.yaml --dry-run
# Multi-agent
docker compose run --rm cli mas-ctl run-mas path/to/mas.yaml -q "Hello"
The cli service uses the tools profile; docker compose run --rm cli … is equivalent to run --rm backend ….
Taskfile helpers (optional)¶
Install go-task, then from the repository root:
| Task | Purpose |
|---|---|
task start |
Build if needed, start UI + backend detached |
task restart |
Rebuild + recreate after docker/.env or code changes |
task verify-env |
Confirm OPENAI_API_KEY inside the running backend container |
task docker-rebuild |
Remove local images and docker compose build --no-cache |
Secrets belong in docker/.env only — shell export OPENAI_API_KEY is not
passed into containers (avoids stale keys). After editing .env, run task restart.
Full reference: docker/README.md in the repository.
Path B — Developers (uv + task)¶
Use this path when you change Python sources in runtime/, ctl/, or lab/.
1 — Prerequisites (one-time)¶
| Tool | Purpose | Install |
|---|---|---|
| Python ≥ 3.11 | Runtime | python3 --version |
| uv | Fast installs | brew install uv or astral.sh/uv |
| task | Repo automation | brew install go-task |
| direnv (recommended) | Auto-activate .venv |
brew install direnv + hook in ~/.zshrc |
2 — Clone and install¶
git clone https://github.com/outshift-open/mas-lab.git
cd mas-lab
direnv allow # optional; uses committed .envrc → ./.venv
task install # editable: runtime, ctl, library-standard, lab stack
Verify CLIs:
command -v mas-lab mas-ctl mas-runtime
mas-lab --help
For evaluation metrics, tutorials, and sample apps:
task install-dev # install + pytest, pyarrow, library-samples
# or full optional libraries:
task install-all
Manifest reference: references/index.md.
3 — direnv and .env¶
The committed .envrc sets UV_PROJECT_ENVIRONMENT=./.venv so this checkout
never shadows another project's venv.
Create a gitignored .env at the repo root for secrets:
cat > .env <<'EOF'
OPENAI_API_KEY=sk-...
EOF
mas-lab benchmark run and mas-ctl chat walk up from the cwd and load .env
automatically. Never commit API keys.
4 — Environment overrides (no YAML edits)¶
| Variable | Purpose |
|---|---|
MAS_INFRA_REFS |
Replace infra_refs from config.yaml (e.g. standard:llm-proxy) |
MAS_CTL_MODEL |
Override the agent model for one run (e.g. gpt-4o-mini, or a provider-prefixed id via a proxy gateway) |
MAS_LLM_MODEL |
Alias for MAS_CTL_MODEL (legacy .env name) |
MAS_WORKSPACE_ROOT |
Point at a project root when cwd is elsewhere |
LLM_PROXY_API_BASE |
API base for standard:llm-proxy (read from .env) |
OPENAI_API_KEY |
Credential named by the LLMProxy manifest |
Example (proxy gateway, Tutorial 0 CI smoke):
export MAS_INFRA_REFS=standard:llm-proxy
export MAS_CTL_MODEL=gpt-4o-mini
export OPENAI_API_KEY=...
export LLM_PROXY_API_BASE=https://your-proxy.example/v1
mas-ctl chat docs/tutorials/01-building-an-agent/agent.yaml \
-q "What is the capital of France?"
5 — User config ($XDG_CONFIG_HOME/mas/config.yaml)¶
Machine-wide paths and default infra bundle:
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/mas"
cp docs/tutorials/00-environment-setup/config.example.yaml \
"${XDG_CONFIG_HOME:-$HOME/.config}/mas/config.yaml"
Or create manually:
apiVersion: mas.config/v1
kind: UserConfig
default_infra: standard:production
runs_dir: ~/.local/share/mas/runs
cache_dir: ~/.cache/mas
labs_dir: ~/.local/share/mas/labs
Check effective paths:
mas-lab config
6 — Taskfile overview¶
Run task --list from the repo root. Common tasks:
| Task | Purpose |
|---|---|
task install / install-dev / install-all |
Editable package installs |
task verify |
Pre-commit gate (unit + tutorial manifests + smoke) |
task verify-tutorials |
Replay tutorial demo/scenario.yaml commands |
task reproduce |
Run all paper lab experiments |
task start / restart |
Docker UI stack |
task docs-serve |
Local MkDocs site (http://127.0.0.1:8000) |
task docs-build |
Build site to site/ (same as GitHub Pages CI) |
7 — Smoke test¶
mas-ctl validate docs/tutorials/01-building-an-agent/agent.yaml
mas-ctl chat docs/tutorials/01-building-an-agent/agent.yaml \
-q "What is the capital of France?"
Offline (no network):
mas-ctl chat docs/tutorials/01-building-an-agent/agent.yaml \
-o docs/tutorials/01-building-an-agent/overlays/mock-llm.yaml \
-q "What is 2+2?"
7 — Keeping up to date¶
git pull
task install # only if pyproject.toml dependencies changed
Editable installs pick up code changes immediately; dependency changes need task install.
Infrastructure: LLM endpoints and data paths¶
The runtime needs a non-secret infra reference (where to call the LLM) and a
secret API key in .env or docker/.env.
OSS infra bundles (library-standard)¶
| Bundle | Use when |
|---|---|
standard:openai |
OpenAI API (OPENAI_API_KEY) |
standard:ollama |
Local Ollama at http://localhost:11434/v1 (no key) |
standard:production |
Default for tutorials — wraps standard:openai |
standard:development |
Local Ollama bundle |
List installed bundles:
mas-runtime list-bundles
# Docker:
docker compose -f docker/compose.yaml run --rm --no-deps cli mas-runtime list-bundles
Set the default in $XDG_CONFIG_HOME/mas/config.yaml (default_infra: standard:production) or
per-project in config.yaml (infra_refs:). CLI --infra-ref overrides
for one run.
Inline URL (quickest smoke test)¶
mas-ctl chat docs/tutorials/01-building-an-agent/agent.yaml \
--infra-ref http://localhost:11434/v1 -q "Hello"
Data directories¶
| Setting | Contents |
|---|---|
labs_dir |
Experiment trees (<name>/<scenario>/itemN/rN/traces/events.jsonl) |
cache_dir/traces/ |
Content-addressed trace store |
cache_dir/artifacts/ |
Pipeline step cache |
Override: MAS_LABS_ROOT, MAS_TRACE_CACHE, or fields in $XDG_CONFIG_HOME/mas/config.yaml.
Always confirm with mas-lab config.
More detail: user-config.md.
Verify this tutorial (CI)¶
Developer path (no Docker):
pytest tests/tutorials/test_scenario_commands.py -v -k "tuto-00 and Developer"
Docker path (skipped automatically when the daemon is not running):
pytest tests/tutorials/test_scenario_commands.py -v -k tuto-00
Full tutorial gate: task verify-tutorials.
Live LLM (requires OPENAI_API_KEY in .env or docker/.env):
TUTORIAL_ONLINE=1 pytest tests/tutorials/test_scenario_commands.py -v -k tuto-00
Common errors¶
command not found: mas-lab¶
Activate the venv: direnv allow or source .venv/bin/activate, then task install.
401 from the LLM¶
- Docker: set
OPENAI_API_KEYindocker/.env, thentask restart - Source: set
OPENAI_API_KEYin repo.envorsource .env - Check bundle:
mas-lab configanddefault_infrain$XDG_CONFIG_HOME/mas/config.yaml
Docker build fails¶
Ensure you run docker compose from docker/ (or use docker compose -f docker/compose.yaml from repo root). Network is required for the first uv sync inside the image.
Wrong benchmark output path¶
Run mas-lab config — outputs go to $XDG_DATA_HOME/mas/labs/ by default (or paths from user config).