System overview
How Disco Parrot is built, in one picture. One Node service and one React app, deployed as a single unit, with the sandbox host, AI runtime, connected tools, and git provider all swappable at the edges. A modular monolith by design, not a mesh of services.
Most platforms that run AI agents are a constellation: a queue here, a worker fleet there, a cache, a message bus, a handful of services that have to agree with each other to get one thing done. Disco Parrot is not built that way, and the difference matters whether you are going to operate it, extend it, or vet it. The whole system is small enough to hold in your head: one service, one app, deployed as a single unit, with the parts that genuinely vary swappable at the edges. Those parts are where the work runs, which model answers, what tools are connected, and which git provider you use.
This page is the shape of the system, not the security model: the boundary, the permission check, and the credential handling each have a deep page in security and governance, and appear here only as far as the architecture explains them. The pages after it go deep on the data layer, the real-time channel, the agent runtime, the git model, and how it deploys. Start here for the picture they all assume.
One service, one app
There are two pieces. A Node service built on Express owns everything on the server: the API, the chat and flow orchestration, the sandbox lifecycle, the permission checks, the scheduled work. A React single-page app owns everything in the browser, organized into the three areas you actually use, Planning, Platform, and Settings. That is the entire system. There is no separate API gateway, no auth service, no worker tier to deploy and version alongside it.
The two meet at a clean line. Every server endpoint lives under an internal /__ path prefix, and anything that is not one of those paths is the single-page app, served and left to its own router. A request is either the API or the app, decided by its path. The /__ prefix is reserved, so an app route can never collide with an API route, and there is no path-confusion class of bug to guard against. The server is built once and mounted once, and the dozens of route modules behind it, grouped by area (identity, chat, config, the planning API, webhooks), are wired together at one composition point.
That line is also where identity is established. Every /__ request is authenticated and resolved to a workspace and its permissions before the route's own logic runs, so a call has proven who it is and which workspace it speaks for before any route decides what it may do.
The same app in development and production
A common source of "works on my machine" bugs is that the development stack is not the production stack: a proxy in front, a different server in dev, subtly different behavior at the seams. Disco Parrot removes that gap by running the same Express app in both. In development, the Vite dev server that serves the front end mounts the real server app as middleware, the exact one production runs, so an API request in dev is handled by production's code with no proxy translating between them. In production the same app runs on its own, serving the built front end as static files. The result is the one that matters: what you test is what you ship.
Built to swap at the edges
A modular monolith is not a monolith that resists change. The core is fixed and simple, but the things that legitimately differ from one deployment or one workspace to the next are pluggable behind interfaces, and they are wired in by constructor injection rather than reached through global state. A component is handed what it depends on when it is built; it does not go looking for services in a shared bag. That is why a seam holds: a part can be replaced without reaching into the code that uses it.
Four seams carry most of the variation:
- Where the work runs. Every sandbox host, Local Docker, Azure Container Apps, a BYO Kubernetes operator, sits behind one sandbox-provider interface, and a resolver picks the right one for a given profile. When a profile names no host, the resolver falls back to a known default rather than an arbitrary one, so an unconfigured workspace still lands somewhere predictable. Adding a host kind is a new implementation of that interface, not a change to the code that launches agents. Deployment and hosting covers the host model.
- Which model answers. Each AI runtime, Claude, Codex, Copilot, sits behind a runtime startup-auth provider, so the engine that drives a turn is selected, not hard-coded. The agent runtime and tool surface covers what the agent can do once it is running.
- What tools are connected. Tenant MCP servers attach to a sandbox profile through a configurable connection with a pluggable auth resolver, so a workspace's connected tools are configuration, not code.
- Which git provider you use. GitHub and GitHub Enterprise sit behind a repository-provider abstraction keyed by kind. The code and git model covers how a pull request gets made.
What it deliberately isn't
The clearest way to describe the architecture is by what it leaves out, and each absence is a choice that buys something.
- No microservices. One deployable unit, one container image, one process. There is no service mesh to operate, no network hop between internal components, no partial deploy where one service is a version ahead of another. The cost of a feature that spans areas is a function call, not a distributed transaction.
- No ORM. The data layer talks to Azure Cosmos DB through its SDK directly, with queries you can read. There is no object-relational mapper translating your intent into SQL you did not write, and no migration framework guessing at schema. The data and tenancy model is the full account.
- No message queue. Background work does not ride a broker. There is a real-time channel to the sandbox operators, but it carries live messages, not a job queue. How scheduled and background work runs without one is the next section.
- No Redis. Caching is in-process. A permission bundle or a piece of content is held in a bounded in-memory cache inside the same process that uses it, so there is no cache tier to run, secure, or invalidate across the network.
- No GraphQL. The API is plain REST over Express, internal endpoints returning JSON. There is no schema layer or resolver graph between a route and the store it reads.
None of these is a gap waiting to be filled. They are the things a small, legible system does not need, and leaving them out is what keeps the whole platform something one engineer can reason about end to end.
Async work without a message queue
The honest question this raises is how scheduled and background work happens with no broker. The answer is in-process. Recurring jobs, the MCP catalog sync, warm-pool and volume cleanup, flow-step dispatch, run on an in-process cron scheduler, and that scheduler runs on a single designated replica so the same job does not fire twice. A recurring job is a heartbeat rather than a one-shot: if that replica restarts, the schedule resumes on its next tick and re-evaluates the current state, so no work is missed forever because a single tick was dropped. Longer-running work like a flow run or a background task persists its state to the database as it goes, so a restart resumes it from where it was rather than losing it. The durability lives in the store, not in a queue that has to be stood up and kept healthy.
This is the trade a modular monolith makes on purpose: fewer moving parts to operate, in exchange for a scheduler scoped to one replica instead of a worker fleet to keep in sync, and one obvious place a job fires.
Internal endpoints, not a public API
The /__ endpoints are internal. They are the contract between Disco Parrot's own front end and its own server, and they are free to change as the product changes. There is no public, stable API today, and nothing on this page should be read as one. If and when a public API exists, it will be a documented surface of its own. Until then, the way to automate against Disco Parrot is through the product: its flows, its skills, and its MCP tools, not by calling these paths directly.
Why the system is built this way
The reason to keep a platform this small is that an agent platform is already doing something hard: letting software act on your code, your tools, and your data, under review. Every additional service is another place a credential lives, another boundary to secure, another thing that can be a version out of step during a deploy. By collapsing the system to one service and one app, with the genuinely variable parts isolated behind interfaces, Disco Parrot spends its complexity budget where the product is hard, the agent runtime, the sandbox isolation, the permission model, and refuses to spend it on infrastructure that mostly exists to hold other infrastructure together. The payoff is a system you can read, operate with a small team, and reason about during a security review, because the answer to "what talks to what" is short.
For a developer, the model to keep is one Express service and one React app, meeting at the /__ line, with the sandbox host, AI runtime, MCP tools, and git provider behind interfaces that are injected, not located. Adding a host or a runtime is a new implementation, not surgery on the core.
For a platform engineer, the operational story is one image and one process, no broker, no cache tier, no mesh. Background work is an in-process cron scheduler pinned to a single replica plus state persisted to the store for resume. What you deploy in production is the same app you run in development.
For an enterprise reviewer, fewer parts is fewer places for a credential to sit and a smaller surface to assess. There is one boundary between the app and the API, every server route declares the permission it needs, and an unguarded route is caught by the test suite before it can ship; in production the same check logs rather than blocking the boot. The deep version of that control is on approved actions and least privilege.
For a prospect comparing platforms, the thing to weigh is operability. A constellation of services is a constellation of things to run, secure, and keep in sync. Disco Parrot is one service and one app, which means the cost of running it, and the cost of trusting it, is something a small team can actually carry.
Where your work is stored and how one workspace stays one workspace.
What the agent can do once it is running, and how each write is checked.
The single deployable unit and where you can run the work.
The whole security model on one page.