# Pizza Bot keeps the run going when you close the tab

> Pizza Bot is a local-first inbox for long-running agent work, built with DeepAgents and LangGraph and released under Apache 2.0. One api-server holds the runs while the desktop app, browser and terminal CLI come and go, finished work lands in Unread, and approval requests wait in Action.

**pizza-bot-app/pizza-bot** — A local-first inbox for long-running AI agents, built with DeepAgents and LangGraph.

- Repository: https://github.com/pizza-bot-app/pizza-bot
- Website: https://github.com/pizza-bot-app/pizza-bot/releases
- Stars: 410 · Forks: 37
- Language: TypeScript
- License: Apache-2.0
- Published: 2026-09-19 · Updated: 2026-09-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/pizza-bot-app-pizza-bot

## Unread collects finished runs, Action collects approvals

An agent run that outlives the window you started it in is the problem this project takes on. Work you kick off keeps going after you switch conversations or close the client, and when it stops it does not open a modal in your face. Finished results land in Unread, and approval requests that need a human decision wait in Action. Both queues are global, so moving a conversation into a folder organizes it without hiding it from the inbox.

Approvals sit inside the workflow rather than interrupting it from outside, next to long-term memory, file attachments and desktop notifications. A run that wants to write a file or call a consequential tool pauses until someone decides, and that decision stays visible in Action until it is handled.

## Only the api-server has to stay alive

Checkpointed runs survive client disconnects, and the api-server is the one process that has to remain running. The Electron shell forks and supervises its own api-server, which the README describes as matching the process model of the packaged application, so closing the desktop window does not take the work inside it down. The browser app and the terminal CLI talk to that same server over HTTP/SSE.

Two triggers start work with no conversation open at all: cron and webhooks. A scheduled job that does not need someone sitting at the keyboard is the case this design fits, because nothing about a run requires a browser tab to stay alive.

## One server, four front ends

Node.js 24 or newer is the only prerequisite the README names, and the source build is three commands:

```bash
npm install
npm run build
npm run dev
```

`npm run dev` starts the Vite frontend and the Electron desktop shell, and the shell supervises the api-server. Four front ends can reach that server: the Electron desktop app, a browser for web development or static deployment, a terminal CLI for scripts and remote backends, and a standalone backend for remote Electron, containers or Linux services. A running api-server needs at least one model provider; HTTP clients do not. Configure one under Settings > Providers before starting a live run, because with no provider configured runs fail at the first model call.

## A non-loopback listener is refused without a token and an origin allowlist

Binding the api-server to anything other than loopback is a guarded move, and the compose file states the rule directly above its own configuration:

```yaml
    environment:
      # A non-loopback listener is refused without a token of at least 32
      # characters and an explicit origin allowlist.
      PIZZA_API_TOKEN: "${PIZZA_API_TOKEN:?generate one with openssl rand -hex 32}"
      PIZZA_ALLOWED_ORIGINS: "${PIZZA_ALLOWED_ORIGINS:-http://127.0.0.1:8080}"
    ports:
      - "127.0.0.1:8080:8080"
```

Defaults point inward. The api-server binds loopback, the published port is 127.0.0.1, and the image sets PIZZA_HOST=0.0.0.0 only because it sits behind that mapping. The runtime stage runs as a user created with uid 10001 and /sbin/nologin, keeps data under the /var/lib/pizza-bot volume, and health-checks /ping every 30 seconds. Anyone who turns that host binding on somewhere else inherits the token requirement whether or not they read the note above it.

## Provider choice is set in three different places

Bedrock is the reference path. It accepts an AWS profile, access keys or a Bedrock API key, falls back to AWS_REGION and then to us-west-2, and combines its native catalog with a regional Mantle catalog before routing a model through Converse, the OpenAI Responses or Chat Completions families, or Anthropic Messages depending on the API family the model advertises. Anthropic and OpenAI also take custom base URLs for compatible endpoints, with Anthropic accepting x-api-key or bearer authentication.

