# Sage: one runtime, three hosts, and no container isolation

> A multi-agent platform that ships as a Flutter desktop app, a web server with an agent studio, and an embeddable Python runtime, all running the same agent package, session and run model. Its own documentation is explicit that local process execution is not container isolation, the web server supports exactly one worker, and the downloadable installers are built from a legacy desktop app rather than the current one.

**ZHangZHengEric/Sage** — Multi-Agent System Framework For Complex Tasks

- Repository: https://github.com/ZHangZHengEric/Sage
- Website: https://zhangzhengeric.github.io/Sage/
- Stars: 1,210 · Forks: 103
- Language: Python
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/zhangzhengeric-sage

## One runtime with three ways in

The architecture is described as a diagram, and the diagram has one box in the middle with three above it and three below.

The three ways in are the desktop app, the web platform, and your own Python application. All three call into the same runtime, which holds three nouns and three capability groups.

The nouns are worth stating precisely because everything else refers to them. An agent package defines what an agent can do, and it is declared rather than coded, with instructions, capabilities and runtime configuration living in a manifest file, with immutable versions managed in the server's studio. A session keeps an agent's conversation history across runs. A run executes one task with live progress and interaction.

The capability groups below the runtime are models and context, which covers providers and memory; tools and workflows, which covers skills and MCP services; and execution and state, which covers storage, the sandbox and events.

That layout is why the platform can claim three hosts. The desktop app and the web server are two front ends over one runtime rather than two implementations, and a Python application embedding the runtime gets the same packages and sessions as either.

## The page says local execution is not container isolation

One sentence in the architecture section does more work than the rest of it, and it is worth quoting rather than paraphrasing.

The page states that your application owns the interface, the authentication and the credentials. Then it states that the built-in runtime configurations target a single process or a single host, and that local process execution is not container isolation.

That is a boundary claim, not a caveat. An agent that can run shell commands and write files is running with the permissions of the user who started it, and nothing in the default configuration changes that. Combined with the multi-agent orchestration features, where one agent can send directed messages to another, the blast radius of a misbehaving agent is the host, not a container.

The plugin architecture is described in the same terms as the rest of the platform: model, memory, storage, tool and scheduling providers composed through explicit contracts with managed lifecycles. Those contracts are an interface boundary between components, and an interface boundary is not a security boundary.

So the deployment question is not whether the platform is safe by default, because the page does not claim that. It is which isolation provider you attach to it, which is the next section.

## Two sandbox implementations, and one mode named passthrough

The example environment file documents the sandbox settings in more detail than the prose does, and it is the place the security story actually lives.

There are three modes. One runs locally, one passes execution through, and one is remote. The names alone tell you the pass-through mode applies no isolation, so choosing it is a decision to make explicitly.

Local mode differs by operating system. On Linux the isolation setting defaults to a bubblewrap-style mechanism, and a comment beside it says the server's local mode must use it, and that without it you should switch to remote instead. On macOS the choice is between plain subprocesses and seatbelt, the platform's own sandbox profile mechanism.

The limits are configurable and the comments are unusually honest about what they do not do. There is a CPU time limit of 300 seconds, and a virtual memory limit of 4096 megabytes, whose comment says it applies per process, is inherited by child processes, and is explicitly not a combined budget across processes or sessions. Eight parallel agents each get their own four gigabytes rather than sharing one.

Remote mode has three provider choices, a local execution service, Kubernetes and a microVM implementation, with an image reference, a 1800-second timeout, and a 256 kilobyte cap on appended output.

Mount paths are declared as comma-separated pairs mapping a host path to a sandbox path, which is the mechanism by which a sandboxed agent gets access to a project at all.

## One worker for the web platform, and installers from the old app

Two deployment facts will shape expectations if you have not read them.

The first is about the web server. It is described as supporting multi-user web access with an agent studio, and it requires a MySQL connection, a JWT secret and initial administrator credentials in an environment file. Then the page says server v2 currently supports one worker, and that MySQL persistence does not enable horizontal scaling.

That is an unusual thing to publish, and it is useful. A multi-user web platform backed by a real database is exactly the setup people assume will scale, so saying plainly that it will not saves a deployment plan built on the wrong assumption.

The second is about the downloadable builds. The release page offers packaged desktop installers, and then the page notes that packaged releases follow their own instructions while the existing release workflow builds the legacy Tauri app. The current desktop app is Flutter, built from source with a pinned Dart constraint and a desktop toolchain.

So the binaries on the releases page and the app described in the quick start are two different applications. The releases themselves show the same split: three tags in a single day in May, all prefixed for the desktop line, at versions 1.1.6 through 1.1.8, while the Python package is at 1.1.0 and the repository has moved on since.

Building the current desktop app from source instead looks like this on macOS, with Python 3.12, Flutter, and a Dart constraint:

```bash
git clone https://github.com/ZHangZHengEric/Sage.git
cd Sage
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
cd app/v2/desktop
flutter pub get
flutter run -d macos
```

The app starts its own backend, so there is no second process to launch. Settings and session data go to a runtime directory in the user's home, and the default workspace is a sibling directory beside it.

The server path is heavier: an install with the server extra, a copy of the example environment file, a web client install and build, and then the server module. It ends at a port in the eight thousands, with the agent studio served from a path under it.

## Two dependency files, and the older one lists a detection bypass

The repository carries both a requirements file and packaging metadata, and they are not the same list.

The requirements file is grouped by purpose in comments: general basics, document parsing, web and API frameworks, multi-model cooperation, network and async clients, instant-messaging platform SDKs, an ORM and databases, authorization, and scheduling. It includes an async messaging SDK for one platform and a streaming SDK for another, a proxy-supporting HTTP client, a document stack covering PDFs, presentations, spreadsheets and Word files, an unstructured partitioning library, a conversion layer, and a test-oriented set that includes an exact pin on the linter.

