Complete Community Edition under Apache 2.0. No telemetry.See the source

Reduce the reach of an injection without pretending it disappears.

Agents City keeps yolo so a committee can work, but narrows what a repository agent can read, write, and authorise. Security is shared across the kernel, credentials, bus, and seat protocol.

Control layers

  1. 01

    Repo cage on macOS

    Claude, OpenCode, and Kimi may start under a generated seatbelt profile: writes denied by default, allowed for the repo and required caches, then credential stores sealed last. Codex uses its native workspace-write sandbox to avoid incompatible nesting.

  2. 02

    Credential broker

    With CITY_BROKER=1 an agent asks an outside process to push or open a PR. Its token is per window and bound to one repo; the default branch and force pushes are always refused.

  3. 03

    Audit chain

    Every served or refused request links the previous hash. Evidence vocabulary separates enforced control, attribution, unknown, ambiguous, and unsupported. Unknown never authorises.

  4. 04

    Path containment

    The cage and broker resolve real paths through symlinks and missing leaves, and refuse repositories placed inside sealed stores.

  5. 05

    Road admission

    An ordered graph checks address, road, sender, and payload. The first blocker decides and returns a stable reason without leaking the allowlist.

  6. 06

    Pairing primitive

    The source tests a short code with a TTL, pending limit, and opaque approval id, but the current beta does not yet wire it into the live road router or CLI. Operational remote onboarding still exchanges public invitations in both directions.

  7. 07

    Untrusted text

    Every inbound message is wrapped in a random boundary and chat-role tokens are defanged. This is defence in depth, not a promise that the model obeys.

Cage controls

The cage never wraps the seat. The seat is not yolo and retains the decision boundary against external context.

CITY_CAGE=0turn off the cage; Codex changes to dangerFullAccess.
CITY_CAGE_DENY=a:bseal extra paths, for example ~/.npmrc.
CITY_CAGE_ALLOW_WRITE=a:badd writable roots for unusual toolchains.
CITY_BROKER=1start the opt-in PR and push broker.
TERMINAL
CITY_BROKER=1 agents-city seatpython3 plugin/scripts/broker.py call pr --title "Add X" --body "Why"

Remote roads

The optional relay authenticates one owner prefix with a credential issued by its operator, accepts only seat-to-seat road envelopes, and may queue offline direct messages for up to 72 hours. road invite neither mints nor shares that credential.

TERMINAL
agents-city road invite product > product.invitation.jsonagents-city road connect product research.invitation.json

What it does not solve

  • Prompt injection still exists; the layers reduce its value and reach.

  • Outbound networking remains open. An agent may still exfiltrate what it can already see inside its own repository.

  • Every process runs as your OS user. The cage is not hostile-process isolation.

  • Linux without sandbox-exec has no seatbelt layer. Use separate users, containers, or a VM for untrusted code.

  • Keychain credentials may work over IPC even when files are sealed; protect branches and use the broker.

Verify the invariants

The repository turns past sharp edges into cross-cutting tests: sealed secrets, profile ordering, unknown without authority, redacted diagnostics, and the seat outside the cage.

TERMINAL
python3 bin/test-security.pypython3 bin/test-cage.pypython3 bin/test-broker.pypython3 bin/test-pairing.py