Skip to main content

Manhattan Reasoning Gym

Python SDK and CLI (mrg) for hardware design: iterate locally with fast synthesis / place-and-route feedback, run untrusted agents in a sandbox, and program real cloud FPGAs — all from one package.

Surface What it does Needs
mrg.build local synth / place-and-route reports (no board) Docker
mrg.Sandbox run an agent in a locked container that promotes to silicon Docker
mrg.cloud program + drive a real ECP5 over the cloud API key

Cloud FPGA access requires an allowlisted API key (mrg login). Local synth/PnR and sandboxing need only Docker — no toolchain to install.

Install

pip install manhattan-reasoning-gym

For local synth/PnR and sandboxing, pull the pinned toolchain image once (the SDK runs it for you — you never install yosys/nextpnr/LiteX):

docker pull ghcr.io/manhattanreasoning/mrg-sandbox:latest

If your system Python is broken or externally managed, the robust path is uv venv && uv pip install manhattan-reasoning-gym.

Agent quickstart (headless)

Copy-paste path for coding agents and CI — no browser, no prompts:

export MRG_API_KEY=...        # or: mrg login --github-token <no-scope PAT>
mrg synth examples/design.py  # JSON report on stdout, ~seconds
mrg pnr   examples/design.py  # JSON report (fmax_mhz, timing_met), ~tens of seconds
mrg run   examples/app.py     # programs a real FPGA, ~2-3 min first time
mrg reset 0                   # free the board when done (async, ~1 min)
  • All bus addresses are byte addresses: word n in your design's register map is byte address 4*n for app.read/app.write and mrg read/mrg write.
  • After mrg run the board stays reserved to you — reuse it with mrg run --no-program / mrg read / mrg write, and release it with mrg reset <fpga_id> when done. Reset is an async queued job that reflashes the base SoC (~1 min); poll mrg status --json rather than expecting instant idle.
  • mrg synth / mrg pnr print machine-readable JSON on stdout and exit non-zero when the build fails; mrg status --json, mrg jobs --json, and mrg job --json emit the raw orchestrator response — parse JSON, don't scrape tables. A build in flight has no board yet (see below), so mrg jobs is the only way to find its job_id without already having it.
  • Rough time budget: synth seconds · pnr tens of seconds · mrg run ~2-3 min for the first program · --no-program seconds · reset ~1 min.
  • mrg login with no flags is an interactive GitHub device flow. Headless, prefer $MRG_API_KEY, or mrg login --github-token <PAT> (also reads $GITHUB_TOKEN) with a no-scope PAT — it's only used to read your username. If you must run the device flow from a non-tty context, relay the printed URL + code to a human.

Local feedback — mrg.build

import manhattan_reasoning_gym as mrg

rep = mrg.build.synth("examples/design.py")   # fast: resource utilization
rep = mrg.build.pnr("examples/design.py")     # full SoC: real Fmax + timing
print(rep.fmax_mhz, rep.timing_met, rep.util.dsp.used)

CLI: mrg synth design.py · mrg pnr design.py [--sys-clk-mhz N] [--timing-target-mhz N] (--sys-clk-mhz re-clocks the SoC; --timing-target-mhz is the constraint PnR optimizes against and timing_met is graded on, defaulting to the sys clock; --target-mhz stays as a legacy alias for both).

synth is the cheap "is it getting bigger?" signal (core-only util); pnr places & routes the full SoC for the truthful system-clock Fmax and timing.

Sandboxed agents — mrg.Sandbox

Run untrusted agent code in a locked container (--network none, no key) that iterates locally and promotes vetted candidates to silicon:

import manhattan_reasoning_gym as mrg

result = mrg.Sandbox(files=["examples/design.py", "examples/agent.py"]).run("agent.py")
for promo in result.promotions:
    print(promo)

The container never holds a key or touches the network; the promote is a file handoff the trusted host brokers to silicon. No promote gating by default — the agent gates itself; pass guard= for an opt-in host-side check. With no API key, silicon resolves to a no-op backend; set one (and silicon="cloud") for real hardware.

Real silicon — mrg.cloud

