Metaworld's mt and ml prefixes decide what your policy can see
Collections of robotics environments geared towards benchmarking multi-task and meta reinforcement learning
At a glance
- What is it?
- Metaworld is a Farama Foundation benchmark of 50 MuJoCo manipulation tasks for multi-task and meta reinforcement learning, packaged behind the Gymnasium API. The single most consequential detail is that an mt benchmark returns goal observable states while an ml benchmark returns partially observable ones, so the prefix changes the problem, not just the label.
- Who is it for?
- Metaworld fits research code that already speaks Gymnasium and wants a fixed 50 task manipulation suite to compare multi-task or few-shot adaptation results against, with vectorised sync or async execution available. It does not fit work that needs Windows support, that runs on Python 3.10 or 3.14, or that has already standardised on a different manipulation suite with different tasks and reward scales.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- Farama-Foundation/Metaworld1,905 ★ · +7
| Repository | 2026-10-16 | 2026-11-07 |
|---|---|---|
| Farama-Foundation/Metaworld | 1.9k | 1.9k |
7 Stars in the last 22 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Gymnasium registration strings, not Python classes
Metaworld exposes itself entirely through Gymnasium. The README says the API follows the Gymnasium API for environment creation and environment interactions, and every example goes through gym.make or gym.make_vec with a string identifier that starts with Meta-World/.
import gymnasium as gym
import metaworld
env = gym.make("Meta-World/MT1", env_name="reach-v3")
observation, info = env.reset()
for _ in range(500):
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action)
env.close()The string is the whole configuration surface, and it encodes three separate choices. The prefix picks the benchmark family, the train or test suffix appears where a benchmark is split, and env_name selects one of the 50 tasks. The examples pass a seed explicitly for reproducibility, as in seed = 42, rather than relying on any default.
Task names carry a version suffix. The single task benchmarks use names like reach-v3, the ML1 example uses reach-V3 with a capital V, and the custom benchmark section requires the user to provide a list of environment names with the suffix '-v3'. That inconsistency between the ML1 example and the rest of the README is small but real: an env_name that does not resolve is a silent-looking failure rather than an obvious one.
The step signature follows current Gymnasium, returning five values with terminated and truncated separate rather than a single done flag.
One-hot task IDs change what MT10 and MT50 observe
The multi-task benchmarks MT1, MT10 and MT50 train a single policy over 1, 10 or 50 tasks at once. MT1 can be built from any of the 50 available tasks. In MT10 and MT50, the README states that the observations returned by the benchmark come with one-hot task IDs appended to the state.
That sentence is the design decision that matters. An MT policy is told which task it is in, so the burden falls on the network to condition its behaviour rather than infer the task from the state. MT1 gets no such append, which means the same code path behaves differently at scale 1 and at scale 10. Any layer size, normalisation or input dimension you derive from MT1 observations will be wrong for MT10 unless you account for the appended IDs.
The meta-learning benchmarks behave differently again. ML1, ML10 and ML45 are three meta-reinforcement learning benchmarks. ML1 tests few-shot adaptation to goal variations within a single task, and can be used with any of the 50 tasks. ML10 and ML45 test few-shot adaptation to new tasks: ML10 has 10 training tasks with 5 test tasks, ML45 has 45 training tasks with 5 test tasks.
Each meta-learning benchmark has training and testing environments that must be created separately.
train_envs = gym.make('Meta-World/ML1-train', env_name='reach-V3', seed=seed)
test_envs = gym.make('Meta-World/ML1-test', env_name='reach-V3', seed=seed)Getting the train and test pair right is the whole meta-learning protocol, and the two IDs are separate strings rather than a flag.
sync and async decide whether ten environments share a process
The vectorised benchmarks come in two execution strategies, and the difference is not a performance knob, it is a process model.
envs = gym.make_vec('Meta-World/MT10', vector_strategy='sync', seed=seed)
obs, info = envs.reset()
a = envs.action_space.sample()
obs, reward, truncate, terminate, info = envs.step(a)With vector_strategy='sync', all environments live in the same process and step together. The README says the synchronous option needs the least resources, and recommends it for users with limited compute. With vector_strategy='async', each environment is isolated in its own process and communication happens through pipes.
envs = gym.make_vec('Meta-World/MT50', vector_strategy='async', seed=seed)That distinction propagates. MT50 has both strategies, MT10 has both, and ML10 and ML45 also accept either. ML1 does not go through make_vec at all in the README examples, because it is a single task.
The practical consequence for anyone porting existing code: an async vector environment returns actions and observations through inter-process messaging, so a policy that holds state across steps, or a wrapper that assumes in-process access to the MuJoCo model, will behave differently. The README does not document the pipe mechanism in detail, and does not say what the failure looks like if you mix the two.
Custom benchmarks are assembled from a list, and the prefix is the contract
Beyond the named benchmarks, the project supports custom benchmarks built by combining any number of Meta-World environments. The README states the rule plainly: the prefix 'mt' returns environments that are goal observable for multi-task reinforcement learning, while the prefix 'ml' returns environments that are partially observable for meta-reinforcement learning.
So the observable space of your custom benchmark is decided by the string prefix you pass to gym.make_vec, alongside a list of environment names that each carry the '-v3' suffix. This is the part worth internalising, because a custom benchmark assembled under the wrong prefix silently gives your algorithm an easier or a different problem than the one you meant to pose.
Like the built in benchmarks, custom ones run in synchronous or asynchronous mode.
The identifier the README uses for this is 'Meta-World/custom-mt-envs', passed to gym.make_vec alongside vector_strategy and the envs_list of '-v3' names.
Dependencies are pinned tightly in pyproject.toml. The package version is 3.1.1, requires-python is >= 3.11, < 3.14, and the runtime dependencies are gymnasium>=1.1, mujoco==3.3.0, numpy>=1.18, scipy>=1.4.1 and imageio. The mujoco pin is an exact equality, so a MuJoCo upgrade is not something pip will resolve for you inside an existing environment. Optional extras exist for testing, which pulls ipdb, memory_profiler, pyquaternion==0.9.5 and pytest>=4.4.0, and for development, which pulls black, isort and mypy.
Platform support stops at Linux and macOS
Installation is a single command, and the support statement is unusually precise about what is tested.
pip install metaworldThe README says the project supports and tests Python 3.11, 3.12 and 3.13 on Linux and macOS. It goes on to say that pull requests related to Windows are accepted but that Windows is not officially supported. That is the boundary to plan around: a Windows research workstation can attempt it, a Windows CI runner should not be treated as a supported configuration.
The version range matches the packaging metadata, which requires Python >= 3.11 and < 3.14. The upper bound is worth noting because it is an exclusion, not a statement that 3.14 will never work.
Repository structure shows a modest amount of engineering infrastructure: a Justfile and mise.toml for task running and toolchain pinning, a docker/ directory, a scripts/ directory, a tests/ directory, a .pre-commit-config.yaml and a CODE_OF_CONDUCT.md. Documentation lives at metaworld.farama.org, and the README also links an arXiv paper at arXiv 2505.11289, which is the scholarly description of the benchmark and the more authoritative source for what the tasks measure than the README is.
On cadence: v3.1.1 was released on 2026-06-28, after 3.0.0 on 2025-06-14 and v2.0.0 on 2023-06-16. The last push was on 2026-10-09 and the repository is not archived. The licence is MIT.
Editorial conclusion
Metaworld fits research code that already speaks Gymnasium and wants a fixed 50 task manipulation suite to compare multi-task or few-shot adaptation results against, with vectorised sync or async execution available. It does not fit work that needs Windows support, that runs on Python 3.10 or 3.14, or that has already standardised on a different manipulation suite with different tasks and reward scales. Before using it, fix your MuJoCo version at 3.3.0 as pyproject.toml pins, confirm whether your algorithm needs goal observable mt environments or partially observable ml ones, and keep your seeds explicit in examples where reproducibility is required.
Frequently asked questions
How do I install Metaworld and which Python versions are supported?
The install is pip install metaworld. The README states support and testing for Python 3.11, 3.12 and 3.13 on Linux and macOS, and pyproject.toml sets requires-python to >= 3.11, < 3.14. Windows pull requests are accepted but Windows is not officially supported.
What is the difference between the mt and ml prefixes?
The mt prefix returns environments that are goal observable for multi-task reinforcement learning, while the ml prefix returns environments that are partially observable for meta-reinforcement learning. The prefix therefore determines what the policy can observe.
Should I use vector_strategy sync or async for MT50?
Both exist. The synchronous version keeps all environments in one process and the README says it needs the least resources, while the asynchronous version isolates each environment in its own process and communicates through pipes.
How do ML10 and ML45 split their tasks?
ML10 comprises 10 train tasks with 5 test tasks, and ML45 comprises 45 training tasks with 5 test tasks. Both are created as separate vector environments with the -train and -test identifiers and accept either vector strategy.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/farama-foundation-metaworld)Star history chart for your README
[](https://hysenlabs.com/projects/farama-foundation-metaworld)Was this useful?