Tutorial 0 — Environment Setup¶
Packages:
mas-runtime,mas-ctl,mas-lab(Docker or source checkout; PyPI upload pending) Time: ~10 min (Docker) · ~20 min (developer)
You install MAS Lab, give it access to an LLM, and run your first mas-ctl commands.
mas-ctl runs one agent or one multi-agent system (MAS). mas-lab runs experiments and manages configuration.
What you need¶
- A clone of the repository:
git clone https://github.com/ioc-project/mas-lab.git && cd mas-lab - An
OPENAI_API_KEYfor live LLM runs. Offline, onlymas-ctl validateworks.
Choose your path¶
| Path | Best for | You need |
|---|---|---|
| Path 0 — PyPI (not yet published) | Running a published release | Python ≥ 3.11, uv |
| Path 1 — Docker | Users, demos, benchmarks | Docker, optional go-task |
| Path 2 — Developer | Patching runtime, ctl, or lab | Python ≥ 3.11, uv, task, direnv (recommended) |
If unsure, pick Docker. All paths use the same manifests. Then do Verify your install.
Path 0 — PyPI packages¶
The packages are not uploaded yet. Use Docker or the developer path until the first release.
uv venv .venv
uv pip install mas-lab mas-library-standard mas-library-samples
export PATH="$PWD/.venv/bin:$PATH"
mas-lab init
export OPENAI_API_KEY=<your-key>
mas-lab installs mas-runtime and mas-ctl. To pin a release, use mas-lab==0.2.0.
The tutorial manifests live in the repository, not in the packages. Clone it to follow Tutorial 1.
Path 1 — Docker¶
Step 1 — Configure LLM access¶
LLM access has three parts. Keep secrets out of YAML.
| Piece | What it is | Where it lives |
|---|---|---|
| Infra manifest | Endpoint settings: API base URL, allowed models, api_key_env name (no secret) |
infra_refs in config.yaml, or --infra-ref |
| Credential | API key or token | docker/.env (Docker) or a gitignored .env (developers) |
| Flavour | Named runtime environment; local is the default |
mas_ctl.flavour / mas_lab.flavour, or the manifest |
The bundled standard:openai and standard:ollama infra need no mas-lab init. Set the key:
cp docs/tutorials/00-environment-setup/.env.example docker/.env
# Edit docker/.env — set OPENAI_API_KEY=sk-...
For an OpenAI-compatible proxy, pass --infra-ref standard:llm-proxy and set LLM_PROXY_API_BASE next to the key.
Schema: config.schema.yaml. Reference: user-config.md.
Step 2 — Build the images¶
cd docker
docker compose build backend # CLI + controller API; first build takes several minutes
# UI (optional): docker compose build ui
For a clean rebuild, run task docker-rebuild.
Step 3 — Run the CLI¶
Prefix every mas-ctl / mas-lab command with the cli service (profile tools):
docker compose --profile tools run --rm --no-deps cli mas-lab config
docker compose --profile tools run --rm --no-deps cli mas-ctl validate \
docs/tutorials/01-building-an-agent/agent.yaml
docker compose --profile tools run --rm --no-deps cli mas-ctl chat \
docs/tutorials/01-building-an-agent/agent.yaml -q "What is the capital of France?"
The first two commands run offline. chat needs the key or an llm_cache replay.
Use cli, not backend (the long-running API service).
Two more checks, both from docker/. The dry run plans an experiment without calling the LLM. run-mas runs a multi-agent system and needs a key or a cache replay.
docker compose --profile tools run --rm --no-deps cli mas-lab benchmark run \
labs/design-space.lab/01-design-patterns/experiment.yaml --dry-run
docker compose --profile tools run --rm --no-deps cli mas-ctl run-mas path/to/mas.yaml -q "Hello"
In the container, the working directory /opt/mas-lab is a copy of the repository baked into the image.
Your host checkout is mounted at /workspace. Use /workspace/<path> for files you edited after the build.
| Container path | Host (default) | Purpose |
|---|---|---|
/workspace |
Repository root | labs/, infra/, tutorials |
/data |
docker/data/ |
Trace cache, benchmark outputs |
Override the mounts in docker/.env with MAS_WORKSPACE_MOUNT and MAS_DATA_MOUNT.
Configuration priority: /workspace/config.yaml, then the mounted ~/.config/mas/config.yaml, then the baked /opt/mas-lab/config.yaml.
Step 4 — Start the web UI (optional)¶
cd docker && docker compose up -d # or from the repo root: task start
Open the UI at http://localhost:8080. The controller API is at http://localhost:8090/api/health. See the Web UI guide.
| Task | Purpose |
|---|---|
task start / task restart |
Start the stack; rebuild after docker/.env or code changes |
task verify-env |
Confirm OPENAI_API_KEY inside the backend container |
Put secrets in docker/.env only. A shell export does not reach containers. Details: docker/README.md.
Path 2 — Developers (uv + task)¶
Use this path to change the Python sources in runtime/, ctl/, or lab/.
Step 1 — Install¶
Install Python ≥ 3.11, uv (brew install uv), task (brew install go-task), and optionally direnv.
git clone https://github.com/ioc-project/mas-lab.git && cd mas-lab
direnv allow # recommended; uses the committed .envrc -> ./.venv
uv sync # workspace packages install editable
task install-dev # editable packages plus test and sample dependencies
Without direnv, run uv venv .venv once, then uv sync. uv run <cmd> runs a command in that environment.
task install-all adds every optional library.
Check the install. command -v prints three paths, and --help lists the commands. task verify-unit runs unit and package-boundary tests.
command -v mas-lab mas-ctl mas-runtime
mas-lab --help
task verify-unit
Step 2 — Set the key¶
cp docs/tutorials/00-environment-setup/.env.example .env
# Edit .env and set OPENAI_API_KEY=sk-...
mas-ctl and mas-lab benchmark run load .env from the current directory. mas-ctl also searches
from the manifest's directory up to the repository root. Use mas-ctl --env FILE … to name one. Never commit keys.
Step 3 — Set the user config¶
mas-lab init # writes ~/.config/mas/config.yaml (and optionally infra/<name>.yaml)
mas-lab config # show effective paths
The user config holds two keys: infra_refs (manifests to register, such as standard:openai) and
default_infra (used when you pass no --infra-ref). To write it by hand, start from
config.example.yaml (user config) or
config.openai.example.yaml (project config).
mas-lab init --local writes config.yaml and infra/<name>.yaml in the project root instead. Those take priority.
Step 4 — Make a self-contained project (optional)¶
To hand a project to someone unchanged, keep all paths inside it:
mkdir my-project && cd my-project
mas-lab init --local --yes
Add a paths: block (config.local-example.yaml) and data/ to .gitignore:
paths:
labs_dir: ./data/labs
cache_dir: ./data/cache
runs_dir: ./data/runs
Precedence: CLI flag, MAS_* variable, paths:, user config, XDG defaults. See user-config.md § Data paths.
Step 5 — Common tasks¶
Run task --list for all tasks. The useful ones:
| Task | Purpose |
|---|---|
task verify |
Pre-commit gate: version and env checks, then task ci |
task verify-lint |
Lockfile, literals, Ruff on changed Python |
task ci-fast |
Lint then unit |
task verify-tutorials |
Replay each tutorial's demo/scenario.yaml commands |
task docs-serve |
Local MkDocs site at http://127.0.0.1:8000 |
After git pull, run task install only if dependencies changed.
Verify your install¶
Run this from the repository root (prefix with uv run or the Docker command if needed):
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?"
validate works offline and prints a success line. chat prints an answer that names Paris.
mas-ctl reads and writes the LLM response cache by default, so a repeat of
the same query can return in tens of milliseconds with identical wording. Pass
-v to log cache hits and other internals (summarization, session hints).
Disable reads with --no-cache-read or MAS_LLM_CACHE_READ=false (PowerShell:
$env:MAS_LLM_CACHE_READ = "false"). See llm-cache.md.
Where things go¶
A trace is the record of a run. events.jsonl is its machine-readable form: one JSON event per line.
The trace cache stores whole-run traces so experiment reruns skip execution.
The LLM response cache is separate: it stores individual completions for
mas-ctl chat and run-mas (on by default; see the note above).
| Store | Default location |
|---|---|
| Trace cache | $XDG_CACHE_HOME/mas/traces/ (default ~/.cache/mas/traces/) |
| LLM response cache | $XDG_CACHE_HOME/mas/llm_cache.json |
| Lab outputs | $XDG_DATA_HOME/mas/labs/<lab>/<experiment>/…/itemN/rN/traces/events.jsonl |
mas-ctl chat traces |
traces/events.jsonl next to the manifest |
Run mas-lab config to confirm paths. To change them:
| Tool | Flag | Effect |
|---|---|---|
mas-lab benchmark run |
-o / --output-dir PATH |
Write the experiment under PATH |
mas-lab benchmark run |
--trace-cache PATH |
Use a separate trace cache |
mas-ctl chat |
--events-file PATH |
Write events.jsonl to PATH |
For per-project defaults, set paths.labs_dir, paths.cache_dir, and paths.runs_dir in the workspace config.yaml.
On mas-ctl, -o / --overlay applies an overlay (a small YAML file that changes a manifest at run time). It is not an output path.
Infrastructure: LLM endpoints¶
The infra reference says where to call the LLM. The key lives in .env or docker/.env.
| Bundle | Use when |
|---|---|
standard:openai |
OpenAI API (OPENAI_API_KEY) |
standard:ollama |
Local Ollama at http://localhost:11434/v1 (no key) |
standard:production |
Tutorial default. Wraps standard:openai. |
standard:development |
Local Ollama bundle |
List them with mas-ctl list-bundles. Set the default with default_infra: standard:production in the user config,
or infra_refs: in a project config.yaml. --infra-ref overrides it for one run, including an inline URL:
mas-ctl chat docs/tutorials/01-building-an-agent/agent.yaml \
--infra-ref http://localhost:11434/v1 -q "Hello"
Use --model ID on chat / tui to override the agent model. MAS_* override variables exist for test harnesses only:
see Environment overrides.
Verify this tutorial (CI)¶
pytest tests/tutorials/test_scenario_commands.py -v -k "tuto-00 and Developer" # no Docker
pytest tests/tutorials/test_scenario_commands.py -v -k tuto-00 # Docker (skipped without a daemon)
TUTORIAL_ONLINE=1 pytest tests/tutorials/test_scenario_commands.py -v -k tuto-00 # live LLM
Common errors¶
| Symptom | Fix |
|---|---|
command not found: mas-lab |
Run direnv allow or source .venv/bin/activate, then task install. |
401 from the LLM |
Set OPENAI_API_KEY in docker/.env then task restart (Docker), or in the repo .env (source). Check default_infra with mas-lab config. |
| Docker build fails | Run docker compose from docker/. The first uv sync in the image needs network access. |
| Wrong benchmark output path | Run mas-lab config. Outputs go to $XDG_DATA_HOME/mas/labs/ unless the user config says otherwise. |
What you learned¶
- MAS Lab needs an infra manifest (where to call), a credential (the key), and a flavour (environment).
mas-ctl validateworks offline;chatandrun-masneed a provider or a cache replay.mas-lab configshows where traces, cache, and results go.
Next step¶
Tutorial 1 — Building an Agent. On Docker, prefix its commands with docker compose --profile tools run --rm --no-deps cli.