Model selection can be overridden per run with PIZZA_MODEL, written as provider:id, and PIZZA_MAX_TOKENS caps output at 8192 by default. Secrets split in two: the desktop protects entered values with Electron safeStorage, while server configuration persists only environment-variable references. The .env.example file is explicit that an exported shell variable always wins over a file value, which decides the outcome when SSO or a process manager sets credentials for you.

## Skills are subagents that stay quiet until their tools are connected

A skill becomes a tool-scoped subagent whose progress appears in the Activity panel, and it does nothing until the tools it declares are enabled and connected. MCP servers come from the UI or from <PIZZA_DATA_ROOT>/.mcp.json, Agent Skills sit under <PIZZA_DATA_ROOT>/skills, and plugins package the two together. Overriding works by id: a custom skill with the same id replaces the Built-in or Plugin version, and removing the customization reveals the original again.

Filesystem reach is granted per folder rather than inherited. Settings > Files is where you add individual read-only or writable folders, and the project states it receives no default home-directory access at all. The Built-in Pizza Bot Guide can explain features, suggest workflows and point at project documentation, which is the sensible first stop before you write a skill of your own.

## One graph engine, and frontends that never import it

The production graph engine is isolated in packages/runtime-langgraph, and frontends consume protocol projections instead of importing runtime or model bindings. The workspace layout shows where the lines are drawn:

```text
apps/        api-server (Hono) | cli | desktop-shell (Electron) | web (React)
packages/    core | runtime-langgraph | inference-providers | plugin-api | plugin-sdk | storage | logging
plugins/     bundled Plugin packages and their packaging workspace
skills/      optional Built-in Agent Skills
tests/       LangGraph compatibility and protocol conformance
```

That split is why the tests directory can hold LangGraph compatibility and protocol conformance suites as separate workspaces, and why replacing the graph engine would be a change inside packages rather than a rewrite of the frontends. Licensing is Apache 2.0 with a NOTICE file at the root. The OSS releases so far are v1.0.0 on 2026-09-08 and v1.1.0 on 2026-09-19, and the last push to the repository was on 2026-10-01.

## Conclusion

Pizza Bot suits teams that already drive agents through a provider API and want a queue instead of a terminal full of half-finished runs, and it suits remote deployments only where someone can hold a token of at least 32 characters and an explicit origin allowlist. It does not suit a team that wants a hosted service with no process of its own, since the api-server is the product and the data root is local. Start by running `npm run dev` on Node 24 and reading SECURITY.md before anything sets PIZZA_HOST away from loopback.

## FAQ

### What is Pizza Bot and who is it for?

Pizza Bot is a local-first inbox for long-running AI agents, built with DeepAgents and LangGraph and released under the Apache 2.0 license. It was developed at Amazon, and its desktop app, web app and terminal CLI all talk to the same api-server over HTTP/SSE.

### What are the Unread and Action queues in Pizza Bot?

Completed work lands in Unread, and durable approval requests land in Action. Conversations can be grouped into folders without hiding matching work from the global Unread and Action queues.

### How do I run Pizza Bot from source?

Node.js 24 or newer is required. Run `npm install`, then `npm run build`, then `npm run dev`, which starts the Vite frontend and the Electron desktop shell. Configure a model under Settings > Providers before starting a live run, since with no provider configured runs fail at the first model call.

### Which model providers does Pizza Bot support?

Amazon Bedrock, Anthropic, Google Gemini, OpenAI, OpenRouter and Ollama are supported. A running api-server needs access to at least one of them, while HTTP clients do not, and a model can be selected with PIZZA_MODEL written as provider:id.

### Can Pizza Bot read files in my home directory by default?

No. You add individual read-only or writable folders under Settings > Files, and the project states that Pizza Bot receives no default home-directory access.

## Sources

- [License: Apache-2.0](https://github.com/pizza-bot-app/pizza-bot/blob/main/LICENSE)
- [pizza-bot-app/pizza-bot on GitHub](https://github.com/pizza-bot-app/pizza-bot)
- [Project website](https://github.com/pizza-bot-app/pizza-bot/releases)
- [README](https://github.com/pizza-bot-app/pizza-bot/blob/main/README.md)
- [Releases](https://github.com/pizza-bot-app/pizza-bot/releases)

---

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