Model or dataset
maze-agent/Maze avatar
maze-agent/Maze

Maze: scheduling LLM agent DAGs across gpu, cpu and io queues

A distributed framework for LLM agents

611 stars26 forksPythonMIT

At a glance

What is it?
Maze is an MIT-licensed Python framework that turns agent programs into distributed workflows, with Core-owned Runs, Ray-backed execution and a choice of FCFS or HACS task ordering. The interesting part is the resource model; the open question is how much infrastructure you already have.
Who is it for?
Adopt Maze if you already run Ray and your agent work is genuinely heterogeneous: tasks that want a GPU, tasks that are pure CPU, and tasks that mostly wait on I/O. Skip it if your agents are a single process calling one API, because the Run, workspace and worker machinery will cost more than it saves.
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 8 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 September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Maze targets: agent steps that want different hardware

An agent program is usually a loop of small steps, and those steps do not have the same appetite. One step calls a model on a GPU. The next parses files on CPU. A third waits on a network fetch and burns nothing. If you run all of it in one process, the GPU sits idle while the parser works, and the parser waits while the model runs. Maze's answer is to make each step a task in a DAG and schedule those tasks across separate gpu, cpu and io queues so one resource class cannot block another. That is the claim the README makes, and it is the reason the project exists rather than being another agent loop library. The audience is therefore narrow and specific: teams that already run their agents on more than one machine, or that have a mix of model-serving and non-model work in the same pipeline. A single developer running a ReAct loop against one hosted API gets nothing from this.

Core owns Runs, clients submit DAGs, Ray does the executing

The architecture diagram in the README is three layers stacked on top of Ray. Clients (Python SDK, LangGraph adapter, Workbench, application specs) all converge on one contract, maze.workflow/v1, posted to /workflows/submit. Below that, Maze Core owns what it calls Runs: a Core run_id is the public identity, and static workflows, DynamicRuns and application specs share the same persisted snapshots, events, logs, artifacts, cancel and retry APIs. Below Core, a scheduler and Ray split the work. The README is explicit that scheduling and placement are two separate decisions: FCFS or HACS decides which ready task goes first, and a node placement strategy decides which registered node receives it. That separation is worth noting because it means you can change ordering without changing placement, and the CLI reflects it. Model wait is also modelled as its own state. A task waiting for a local model instance is not counted as a dispatchable GPU, CPU or I/O queue item, and returns to its resource queue once routing is available. That is a small design detail with real consequences: without it, a queue would look busy while nothing was actually running.

Getting a head node, a worker and a cluster view running

Installation is a single package from PyPI, or an editable install from a clone. The head node starts with maze start --head --port 8000 --playground --detach, which brings up the Core API on 8000 and the Workbench UI on 5173. The command validates its configured ports before startup and prints the detached log path, which matters because a detached process that fails silently is hard to diagnose. maze status, maze doctor and maze stop manage that service. Workers join with maze start --worker --addr HEAD_IP:8000 --agent --heartbeat-interval 20, and the README frames the heartbeat as the mechanism that lets a worker periodically re-register after Head or Ray restarts. One constraint is stated plainly: a Ray node must also register as a Maze worker before Maze can schedule tasks to it. Inspection commands are maze cluster resources, maze cluster queues, maze cluster join-command and maze cluster reconcile-workers, all taking --server-url. Scheduling is switched with --scheduling-algorithm HACS on the head command, independently of --strategy least-loaded for placement. HACS has five environment variables with documented bounds: MAZE_HACS_ALPHA (default 2, greater than 0), MAZE_HACS_BETA (default 5, greater than 1), MAZE_HACS_INITIAL_DCT_SECONDS (60), MAZE_HACS_DCT_EMA_ALPHA (0.2, at most 1) and MAZE_HACS_STARVATION_SECONDS (600).

HACS is the one part of Maze that needs tuning before it helps

FCFS is the default, and for a small cluster it is probably right. HACS is the paper-aligned option, accepted to SC26 according to the release notes, and it works by refreshing ready-task priorities at dispatch time and maintaining a DCT EMA from completed workflow durations. That is a feedback loop, and feedback loops need data. MAZE_HACS_INITIAL_DCT_SECONDS defaults to 60, so before any workflow has completed, HACS is estimating from a guess. MAZE_HACS_DCT_EMA_ALPHA at 0.2 means each new completed duration moves the estimate by a fifth, so the estimate adjusts over roughly a handful of runs rather than immediately. MAZE_HACS_STARVATION_SECONDS at 600 is a floor against the obvious failure mode of a priority scheme: a task that never gets picked. The honest reading is that turning on HACS on day one, with an empty duration history and a workload you have not measured, gives you a scheduler tuned to a 60-second fiction. The README does not describe a warm-up mode or a way to seed the DCT, so the practical path is to run FCFS first, observe real durations, and only then decide whether HACS ordering is worth the transition.