The packaging metadata is shorter and reorganized: database drivers and a telemetry exporter move into optional extras, and three exact pins appear for the agent protocol, the MCP SDK and a second MCP framework.

The notable entry is in the older file. Two packages are annotated as anti-scraping tools, one described as an intelligent web scraping framework with adaptive parsing and anti-bot bypass including all of its dependencies, and the other as a tool for bypassing browser detection. Neither is in the packaged dependency list, so a pip install of the current package does not pull them, while a developer following the requirements file does.

The practical consequence is that the two files document different products, and the requirements file is the legacy one.

## The metadata says 3.10 while the runtime wants 3.12

The interpreter support is split across a comment and a field, and the split is intentional.

The packaging metadata declares support from Python 3.10, with a comment above it saying that legacy Sage remains on 3.10 and newer while the v2 runtime and the v2 desktop application require 3.12 and newer. There is also a conditional dependency on a backport package for interpreters below 3.11, which is the same boundary expressed in the dependency list.

So there are two supported configurations, and the one most people will want, the v2 runtime, is the stricter one. The desktop build instructions and the server build instructions both say 3.12 or newer.

The database story has a similar shape. The server instructions require MySQL, and the packaging metadata offers extras for MySQL, for Postgres and for Redis, plus a server extra that includes the MySQL driver and an ORM with an upper bound below the next major version. A deployment that reads the extras list would reasonably think Postgres is a supported server database, while the documented server path is MySQL only.

The rest of the toolchain requirements are explicit: the desktop build needs Flutter with a Dart constraint and desktop support, and the server build needs Node 22.12 or newer plus a client build step.

## The one-file example deliberately has no file or shell tools

The shortest path to a running agent is described as one Python file with no manifest required, which is a friendlier starting point than the declarative package the rest of the platform is built around.

The example imports from a runtime namespace split into layers: a top-level namespace with a builder, a run starter, an actor reference and a request context, then sub-namespaces for commands, content items, principals, and a manifest loader. The agent's configuration is still a YAML document, embedded as a string in the file with a schema version, a kind, an id, a version, a name, and a credentials block whose key is read from the environment.

Two details are documented after the example. One helper parses the YAML text and another accepts the manifest object directly, so you can switch between the two without restructuring.

The other is the sentence that makes this example a good default: it prints events and the final state, without file or shell tools.

Given the platform's own statement that local execution is not container isolation, that omission is the most important line in the quick start. The smallest example is also the safest one, because the two capabilities that would make an agent dangerous on a host are left out of it. Adding them is a deliberate step, and the sandbox settings from the environment file are what you would reach for when you take it.

## Conclusion

Sage is built for teams that want one runtime with three ways in, and the separation of concerns is clean: your application keeps the interface, the authentication and the credentials, while the runtime keeps the packages, sessions and runs. Three things to check before deploying it anywhere shared. The isolation story is a per-deployment choice rather than a default guarantee, and one of the sandbox modes is named for passing execution straight through, so read the security model rather than assuming a sandbox. The web server is single-worker by design, which means a MySQL-backed multi-user deployment is one process. And the version lines have diverged: the Python package and the desktop installers number themselves separately, with the installers built from the previous desktop application.

## FAQ

### What are the ways to run the Sage agent platform?

Four entry points: Desktop v2 for local projects and agent collaboration, Server v2 for multi-user web access with an Agent Studio, SAgents v2 for building agents into your own Python application, and packaged Desktop installers from the releases page. The desktop, the web platform and your application all call into the same runtime, which owns agent packages, sessions and runs.

### Does Sage isolate agent code in a container?

Not by default. The page states that built-in runtime configurations target a single process or host and that local process execution is not container isolation. Sandboxing is a deployment choice with three modes, local, passthrough and remote, where local uses a bubblewrap-style mechanism on Linux and seatbelt or plain subprocesses on macOS, and remote can be a local execution service, Kubernetes or a microVM provider.

### What does the Sage server v2 require, and can it scale?

Python 3.12 or newer, MySQL, and Node.js 22.12 or newer. You install the server extra, copy the example environment file, set the database connection, a JWT secret and initial administrator credentials, build the web client, then run the server module and open localhost:8090, where an agent studio is served at /studio. It currently supports one worker, and the page says MySQL persistence does not enable horizontal scaling.

### What limits can I set on a Sage sandbox?

The example environment file documents a CPU time limit of 300 seconds and a virtual memory limit of 4096 megabytes, noting that the memory limit is per process, inherited by child processes, and not a combined budget across processes or sessions. You can also declare comma-separated host-to-sandbox mount path pairs, and for remote sandboxes a provider, an image and a timeout of 1800 seconds.

### What does the Sage SAgents v2 quickstart actually run?

One Python file with no manifest file on disk, an API key set in an environment variable, and a placeholder model name to replace. The resulting agent prints events and the final state without file or shell tools, which matters given the page's own statement that local process execution is not container isolation. A helper parses manifest text and another accepts the manifest object directly.

## Sources

- [License: MIT](https://github.com/ZHangZHengEric/Sage/blob/main/LICENSE)
- [Project website](https://zhangzhengeric.github.io/Sage/)
- [README](https://github.com/ZHangZHengEric/Sage/blob/main/README.md)
- [Releases](https://github.com/ZHangZHengEric/Sage/releases)
- [ZHangZHengEric/Sage on GitHub](https://github.com/ZHangZHengEric/Sage)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/zhangzhengeric-sage
