Skip to content
66 changes: 66 additions & 0 deletions docs/integration-tiers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# AgentTower Integration Tiers (research note)

Status: Research note (reference only) — v0.2
Date: 2026-06-18

> **Research only — not the authoritative source.** The connection-tier model is
> formalized in the OpenSpec change `openspec/changes/agent-connection-tiers/`
> (`proposal.md`, `design.md`, and the `agent-integration` spec delta). For any
> normative description of the tiers, the two axes, integration modes, the
> router-vs-puppeteer boundary, the adoption story, or the no-network-listener
> invariant, read that change — **not this note.** This file is kept only as an
> orientation/on-ramp plus a little extra comparative context, to avoid the two
> drifting apart.

## Orientation: the connection-strength ladder

Per agent, AgentTower negotiates the strongest available channel and always
falls back to the tmux floor. (Full normative model: `agent-connection-tiers`.)

| Tier | Channel | Inbound (events) | Outbound (delivery) | Works on |
| --- | --- | --- | --- | --- |
| **0 — tmux** | `pipe-pane` + paste-buffer | scraped output, rule-classified | paste-buffer + Enter | _anything_ (universal floor; ships today) |
| **1 — native harness** | hooks / MCP / stream-json | exact harness events | structured message delivery the harness accepts | Claude / Codex, per capability |
| **2 — Omnigent** | Omnigent session API / SSE | uniform structured events | hand off to Omnigent to drive | any harness Omnigent wraps |

