Metadata-Version: 2.4
Name: anima-zero
Version: 1.2.0
Summary: ANIMA — the brain of an embodied robot: an object standard + registry + a generic agent loop. Connects to one object at a time and operates it through vision-capable LLMs.
Author-email: Jeff Liu Lab <contact@jeffliulab.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/jeffliulab/anima-zero
Keywords: embodied-ai,agent,llm-tool-use,object-standard,vision-language-action
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: anthropic>=0.69
Requires-Dist: openai>=1.0
Requires-Dist: fastapi>=0.115
Requires-Dist: uvicorn>=0.32
Requires-Dist: pillow>=10
Requires-Dist: pydantic>=2.6
Requires-Dist: pydantic-settings>=2.6
Requires-Dist: python-dotenv>=1.0
Requires-Dist: httpx>=0.27
Requires-Dist: mcp<2,>=1.2
Requires-Dist: langgraph>=1.0
Provides-Extra: dev
Requires-Dist: ruff<0.17,>=0.15; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Provides-Extra: chess
Requires-Dist: anima-chess>=0.1; extra == "chess"
Dynamic: license-file

# ANIMA Zero

[![Python](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org)
[![PyPI](https://img.shields.io/pypi/v/anima-zero.svg)](https://pypi.org/project/anima-zero/)
[![MCP](https://img.shields.io/badge/protocol-MCP-6f42c1.svg)](https://modelcontextprotocol.io)
[![MuJoCo](https://img.shields.io/badge/sim-MuJoCo-orange.svg)](https://mujoco.org)
[![Version](https://img.shields.io/github/v/tag/jeffliulab/anima-zero?label=version&color=lightgrey)](CHANGELOG.md)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

<a href="README.md"><img src="https://img.shields.io/badge/Language-English-2f81f7?style=flat-square" alt="English"></a>
<a href="docs/i18n/zh/README.md"><img src="https://img.shields.io/badge/%E8%AF%AD%E8%A8%80-%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87-e67e22?style=flat-square" alt="简体中文"></a>
<a href="docs/i18n/ja/README.md"><img src="https://img.shields.io/badge/%E8%A8%80%E8%AA%9E-%E6%97%A5%E6%9C%AC%E8%AA%9E-bf3989?style=flat-square" alt="日本語"></a>
<a href="docs/i18n/fr/README.md"><img src="https://img.shields.io/badge/Langue-Fran%C3%A7ais-8250df?style=flat-square" alt="Français"></a>
<a href="docs/i18n/es/README.md"><img src="https://img.shields.io/badge/Idioma-Espa%C3%B1ol-1a7f37?style=flat-square" alt="Español"></a>

> 🤖 **If you are an AI agent, read [AGENTS.md](AGENTS.md) first** — the machine-facing entry point:
> the layering rule, where each fact lives, and the commands.

## Overview

ANIMA Zero is the brain of an embodied robot. It thinks but never moves: it decides *what to do*,
and the body decides *how to move*.

Tell it "go to the living room". It has no map, no coordinates and no list of rooms — only the
camera on the robot's head. From that it works out where it is, picks a direction, and keeps
walking until it sees the room you asked for. The robot walks with a learned gait, so the legs
really step; nothing teleports.

<div align="center">
<img src="docs/images/nav-g1.gif" alt="ANIMA driving a humanoid through a house" width="820">
<br>
<img src="docs/images/nav-go2.gif" alt="ANIMA driving a quadruped through a house" width="820">
<br>
<sub>One brain, two bodies: a G1 humanoid above, a Go2 quadruped below.
In each clip the left half is the only input ANIMA gets; the right half is what actually happens, which it never sees.</sub>
</div>

### Why "Zero"?

It is a series name, not a version number. **Zero means this line stays open source** —
the brain is ANIMA Zero, the body is Open Chess Robot, and any future commercial edition will
carry a different name rather than closing this one. The whole project is MIT.

On PyPI it is `pip install anima-zero` and the import is `import anima` — `anima` alone was already registered by someone else.

## Key features

- **One brain, different bodies**: the same brain code drives a Unitree Go2 quadruped and a
  Unitree G1 humanoid without a line changing — only the eye height differs, 0.38 m against 1.25 m.
- **One interface for any world**: a world is a separate process speaking AWI over MCP. Swapping
  worlds means swapping a URL — and a world is untrusted until you have reviewed and approved it.
- **From a sentence to joint torques**: an instruction crosses five layers before it becomes leg
  motion, and those layers run three and a half orders of magnitude apart in frequency.
- **It remembers what it is doing**: two state registers ride along in the system prompt, so a
  sixty-step turn does not forget the goal or what it has already ruled out.
- **Auditable and interruptible**: every frame, thought and tool call is recorded, and a running
  turn can be stopped mid-flight.

<div align="center">
<img src="docs/images/eye-go2.png" alt="Quadruped view" width="400">
<img src="docs/images/eye-g1.png" alt="Humanoid view" width="400">
<br>
<sub>The same living room through the quadruped's eyes (left) and the humanoid's (right).
What a robot can see decides what it can conclude, which is why the scene is built realistically
rather than tailored to one machine.</sub>
</div>

## Architecture

A world is a program of its own — a simulator today, real hardware later. ANIMA never reaches
inside it. Everything the brain knows arrives through four channels, and everything it does leaves
through the same four. A human can also bypass the brain entirely and poke the world in its own UI,
which is the clearest proof that the two are genuinely separate.

<div align="center">
<img src="docs/images/arch-overview.svg" alt="Human, ANIMA and the world, with AWI in between" width="860">
</div>

The three endpoints along the bottom — ground truth, video and liveness — never travel over MCP and
never reach the brain. That separation is deliberate: the moment ground truth enters perception,
the ability this world is meant to test is given away for free.

Inside a single instruction the layering becomes concrete. The brain reasons once per step; the
gait policy runs at 50 Hz; physics at 500 Hz. That gap is what System 2 and System 1 actually mean
here, and it is why the brain can only ever issue intent, never joint angles.

<div align="center">
<img src="docs/images/command-journey.svg" alt="From one sentence to joint torques" width="860">
</div>

The world reports back truthfully rather than conveniently. A learned gait does not track a velocity
command exactly — a turn drifts, a walk falls short — so the world measures what actually happened and
says so, and the brain corrects its own sense of position from that rather than from what it asked for.

```text
src/core/      orchestrator, AWI contract, trust store, safety gate
src/clients/   MCP client layer and the world registry
src/session/   sessions, context window, unified log
src/llm/       model adapters      src/presentation/  HTTP backend
world/         the worlds, each its own process
services/      board-game engine   frontend/  web app   eval/  scoring
```

## Installation

```bash
uv tool install anima-zero     # or: pipx install anima-zero, or plain pip
anima demo
```

That is the whole first five minutes. The demo starts a tiny bundled world — a dot on an
eight-cell corridor, ANIMA's talker/listener — picks a brain, and runs one real turn:
if you have an API key it uses it, otherwise it walks you to a **free local brain that
runs on your CPU** (Qwen3-4B-Instruct via Ollama — `qwen3:4b-instruct`, ~2.5 GB, offered
as a one-line pull). Every frame, thought and tool call lands in a session log you can
read afterwards. Nothing you see is staged, and `anima doctor` will tell you where on
your disk all of it landed.

A real world is a separate program and none ships in the wheel, so the next step is to
get one: clone this repository for the worlds in [`world/`](world/), or write your own
against [the AWI spec](docs/awi-spec-v1.md) — [`src/examples/minimal_world.py`](src/examples/minimal_world.py),
the corridor from the demo, is the template to copy.

The fastest way to find your way around is to hand the repository to a coding agent — Claude
Code, Codex, or whichever you use — and let it read [AGENTS.md](AGENTS.md), which is written
for exactly that. It will start a world with you, or write you a new one.

```text
anima demo                    prove the loop works: a bundled world, one brain, one real turn
anima chat --world W          a conversation in the terminal
anima run --say "..."         one turn, scripted
anima serve                   the backend API, for the web app
anima world add NAME URL      register a world — and review it before approving
anima doctor                  what is configured and what is reachable
```

Stuck? [The FAQ](docs/faq.md) covers the six things new users actually trip over.

### The full setup

Three processes: a world, the backend, and the web app. Scenes and robots come from
alice-house, looked up next to this repository; set `HOUSENAV_ASSETS_ROOT` if it is elsewhere.

```bash
cd world/sim-house-nav && pip install -e . && uvicorn server:app --port 8112
pip install -e . && cp .env.example .env      # add an API key, or point at a local Ollama
anima serve
cd frontend && npm install && npm run dev
```

### Connecting a world is a trust decision

A world is a remote process, and its own description of itself lands in the brain's system
prompt — so its tools and guidance do not reach the brain until you have looked and said
yes. `anima world add NAME URL` prints what it declares, then asks. Approval binds to the
content, not the name: if the world comes back different you are asked again, with a note
on what changed. While developing your own world, set `ANIMA_TRUST_ALL=1`.
[SECURITY.md](SECURITY.md) says what this does and does not protect against.

## Seeing it run

Open the web app, create a session against `sim-house-nav`, and type "go to the living room".
The middle column shows what the robot sees and, separately, a chase camera that only you can
see. The right column shows every step: frame, reasoning, tool call, and the world's answer.

<div align="center">
<img src="docs/images/ui-chat-en.png" alt="The ANIMA web app" width="880">
</div>

To check whether a claim is true rather than plausible, ask the world directly —
`curl -s localhost:8112/status`, an endpoint for human verification that never enters perception.
Swapping things costs one line each: the body has a dropdown on the AWI dashboard (or set
`HOUSENAV_ROBOT=g1` before starting the world), the brain has one in the web app, and the world is
chosen when you create a session.

These worlds ship with the repository:

| World | Port | What it is |
|---|---|---|
| [sim-house-nav](world/sim-house-nav) | 8112 | An apartment and a walking robot, quadruped or humanoid |
| [sim-chess](world/sim-chess) | 8102 | A chess set that holds the only ground truth and plays back |
| [camera](world/camera) | 8104 | A real webcam, with no tools at all — look but never touch |

### How well it actually works

Five target rooms, one run each, every final frame checked by hand against what the model claimed:

| Target | Steps | Result |
|---|---|---|
| Kitchen | 9 | Correct — fridge, counter and wall cabinets all in frame |
| Living room | 5 | Correct — TV, sofa and floor lamp, not arguable |
| Master bedroom | 34 | Wrong — a marble floor was read as a "white mattress" |
| Bathroom | 40 | Wrong — that was the kitchen |
| Laundry | 60 | Unfinished — hit the per-turn step ceiling |

The interesting result is the negative one. The suspected cause used to be that a kitchen and a
bathroom look alike from 0.38 m, which is part of why the humanoid was added. But the humanoid, at
1.25 m, sees the hob and the range hood clearly and still calls it a bathroom. So this is not a
perception problem: facing the same doorway, the model composes whatever story matches the room it
is hunting for. The next release aims at the acceptance criterion instead.

Runs that did work, with per-frame verification, are written up in
[world/sim-house-nav/实测记录.md](world/sim-house-nav/实测记录.md).

## Add your own world

Implement a standard MCP server with the four channels above, add its address to `ANIMA_WORLDS`, and the
brain will drive it unchanged. The smallest complete example ships inside the package:
`src/examples/minimal_world.py` — the corridor from `anima demo`, annotated line by line
against the spec, and runnable on its own with `python -m anima.examples.minimal_world`.
Copy from [camera](world/camera) if your world is only something to look at,
[sim-chess](world/sim-chess) if it takes actions, or [sim-house-nav](world/sim-house-nav) for the
complete one, and read [world/README.md](world/README.md) first. The contract is written down in
[docs/awi-spec-v1.md](docs/awi-spec-v1.md), and `anima conformance <url>` checks a world against it.

## Acknowledgements

Scenes, robot models and locomotion policies come from [alice-house](https://github.com/jeffliulab/alice-house).
The humanoid's turning policy was trained in [unitree-g1-locomotion](https://github.com/jeffliulab/unitree-g1-locomotion).
Physics is [MuJoCo](https://mujoco.org); the robot models originate from
[MuJoCo Menagerie](https://github.com/google-deepmind/mujoco_menagerie).