Durability claims and the DynamicRun state you have to keep consistent

The README lists what a Run retains across process restarts: task state, structured errors, events, logs, retries, timeouts, cancellation, placement and content-addressed artifacts. The 2026-07 notes add worker re-registration, run-level deadlines, explicit scheduler-failure states and restart-safe Run discovery. Taken together this is a persistence story rather than a fault-tolerance guarantee, and the distinction is worth keeping. Durable state tells you what happened. It does not tell you that a task which was mid-execution when a worker died will resume from where it stopped, and nothing in the supplied material describes checkpointing inside a running task. The dynamic workflow path raises the same question in a different form: tasks can be appended at runtime with persisted DynamicRun state, which means the DAG is being mutated while the scheduler is reading it. That is a legitimate design for agent loops, where the next step depends on the last result, but it puts the burden on you to keep appends and reads coherent. The README does not document what happens if a submission races an in-flight scheduling pass.

Where Maze is the wrong tool, and what to use instead

The clearest case against Maze is a single-process agent. If your program is one loop calling one model API, Maze asks you to install Ray, run a head node, register workers, and think about workspaces before you have written a second task. The architecture diagram is a stack of layers, and every layer is a thing that can be misconfigured. For that situation a plain Python loop, or a library that keeps the agent in one process, is the better fit. The closer comparison is Ray itself, since Maze is built on it. Ray gives you tasks, actors and a cluster, and it will schedule work across machines today. What Ray does not give you is the layer Maze adds above it: the maze.workflow/v1 contract, Core-owned run identity with events and artifacts, the gpu/cpu/io queue split, model-wait as a distinct state, and the HACS ordering. So the real question is whether you want to build those semantics yourself on raw Ray or adopt someone else's version of them. If your tasks are homogeneous, or if you are happy to encode resource classes as Ray options by hand, Maze's contribution is mostly convention rather than capability. The LangGraph adapter is a narrower alternative on the client side: it lets an existing LangGraph workflow submit through the same contract, which is useful if you already have LangGraph DAGs and want the scheduling underneath them without rewriting the graph.

Licence, maintenance surface and what upgrading actually costs

Maze is MIT-licensed, which is permissive and places few obligations on how you redistribute or modify it. That is the whole of the licence analysis this material supports; nothing here is legal advice, and if you embed Maze in a product you should read the licence text yourself rather than a summary. The maintenance question is more concrete. The repository shows no releases retrieved, so there is no versioned artifact list to pin against, and the install path documented is a plain pip install maze-agent or an editable install from main. That means your upgrade unit is the branch, not a tagged release, which is a real operational cost: you cannot easily say which commit you are running unless you record it yourself. The changelog cadence is high, with entries for 2026-05, 2026-06, 2026-07 and 2026-08, and the 2026-08 entry describes consolidating SDK, LangGraph and Workbench execution around Core-owned Runs. That is a structural change to how clients reach the runtime, so an upgrade across that boundary is not a patch. Before adopting, check whether tagged releases now exist, and if not, decide how you will pin and test upgrades from main.

Editorial conclusion

Adopt Maze if you already run Ray and your agent work is genuinely heterogeneous: tasks that want a GPU, tasks that are pure CPU, and tasks that mostly wait on I/O. Skip it if your agents are a single process calling one API, because the Run, workspace and worker machinery will cost more than it saves. Before committing, verify three things in your own environment: that a worker survives a Head restart and re-registers (the README shows --heartbeat-interval 20 for exactly this), that maze cluster reconcile-workers reports the nodes you expect, and that your HACS thresholds in MAZE_HACS_ALPHA, MAZE_HACS_BETA and MAZE_HACS_STARVATION_SECONDS behave sensibly against your real task durations rather than the 60-second initial DCT default.

Official sources

  1. Issues
  2. License: MIT
  3. maze-agent/Maze on GitHub
  4. Project website
  5. README
Community notes

Community notes