Two settled decisions anchor the model (both specified normatively in the
design): **AgentTower is the router, not the puppeteer** (agents report *into*
it; it never drives an agent's task loop or intercepts tool calls), and
**Omnigent is the puppet master** AgentTower hands off to for action-level
driving.

## What the authoritative change covers

Rather than restate it here, see `openspec/changes/agent-connection-tiers/` for:

- the tier ladder and Tier-0-as-floor guarantee;
- independent inbound/outbound axis negotiation;
- the per-agent `integration` mode (`auto` / `tmux-only` / `native` /
`omnigent`);
- tier-independent outbound safety (FEAT-009 gate + kill switch in front of
every tier);
- first-class adoption of pre-instrumented panes;
- the no-network-listener invariant (hooks call the CLI over the Unix socket;
the MCP server is a stdio bridge to that socket).

## Extra comparative context (the part not in the design)

This is the background that motivated the model and is not duplicated in the
normative change:

- **Why Omnigent is Tier 2, not a competitor.** See
`docs/related-work-omnigent.md` — Omnigent *wraps and drives* agents; AgentTower
*observes and routes* unmodified ones. Tier 2 is the deliberate hand-off seam,
not a merge of the two products.
- **Native harness surfaces that make Tier 1 possible.** Claude Code exposes
`-p`/`--print` headless with `--output-format stream-json` /
`--input-format stream-json`, lifecycle **hooks** (PreToolUse / PostToolUse /
Notification / Stop), and **MCP**. Codex exposes a headless `exec` mode, a JSON
output mode, and an MCP server mode. **Codex exact flag spellings must be
confirmed before they enter any implementing feature's tasks** (tracked in the
change's tasks).
- **The realism constraint.** Strong tiers generally require control at session
*startup* (hooks/MCP load at start; a running TUI can't switch into
stream-json mid-flight). That is why managed launch and pre-instrumented
adoption are the two unlock points, and why Tier-1 inbound via hooks is the
recommended first step.
141 changes: 141 additions & 0 deletions docs/related-work-omnigent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Related Work: Databricks Omnigent

Status: Research note (reference only) — v0.1
Date: 2026-06-18

> **Research only.** This is a related-work/reference note. It records no
> committed scope and modifies no canonical spec. Proposed AgentTower scope
> derived from this analysis lives under `openspec/changes/` (the OpenSpec
> change flow), not in this file. The connection-tier model in particular is
> formalized in `openspec/changes/agent-connection-tiers/`.

This note compares AgentTower with **Omnigent**, the open-source "meta-harness"
that Databricks released (Apache-2.0, mid-June 2026). The two tools share a
goal — coordinating multiple AI coding agents — but sit at opposite ends of the
coupling spectrum. This doc records the comparison and the Omnigent-derived
ideas that are candidates for AgentTower scope.

Primary sources:

- Databricks blog — "Introducing Omnigent: A Meta-Harness to Combine, Control
and Share Your Agents"
- GitHub — `omnigent-ai/omnigent`

## 1. One-line framing

> **Omnigent is a meta-_harness_ — it runs your agents. AgentTower is a
> meta-_observer/router_ — it coordinates agents that are already running.**

Same neighbourhood, opposite ends of the coupling spectrum. AgentTower could
even observe panes that happen to be Omnigent-launched sessions.

## 2. What each tool is

**AgentTower** is a local control tower that **observes and routes between
agents that already exist** in tmux. It does not launch or wrap agents. It
discovers tmux panes inside bench containers, lets a human label them
`master` / `slave` / `swarm`, tails their output via `tmux pipe-pane`,
classifies events (`waiting_for_input`, `test_failed`, …), and safely routes
structured text notifications between panes via paste-buffers. Host daemon
(`agenttowerd`) plus thin container clients over a Unix socket; SQLite + JSONL;
no network listener; CLI-first.

**Omnigent** is a **meta-harness that wraps and launches agents** behind a
uniform API. A `runner` executes Claude Code / Codex / Cursor / Pi / OpenAI
agents inside OS sandboxes (macOS `seatbelt`, Linux `bubblewrap`, or cloud
sandboxes via Modal / Daytona / Islo), and an optional `server` adds policy
enforcement, a web UI (`localhost:6767`), and **live session sharing by URL** so
teammates can watch, co-drive, or fork a session from any device. Python 3.12+
with a TypeScript harness CLI; `uv` packaging.

## 3. Where they overlap

| Dimension | AgentTower | Omnigent |
| --- | --- | --- |
| Core goal | Coordinate many parallel agents | Coordinate many parallel agents |
| Multi-harness aware | Capabilities: claude, codex, gemini, opencode | Wraps claude code, codex, cursor, pi, openai |
| Governance | Permission gates, routing kill-switch, no-input-to-unknown | Stacked policies: ask-before-shell, spend caps, tool-call limits |
| Audit trail | JSONL event history | Policy checks every action (allow / block / ask) |
| Sandbox-conscious | Bench / devcontainer-first | Omnibox OS sandbox + cloud sandboxes |
| Local-first option | Yes (only option) | Yes (plus cloud / server modes) |

## 4. Where they fundamentally differ

| | AgentTower | Omnigent |
| --- | --- | --- |
| Relationship to the agent | Observer / router — agents run independently in tmux; AT attaches from outside | Harness / wrapper — AT _is_ the thing that launches and mediates the agent |
| Coupling | Loosely coupled; zero changes to Claude / Codex / tmux | Tightly coupled; agent runs _inside_ its runner with a uniform tool API |
| Who drives orchestration | A human-designated `master` agent pane drives; AT is just transport | The server / policy layer + uniform API drives composition |
| Control mechanism | tmux pane I/O (paste-buffer + Enter) | Programmatic API + OS sandbox interception (incl. network transforms) |
| Agent-state knowledge | Inferred from terminal output (conservative, rule-based) | Native (it owns the session) |
| Collaboration | None (single operator, CLI) | First-class: share session URL, co-attach, fork, OIDC multi-user |
| Deployment | Host daemon + container clients, no network listener | CLI + optional server, Docker / Render / Fly / Modal, reachable "from your phone" |
| Substrate scope | tmux + Docker bench containers specifically | Any wrapped harness, local or cloud sandbox |

## 5. Why they don't really compete

- **Omnigent owns the agent.** It is an SDK / framework — you build _on_ it, and
the agent exists only because Omnigent launched it inside its sandbox with its
tool API. That is why it can do clean policy interception and URL sharing: it
sits _in_ the request path.
- **AgentTower watches agents it does not own.** It is deliberately
non-invasive (PRD non-goal #1: don't replace Claude / Codex / tmux; success
metric: "without requiring changes to Claude, Codex, tmux, or Docker"). That
is why it must _infer_ state from terminal scrollback and route via
safe-but-fragile paste-buffers. It sits _beside_ the path.

So AgentTower is closer to a **tmux-native NOC / observability layer + message
bus**, while Omnigent is a **multi-harness agent runtime / SDK**. Omnigent's
`runner` is precisely the part AgentTower deliberately refuses to be.

**Guardrail for AgentTower:** do not converge toward Omnigent's tight coupling.
The value proposition is coordinating _unmodified_ agents in _existing_
tmux/bench setups. Adopting a wrapping runner would turn AgentTower into a
competitor of both Omnigent and Claude Code, rather than a complement.

## 6. Omnigent-derived features (candidate scope)

The following ideas fit AgentTower's non-invasive thesis. They are **candidates
only** — not committed scope and not yet written into any canonical spec. They
are the raw input for a comprehensive OpenSpec proposal; any adopted item will
be captured under `openspec/changes/`. They are listed here with the
AgentTower-appropriate framing.

1. **Layered / stacked policies.** Omnigent stacks policies at server, per-agent,
and per-session levels (ask-before-shell, token-spend caps, tool-call
limits). AgentTower today has a per-pane `send_input_allowed` boolean plus a
global routing kill switch. A layered policy model (global → per-agent →
per-route) generalises this and lands the existing "explicit per-agent
permission grants" item in architecture §24. AgentTower's version governs
_routing/input delivery_, not agent tool calls (which it cannot see).

2. **Session sharing / co-attach / fork.** Omnigent's headline collaboration
feature: share a live session by URL, let a teammate co-drive, or fork the
conversation. For AgentTower this maps onto multi-operator support over the
FEAT-011 `app.*` backend — multiple humans observing the same registry/event
stream, with read-only "watch" vs. permitted "co-drive". This is the natural
answer to PRD Open Question #2 (TUI vs. web vs. CLI) and is V2 because MVP has
no network listener.

3. **Pluggable execution-sandbox backends.** Omnigent treats local OS sandboxes
and cloud sandboxes (Modal / Daytona) as interchangeable execution targets.
AgentTower's analogue is treating the bench container as one _substrate
backend_ among several (host-only tmux, future remote/cloud bench) behind the
discovery interface — additive to the existing "host-only tmux discovery"
backlog item.

4. **Reachable-from-anywhere / mobile surface.** Omnigent makes sessions
reachable from a phone. AgentTower's MVP is explicitly no-network-listener;
this is a deliberate V2 item, gated behind an authenticated transport, and
should reuse the FEAT-011 contract rather than scrape CLI output.

5. **Network-egress policy at the boundary.** Omnigent's Omnibox can transform /
restrict agent network requests. AgentTower cannot intercept an unmodified
agent's syscalls, but it _can_ record this as a known capability gap and, if
ever needed, document an opt-in container-network-policy recommendation
rather than implement interception itself.

Items 1–3 are the highest-leverage and lowest-risk for AgentTower's model.
Items 4–5 are noted for completeness but carry the most tension with the
local-first, non-invasive constitution and should not be pursued without an
explicit decision.
60 changes: 60 additions & 0 deletions openspec/changes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Omnigent-Derived Change Family — Roadmap

This directory holds a coordinated family of OpenSpec changes derived from the
AgentTower ↔ Omnigent analysis in `docs/related-work-omnigent.md` (research
only) and `docs/integration-tiers.md` (research only). The changes are
independent OpenSpec proposals; this note records how they fit together.

## Dependency / build order

```text
agent-connection-tiers (A) ── foundation: how AT connects to an agent
│ (Tier 0 tmux / Tier 1 native / Tier 2 Omnigent)
├── routing-policy-layers (B) ── layered delivery policies; composes with
│ the tier-independent outbound gate
├── discovery-backends (D) ── pluggable substrates feeding the registry
│ (independent of B)
└── app-collaboration (C, V2) ── multi-operator watch/co-drive over
the FEAT-011 app backend; ideally
composes with B
```

Recommended order: **A → B → D → C**. B and D are largely independent and can
proceed in parallel; C builds on the app backend and ideally on B.

## Shared guardrails (every change)

- **No network listener** — C/E gated behind a separately decided authenticated
transport.
- **Router, not puppeteer** — AgentTower routes; Omnigent (Tier 2) drives.
- **No host-absolute paths** in any artifact.
- Every requirement carries at least one scenario (`openspec validate --strict`
clean).

## Dispositions of the remaining candidates

- **E — reachable-from-anywhere / mobile:** deferred non-goal. Recorded inside
`app-collaboration` with the gate it needs (authenticated transport + a
deliberate reversal of the no-network-listener stance). Becomes its own change
only if that gate is opened.
- **F — agent network-egress policy:** advisory only. AgentTower cannot
intercept an unmodified agent's syscalls, so this is a documented capability
gap (and at most an opt-in container-network recommendation), not a change.

## Bench ownership

Per `AGENTS.md` (Single-Bench Feature Ownership), every feature is owned by
exactly one execution bench. All four changes are backend/daemon/contract work
and are owned by **`py-bench`** (Python daemon, CLI, and local `app.*`
contracts). `app-collaboration` defines only the **backend contract** for
multi-operator roles; any Flutter desktop UI that consumes it is a **separate
`flutter-bench` follow-up feature**, split per the AGENTS.md cross-bench rule.

## Changes

| ID | Change | Capability | Owner (bench) | Status |
| --- | --- | --- | --- | --- |
| A | `agent-connection-tiers` | `agent-integration` | `py-bench` | proposed (validated) |
| B | `routing-policy-layers` | `routing-policy` | `py-bench` | proposed |
| D | `discovery-backends` | `discovery-backends` | `py-bench` | proposed |
| C | `app-collaboration` | `app-collaboration` | `py-bench` (Flutter UI → separate `flutter-bench` feature) | proposed (V2) |
2 changes: 2 additions & 0 deletions openspec/changes/agent-connection-tiers/.openspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-06-18
3 changes: 3 additions & 0 deletions openspec/changes/agent-connection-tiers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# agent-connection-tiers

Per-agent connection-strength tier model (Tier 0 tmux / Tier 1 native harness / Tier 2 Omnigent hand-off)
Loading
Loading