import manhattan_reasoning_gym as mrg

app = mrg.cloud.App("my_design", design="examples/design.py")
with app:                    # programs the FPGA on first use, releases on exit
    app.write(0x0, 3)        # byte address: word n in the design => 4*n
    print("read:", app.read(0x8))

Or drive it from the CLI with a file that defines an App and an @app.local_entrypoint() — see examples/app.py, which exercises the example MAC design end-to-end:

mrg run examples/app.py

Name your registers by subclassing mrg.RegisterMap (byte addresses).

Board lifecycle: the with app: form releases the board on exit, but mrg run does not — the reservation persists so you can keep iterating with mrg run --no-program, mrg read, and mrg write. Free the board with mrg reset <fpga_id> (an async job that reflashes the base SoC, ~1 min — poll mrg status).

Authentication (cloud only)

API requests authenticate with an opaque API key sent as X-API-Key. You obtain one by exchanging a GitHub identity — the orchestrator verifies you against its allowlist and mints a key.

mrg login       # GitHub device flow (or paste a no-scope PAT), then you're set

The key is saved to ~/.config/mrg/credentials.json (mode 0600, keyed by orchestrator URL). Every command resolves the key in this order:

  1. --api-key flag
  2. $MRG_API_KEY
  3. the stored login (mrg login)

mrg logout revokes the key on the server and clears it locally.

Tutorials

Two runnable notebooks in examples/notebooks/:

  • 01_build_and_run — local synth/pnr feedback → program a real FPGA.
  • 02_sandboxing — run an agent in a locked sandbox that promotes to silicon.

The shared examples/design.py is a tiny tunable multiply-accumulate; tweak its WIDTH and watch DSP/Fmax move. examples/agent.py is the sandboxed agent, and examples/app.py is the mrg run app that drives the MAC on real silicon.

CLI reference

mrg login | logout
mrg synth <design.py>                       # local synthesis report
mrg pnr   <design.py> [--sys-clk-mhz N] [--timing-target-mhz N] [--target-mhz N]
                                            # local full-SoC place & route
mrg run   <file.py> [--no-program [--fpga-id N]]   # --fpga-id only meaningful with --no-program:
                                                     # a fresh build is never pinned to a board
mrg status [fpga_id] [--json]
mrg jobs [--status queued|running|complete|failed|cancelled] [--json]
mrg job <job_id> [--json]
mrg logs | cancel <job_id>
mrg reset <fpga_id>
mrg read  <fpga_id> <addr> [--count N]
mrg write <fpga_id> <addr> <value>

Development

pip install -e ".[dev]"
ruff check . && pytest -q

License

MIT — see LICENSE.

Metadata

Release files for manhattan-reasoning-gym 0.1.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for manhattan-reasoning-gym 0.1.7
File Size Uploaded
manhattan_reasoning_gym-0.1.7.tar.gz 89.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for manhattan-reasoning-gym 0.1.7
File Interpreter ABI Platform
manhattan_reasoning_gym-0.1.7-py3-none-any.whl Python 3 none any Details

Total release size: 131.7 kB

Release files / manhattan_reasoning_gym-0.1.7.tar.gz

Download URL manhattan_reasoning_gym-0.1.7.tar.gz
Size 89.8 kB
Tags Source
SHA-256 checksum
How to use checksums
41280af49aafc4bad64303d17f808190c28d94022146594958892d43ddd3eb0c
BLAKE2b-256 checksum
How to use checksums
699a783c36903aee0e95e3570085576e376136a401f4fb36daa5ac9e0a0584e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 15, 2026.

Transparency log

Release files / manhattan_reasoning_gym-0.1.7-py3-none-any.whl

Download URL manhattan_reasoning_gym-0.1.7-py3-none-any.whl
Size 41.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1dbe509807ad75650e1a5035dda8137e68b60a87c1bfcabf6a093c80571bc62d
BLAKE2b-256 checksum
How to use checksums
d7146cf8e073ce853afb577f138867c6c58821fdbc89557b85e93002082dd876
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 15, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

This release

0.1.7 This release

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page