Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Command Center and the Sentinel AI agent ship from **one repo, one image, one de
| Code | `backend/app/` + `frontend/` | `backend/app/sentinel_agent/` |
| Process group | `app` | `agent` |
| Command | `uvicorn app.main:app` | `python -m app.sentinel_agent` |
| Machine | 1 GB, always-on, owns the volume | 512 MB, scales to zero, no volume |
| Machine | 1 GB, always-on, owns the volume | 512 MB, always-on, no volume |

Both are the `sentinel-command` Fly app, built from the root `Dockerfile` and deployed by `.github/workflows/deploy.yml`. There is no separate agent app, agent image, agent workflow, or agent lockfile.

Expand All @@ -24,6 +24,8 @@ Four rules follow, and breaking any of them breaks a deploy:
3. **`[processes]` overrides the Dockerfile `CMD`.** The `app` command in `fly.toml` must stay in sync with that `CMD`.
4. **CI path filtering is asymmetric.** `push` is filtered (docs and Markdown only); `pull_request` is **never** filtered. `master` requires `Backend tests (sqlite)`, `Backend tests (postgres)` and `Frontend audit + build`, and GitHub reports *no status at all* for a workflow a path filter skipped β€” so a filtered PR trigger would hang every PR that missed it, presenting as a stuck check rather than a config error.

The agent machine is kept **warm** (`min_machines_running = 1`) rather than scaled to zero. Fly's proxy waits only ~8s for an auto-started machine to bind its port, and this process needs ~10s (Python + the MCP SDK + Sentry + a deferred LiteLLM import) β€” so an auto-started machine was declared unreachable and the wakeup came back `RemoteDisconnected`. It was ~7s before LiteLLM, i.e. always marginal. ~$2/month buys the problem away; see the comment on `[[services]]` in `fly.toml`.

The agent is a separate **process group** rather than a thread in the web app because a run holds base64 frames for up to 270s, and the segment cache is already budgeted 384 MiB of the web machine's 1 GiB. Sharing one machine is how the OOM killer takes every org's streams down at once. Being a separate *app* was never what bought that isolation.

Self-hosting still works the same way: `python -m app.sentinel_agent` runs standalone with `AGENT_MODE=poll` and a per-org `osa_` key, needing no inbound connectivity. Agent docs are in `docs/SENTINEL_AGENT.md`. The code came from the `SourceBox-Sentinel` repo (archived 2026-09-09).
Expand Down
2 changes: 1 addition & 1 deletion docs/SENTINEL_AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ notification fires β”Œβ”€ POST /wakeup (HMAC-signed)
POST /api/sentinel/runs/{id}/start
run agent loop (LLM ↔ MCP tools)
POST /api/sentinel/runs/{id}/complete
return 200 β€” machine idles β†’ auto-stops
return 200 β€” machine stays warm (see fly.toml)
```

## Architecture
Expand Down