Python client for the Menlo Robot Control Service (RCS) control plane.
Project description
menlo-robot-sdk
Python client for the Robot Control Service (RCS) control plane: robot CRUD and LiveKit session lifecycle.
⚠️ Alpha — Not for Production Use
This package is in active development and may have breaking changes between minor versions. APIs are subject to change. Use at your own risk.
Roadmap — Stage 0 (control plane) is shipped; Stages 1–5 cover production hardening, command/telemetry API, identity, publishing, and observability. No fixed dates — see docs/ROADMAP.md and issue #125.
Rough product spec (connect, skills, runtime helpers): ADR 0002 — what works today vs blocked on RCS (#136).
Install
uv add menlo-robot-sdk
# With LiveKit support
uv add "menlo-robot-sdk[livekit]"
cd packages/py/menlo-robot-sdk
uv sync --all-extras --dev
uv run python -c "from menlo_robot_sdk import AsyncClient; print('ok')"
Path dependency from another uv project:
[tool.uv.sources]
menlo-robot-sdk = { path = "../../packages/py/menlo-robot-sdk", editable = true }
When PyPI publishing lands (ROADMAP Stage 4): uv add menlo-robot-sdk and uv add "menlo-robot-sdk[livekit]".
Configuration
See .env.example for all client env vars (placeholders only — no secrets).
| Variable | Description |
|---|---|
MENLO_RCS_URL |
RCS base URL (e.g. http://localhost:8002) |
MENLO_IDENTITY |
Full X-Menlo-Identity header value (JWS or unsigned JSON) |
MENLO_IDENTITY_FILE |
Path to file containing identity (overrides MENLO_IDENTITY) |
MENLO_ROBOT_SDK_TIMEOUT |
Per-request timeout in seconds (default 30) |
MENLO_ROBOT_SDK_MAX_RETRIES |
Max retries on transport errors / safe HTTP codes (default 2) |
MENLO_ROBOT_SDK_DEBUG |
Set to 1 to log httpx request/response events |
MENLO_LIVEKIT_URL |
Optional override for connect_session() when RCS returns an internal hostname |
MENLO_RCS_INTEGRATION |
Set to 1 to run integration tests (see MANUAL_TESTING.md) |
MENLO_API_KEY alone is not supported for RCS; use MENLO_IDENTITY until token exchange ships (#136). Rough-spec url = MENLO_RCS_URL / MenloSettings.url.
Pass MenloSettings or omit rcs_url / identity on Client / AsyncClient to load from env. If you pass rcs_url and identity explicitly, you must pass both; passing only one raises ValueError. Optional timeout / max_retries override env defaults when using the env path.
robots.update(robot_id, name=...) sends only the keyword arguments you provide (omitted fields are not sent as null).
from menlo_robot_sdk import AsyncClient, DevIdentity, MenloSettings, workers
settings = MenloSettings.from_env()
# or local unsigned JSON:
settings = MenloSettings(
rcs_url="http://localhost:8002",
identity=DevIdentity(sub="user_dev", organization_id="org_dev", team_id="team_dev").to_header(),
)
async with AsyncClient(settings=settings) as client:
created = await client.robots.create(name="Lab bot", model="asimov-v0")
print(created.pin_code) # show-once PIN — save securely
page = await client.robots.list(limit=20)
async for robot in client.robots.iter(limit=50):
print(robot.id)
session = await client.robots.create_session(
created.robot.id,
workers=workers.for_rcs_stack(),
)
LiveKit (optional)
from menlo_robot_sdk.livekit import connect_session
room = await connect_session(session) # uses session.livekit_url
# room = await connect_session(session, livekit_url=<URL reachable from your host>) # override for Docker
In a sync-only script (no running event loop), use asyncio.run(connect_session(session)).
Connect helper (rough spec — partial)
from menlo_robot_sdk import AsyncClient, ConnectCallbacks, connect, workers
async with AsyncClient() as client:
handle = await connect(
client,
"rb_myrobot",
workers=workers.for_rcs_stack(),
join_livekit=False, # default True needs menlo-robot-sdk[livekit] for LiveKit + callbacks
)
# handle.get_robot_status(), invoke(), … raise MenloNotAvailableError until mono#136
await handle.disconnect()
See ADR 0002 for the full matrix.
Errors and retries
RCS errors use { "code", "message", "details" }. The SDK raises MenloAPIError for HTTP status ≥ 400. Retries (default 2) apply to transport failures and 429 on safe methods; POST /v1/robots and POST …/session are not retried. Backoff is capped at 30s. See ADR 0001.
Examples
Runnable cookbooks (one use case per file, flat snippets): examples/README.md. Run after local rcs-stack — see MANUAL_TESTING.md.
Testing
- Unit (mocked HTTP):
uv run pytest -q(integration excluded by default) - Integration (live RCS): see MANUAL_TESTING.md
- QA checklist (PR / release): MANUAL_TESTING.md § QA checklist
Development
cd packages/py/menlo-robot-sdk
uv sync --all-extras --dev
cd ../../../services/rcs && uv sync --frozen --no-dev && cd ../../packages/py/menlo-robot-sdk
uv run python scripts/export_rcs_openapi.py
uv run python scripts/regen_models.py --check
uv run ruff check .
uv run mypy src
uv run pytest -q
export MENLO_RCS_INTEGRATION=1
uv run pytest tests/integration -m integration -q # live RCS; see MANUAL_TESTING.md
Publishing
This package is published to PyPI via GitHub Actions on version tags. No API token needed — uses PyPI Trusted Publishing (OIDC).
To release a new version:
# 1. Bump version in pyproject.toml
cd packages/py/menlo-robot-sdk
# Edit version in pyproject.toml, then:
uv lock
# 2. Commit and merge to main
git add pyproject.toml uv.lock
git commit -m "chore: bump menlo-robot-sdk to v0.5.0"
# ... push PR, get approval, merge
# 3. Create and push the version tag (triggers publish workflow)
git checkout main && git pull
git tag menlo-robot-sdk-v0.5.0
git push origin menlo-robot-sdk-v0.5.0
The workflow .github/workflows/menlo-robot-sdk-publish.yml builds and publishes automatically. Check the Actions tab for status.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file menlo_robot_sdk-0.1.0.tar.gz.
File metadata
- Download URL: menlo_robot_sdk-0.1.0.tar.gz
- Upload date:
- Size: 27.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afde8bb9877d6376be9e43ea99ee79aa1c919f37d896ea25206c3e86c00a9a70
|
|
| MD5 |
7baf6c3a16d7bd9850d0b0608108b27b
|
|
| BLAKE2b-256 |
b8c25783df381519486043208bc8b73c0167717796b4301d149a195566471cf6
|
Provenance
The following attestation bundles were made for menlo_robot_sdk-0.1.0.tar.gz:
Publisher:
menlo-robot-sdk-publish.yml on menloresearch/mono
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
menlo_robot_sdk-0.1.0.tar.gz -
Subject digest:
afde8bb9877d6376be9e43ea99ee79aa1c919f37d896ea25206c3e86c00a9a70 - Sigstore transparency entry: 1732261290
- Sigstore integration time:
-
Permalink:
menloresearch/mono@93817179cee6a56ea07c0f8e8122d9f362ca0d6f -
Branch / Tag:
refs/tags/menlo-robot-sdk-v0.1.0 - Owner: https://github.com/menloresearch
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
menlo-robot-sdk-publish.yml@93817179cee6a56ea07c0f8e8122d9f362ca0d6f -
Trigger Event:
push
-
Statement type:
File details
Details for the file menlo_robot_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: menlo_robot_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a08f57bd3935c4844935664e54a2def581ede560d0275d8dc5863124829716d
|
|
| MD5 |
2748e7f8aba7b47307f2f6f046387ffe
|
|
| BLAKE2b-256 |
1972304e19628b94afcb5773bab6cb8d50b358f39c352312d1ac629361aa1661
|
Provenance
The following attestation bundles were made for menlo_robot_sdk-0.1.0-py3-none-any.whl:
Publisher:
menlo-robot-sdk-publish.yml on menloresearch/mono
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
menlo_robot_sdk-0.1.0-py3-none-any.whl -
Subject digest:
9a08f57bd3935c4844935664e54a2def581ede560d0275d8dc5863124829716d - Sigstore transparency entry: 1732261350
- Sigstore integration time:
-
Permalink:
menloresearch/mono@93817179cee6a56ea07c0f8e8122d9f362ca0d6f -
Branch / Tag:
refs/tags/menlo-robot-sdk-v0.1.0 - Owner: https://github.com/menloresearch
-
Access:
internal
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
menlo-robot-sdk-publish.yml@93817179cee6a56ea07c0f8e8122d9f362ca0d6f -
Trigger Event:
push
-
Statement type: