Thanks for your interest in improving Inspect Robots — the evaluation framework for physical AI. This guide covers how to get set up and what we expect from a change.
This repository is the framework (the "Inspect AI for robotics"). Concrete benchmarks live in a separate repository (the "Inspect Evals for robotics"). Backend adapters (simulators, real VLA models) are expected to ship as separate plugin packages that register components through entry points — see below.
So, in scope here: core abstractions, the rollout engine, scoring, logging, compatibility checking, the registry/plugin mechanism, and the dependency-free mock world. Out of scope: specific sims, specific model weights, specific benchmarks.
We use uv:
uv venv && uv pip install -e ".[dev]"
uv run pre-commit install # set up the git hooks (do this once)
uv run pytestBefore opening a PR, the same gates CI runs must pass locally:
uv run ruff check .
uv run ruff format --check .
uv run mypy
uv run pytest --cov # must report 100% coverageThis repo ships a pre-commit configuration
(.pre-commit-config.yaml). Install it once per clone
with uv run pre-commit install — this wires up both a pre-commit and a
pre-push hook. After that:
| Stage | When | Hooks |
|---|---|---|
| pre-commit | every git commit |
trailing-whitespace / EOF / YAML / TOML / merge-conflict / large-file checks, ruff (lint + autofix), ruff format, mypy (strict) |
| pre-push | every git push |
pytest with the 100% coverage gate |
The ruff/mypy/pytest hooks are local — they run the exact tool versions
in your dev environment, so the hooks, your terminal, and CI all agree.
Useful commands:
uv run pre-commit run --all-files # run the commit-stage hooks now
uv run pre-commit run --all-files --hook-stage pre-push # also run the coverage gate
uv run pre-commit autoupdate # bump the pinned hook reposIn a genuine emergency you can bypass hooks with git commit --no-verify /
git push --no-verify, but CI runs the same checks and will block the PR, so
prefer fixing the issue.
- Test-driven, 100% coverage. Write or update tests with every change; the
mock
CubePickworld lets you exercise the whole stack without hardware or a simulator. Coverage must stay at 100% (line and branch) — it is enforced by--cov-fail-under=100in the pre-push hook and as a blocking PR check in CI. For the rare line that is genuinely unexecutable (aProtocolstub, a__main__guard, a defensive branch), add it totool.coverage.report'sexclude_alsoor mark it# pragma: no coverwith a one-line justification — do not lower the threshold. - Typed. The package is
mypy --strictclean and shipspy.typed. Thedict[str, Any]escape hatches (info/extra/meta) are the deliberate boundary of typing — don't widen the public API toAnybeyond them. - Light core. The core depends only on NumPy and the standard library. Anything else (rerun, sim/model backends) is an optional extra and must be lazily imported so the core-only import test stays green.
- Small, focused units. Prefer files and functions with one clear purpose.
- Design first for non-trivial work. Larger features start with a short
design note under
plans/; see the existing ones for the format.
The docs site is built with MkDocs +
Material +
mkdocstrings — the API reference is generated
from docstrings, so keep them accurate. Cross-reference other symbols with
mkdocstrings autorefs: [`Observation`][inspect_robots.types.Observation].
uv pip install -e ".[docs]"
uv run mkdocs serve # live preview at http://127.0.0.1:8000
uv run mkdocs build --strict # what CI runs (warnings fail the build)llms.txt / llms-full.txt are generated automatically by the llmstxt plugin.
Register your component(s) by publishing entry points in your package's
pyproject.toml:
[project.entry-points."inspect_robots.embodiments"]
maniskill = "inspect_robots_maniskill:ManiSkillEmbodiment"
[project.entry-points."inspect_robots.policies"]
openvla = "inspect_robots_openvla:OpenVLAPolicy"Groups: inspect_robots.tasks, inspect_robots.policies, inspect_robots.embodiments,
inspect_robots.scorers, inspect_robots.sinks. They will then appear in inspect-robots list
and resolve by name in eval() / the CLI.
- Branch from
main. - Make the change with tests and docs (keep coverage at 100%).
- Ensure all gates pass — the pre-commit/pre-push hooks run them for you.
- Add a
CHANGELOG.mdentry under "Unreleased". - Open a PR describing the motivation and approach. CI re-runs lint, strict typing, the test matrix, and the 100% coverage gate as required, blocking checks before the PR can merge.
By contributing you agree your contributions are licensed under the project's MIT license.