fort

module
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 22, 2026 License: MIT

README

Fort

Fort

A durable chat service for agents — across frameworks, conversations, and computers.

In Fort, each Channel is a stable named Agent with one permanent Home Conversation and optional pinned secondary Conversations. Groups put two to six exact Agents in one durable chat. Additional Agent-to-Agent work happens only through explicit, attributed, bounded Handoffs; it is never inferred from prose or silently rerouted. Agent-owned Routines return their result to an exact Conversation.

Under that product surface, Fort retains deterministic orchestration: routing uses fixed rules (no model in the routing path), every execution pins an exact behavior, framework profile, model, adapter, authority, and computer revision, and multi-step work pauses at human gates. Native workers run local agent CLIs; the approved cloud architecture uses Vercel for the stateless application tier and Supabase Postgres for the durable ledger.

Built native per the Agent Ops Backlog (rev. 2). The original TypeScript prototype was an experiment; this Go build is the delivered project. The native foundation remains governed by specs/021-fort-native.md; the cloud Agent, Group, Handoff, and Routine model is governed by specs/047-vercel-supabase-cloud-control-plane.md and specs/048-stable-agents-group-chats-and-handoffs.md.

Two planes, two modes (one binary)

fort serve      # full plane: control + deterministic execution
fort control    # LEGACY ADMIN / ROLLBACK CONTROL PLANE ONLY
                # no router/runtime/DAG or agent CLIs needed
  • Control plane — the typed Primary Channels surface plus the durable scheduler, state APIs, and explicit off-mode legacy administration. Depends on nothing but the store.
  • Execution plane (deterministic) — the router, the native runtime that spawns claude/codex/hermes/openclaw, and the DAG engine. Optional — plug it in for fort serve, leave it out for fort control.

Architecture

One Go module, hard module seams (enforced by core/arch_test.go):

Module Role
core/ deterministic orchestration: rules, router, runtime interface, store, engine, graph, inbox, flow, scheduler, server
cloud/ stateless cloud-control contracts, signed service trust, and application-encrypted bodies
api/ bounded Vercel Go Function entrypoints; never starts a native runtime or permanent loop
exec/ native execution: NativeRuntime (PTY-less CLI executor), FakeRuntime, gateway (budgets/tracing/failover)
ui/ Primary Channels HTTP/SSE + Web, with off-mode legacy administration; imports none of the execution components
control/ adapters wiring execution into the ui ports (or a queue-only dispatcher)
gateway/ authenticated Next.js gateway and bounded reconnecting Node SSE transport
supabase/ private Postgres ledger migrations and database contract tests
rules/, flows/ the routing ruleset and flow definitions (YAML)
cmd/fort/ the fort CLI
ui/apple/ Phase 1 FortKit package + explicit iPhone and Mac clients

Design tenets: routing is deterministic (proven by tests, zero model calls); only task nodes invoke inference; every state change is an append-only event (the feed + board are derived, replayable).

Quickstart

# install
brew install tobsai/tap/fort     # or: make build -> ./bin/fort (needs Go 1.22+)

fort control                                  # explicit legacy admin/rollback
# Phase 1 preview, with the execution plane + required readiness inputs:
FORT_PRIMARY_CHANNELS=preview fort serve

The binary embeds a default ruleset, so fort serve works from any directory with no checked-out repo.

Then open / for Private Channels. Setting FORT_PRIMARY_CHANNELS=off (the default) intentionally restores the legacy admin surface instead. The CLI continues to expose deterministic orchestration commands:

fort route --dry-run --label bug "null deref"      # -> codex
fort task add --label research "read the repo"      # auto-route + run natively
fort task breakdown "add search"                    # planner -> backlog sub-tasks
fort flow run ship-feature --input "add search"     # DAG, pauses at gates
fort gate approve <run> plan_gate

FORT_FAKE=1 runs a token-free fake runtime for demos/CI.

Break a goal into backlog sub-tasks with fort task breakdown "<goal>" (or the explicit off-mode legacy admin board). A planner agent (FORT_PLANNER, default claude) decomposes it into source=agent items for deterministic dispatch. It needs the execution plane (fort serve); control-only mode returns 409.

Clients

The shipping clients share the typed Spec 044 Primary HTTP/SSE contract. The older orchestration contract remains documented only for off-mode rollback and administration in docs/notes/event-contract.md.

  • Web — served at GET / in preview or primary: private Channels, canonical transcripts, a text-only composer, read-only Scheduled, Needs you, and Settings/Recheck in the three device-local themes.
  • Appleui/apple: the same Phase 1 contract in native iPhone and Mac clients through one closed FortKit package. The iPhone archive contains no Watch, complication, or CarPlay scene. make apple-build compiles both shipping targets. Deploy: docs/notes/testflight.md.

Multi-machine (spec 022, spec 024)

One control plane can orchestrate agents across several hosts (e.g. a Mac Mini + a MacBook Pro). Fort routes each task to the agent (deterministic, as always) and then to a machine that offers it — local or remote — streaming the run back to the board you're watching. Remote execution is just another runtime.Runtime, so the core is unchanged.

The easy path is fort mesh: it mints and distributes the shared token and manages the registry for you — no file edits.

# hub (laptop)
fort serve &
fort mesh invite            # prints: fort mesh join http://100.x.y.z:4087 --code XXXX-XXXX

# new machine (paste the printed line)
fort mesh join http://100.x.y.z:4087 --code XXXX-XXXX
fort serve

fort mesh invite mints the durable mesh token on first use (the hub then also accepts inbound mesh exec) and prints a paste-ready fort mesh join line good for one use within its TTL (--ttl, default 15m, capped at 1h). fort mesh join probes $PATH for agent CLIs (or takes --agents a,b), registers with the hub, and writes this machine's identity. fort mesh remove <name> drops a machine from the registry — see the token-rotation runbook in docs/notes/threat-model.md for what it does not do.

The off-mode admin board shows every host and tags each run with its machine; legacy chat and fort task add --machine <host> can pin a target. Placement is deterministic: an explicit pin, else the local host if it offers the agent, else the first host in the registry that does. Inter-host /api/exec is bearer-token authenticated; keep it on a trusted LAN.

Manual / hand-managed alternative

You can still hand-manage the registry and token instead of fort mesh:

cp machines.example.yaml machines.yaml    # name + url + agents per host

# on each host that runs agents (expose on the LAN, share one token):
FORT_ADDR=0.0.0.0:4087 FORT_NODE_TOKEN=shared-secret fort serve

# on the host you drive (also knows the registry):
FORT_MACHINES=machines.yaml FORT_NODE_TOKEN=shared-secret \
  FORT_NODE_NAME=mac-mini FORT_ADDR=0.0.0.0:4087 fort serve

Unset FORT_MACHINES ⇒ classic single-machine mode. When FORT_MACHINES is set, fort mesh refuses to write to it (it only manages its own file).

Provider boundary

  • Discovering an installed framework does not authorize it for production. Every real runtime family keeps its own reviewed identity, readiness, lifecycle, authority, and terminal-normalization contract. Fake runtimes can prove deterministic state transitions but cannot satisfy cross-framework production acceptance.
  • Provider credentials, CLI OAuth state, workspace files, browser sessions, and source-managed memory remain on the enrolled worker unless a later approved contract says otherwise.

Docs

Agent Ops Backlog/ (the plan), docs/notes/ (recon, decisions, threat model, control-plane, event contract, distribution, TestFlight), specs/ (specs).

License

MIT © 2026 Tobias Gunn.

Directories

Path Synopsis
api
v2
cloud
controlapi
Package controlapi contains stateless HTTP handlers for Fort's cloud control plane.
Package controlapi contains stateless HTTP handlers for Fort's cloud control plane.
migration
Package migration implements Fort's offline, encrypted SQLite/Postgres migration evidence.
Package migration implements Fort's offline, encrypted SQLite/Postgres migration evidence.
postgres
Package postgres implements Fort's account-scoped cloud ledger on Postgres.
Package postgres implements Fort's account-scoped cloud ledger on Postgres.
securebody
Package securebody encrypts sensitive Fort record bodies before they enter the cloud ledger.
Package securebody encrypts sensitive Fort record bodies before they enter the cloud ledger.
cmd
fort command
Command fort is the fort-native CLI (backlog AO-018): route --dry-run, task add, runs list, run logs, gate, flow, schedule, and serve (the core daemon).
Command fort is the fort-native CLI (backlog AO-018): route --dry-run, task add, runs list, run logs, gate, flow, schedule, and serve (the core daemon).
Package control provides the adapters that plug Fort's deterministic components into the control-plane ports (ui.Dispatcher, ui.FlowRunner).
Package control provides the adapters that plug Fort's deterministic components into the control-plane ports (ui.Dispatcher, ui.FlowRunner).
Package core is the umbrella for Fort's deterministic orchestration modules: rules, router, runtime (the executor interface), task, store, graph, inbox, flow, scheduler, event, and server.
Package core is the umbrella for Fort's deterministic orchestration modules: rules, router, runtime (the executor interface), task, store, graph, inbox, flow, scheduler, event, and server.
capability
Package capability owns Fort's closed capability catalog, strict plan contract, safe inventory projection, and deterministic placement solver.
Package capability owns Fort's closed capability catalog, strict plan contract, safe inventory projection, and deterministic placement solver.
config
Package config loads fort-core configuration from the environment with sane defaults (backlog AO-011).
Package config loads fort-core configuration from the environment with sane defaults (backlog AO-011).
conversation
Package conversation defines Fort's durable shared-conversation model.
Package conversation defines Fort's durable shared-conversation model.
engine
Package engine wires the deterministic router to native execution and the state store (backlog AO-015): a submitted task auto-routes, is persisted with its matched rule, and runs natively with zero manual assignment.
Package engine wires the deterministic router to native execution and the state store (backlog AO-015): a submitted task auto-routes, is persisted with its matched rule, and runs natively with zero manual assignment.
flow
Package flow loads and validates Fort flow definitions (YAML) into graph.Flow values (backlog AO-026/027).
Package flow loads and validates Fort flow definitions (YAML) into graph.Flow values (backlog AO-026/027).
graph
Package graph is Fort's deterministic DAG engine (backlog AO-021..025).
Package graph is Fort's deterministic DAG engine (backlog AO-021..025).
inbox
Package inbox sources new tasks from a watched directory and submits them to the engine (backlog AO-015: "watched file/dir" task source).
Package inbox sources new tasks from a watched directory and submits them to the engine (backlog AO-015: "watched file/dir" task source).
ledger
Package ledger defines Fort's durable control-plane persistence contracts.
Package ledger defines Fort's durable control-plane persistence contracts.
machines
Package machines is Fort's static machine registry and deterministic placement (spec 022).
Package machines is Fort's static machine registry and deterministic placement (spec 022).
playbook
Package playbook defines Fort's reusable, deterministic agent pipelines.
Package playbook defines Fort's reusable, deterministic agent pipelines.
requestid
Package requestid carries one safe correlation identifier across HTTP, orchestration, and durable run creation without carrying request content.
Package requestid carries one safe correlation identifier across HTTP, orchestration, and durable run creation without carrying request content.
router
Package router is Fort's deterministic matcher engine (backlog AO-013).
Package router is Fort's deterministic matcher engine (backlog AO-013).
rules
Package rules defines Fort's deterministic routing-rule schema and a strict parser for it (backlog AO-012).
Package rules defines Fort's deterministic routing-rule schema and a strict parser for it (backlog AO-012).
runtime
Package runtime defines the execution seam (backlog AO-014, spec §6.2).
Package runtime defines the execution seam (backlog AO-014, spec §6.2).
scheduler
Package scheduler fires flows on cron schedules and one-shot times (backlog AO-028) — the basis for "assign and walk away" and recurring digests.
Package scheduler fires flows on cron schedules and one-shot times (backlog AO-028) — the basis for "assign and walk away" and recurring digests.
server
Package server is fort-core's local HTTP/WS API (backlog AO-011): /health, graceful shutdown, and the event/command surface the fort-ui module consumes (the live-feed and command routes are added in Phase 3 on top of this).
Package server is fort-core's local HTTP/WS API (backlog AO-011): /health, graceful shutdown, and the event/command surface the fort-ui module consumes (the live-feed and command routes are added in Phase 3 on top of this).
store
Package store is Fort's SQLite state store (backlog AO-016, spec §6.6): run, node_run, route_decision, and an append-only event log.
Package store is Fort's SQLite state store (backlog AO-016, spec §6.6): run, node_run, route_decision, and an append-only event log.
task
Package task defines the Task — the atomic routable unit of work in Fort.
Package task defines the Task — the atomic routable unit of work in Fort.
today
Package today defines the truthful right-rail projection shared by Fort's presentation surfaces.
Package today defines the truthful right-rail projection shared by Fort's presentation surfaces.
transporttrust
Package transporttrust carries authenticated transport provenance across an in-process HTTP handler call.
Package transporttrust carries authenticated transport provenance across an in-process HTTP handler call.
worker
Package worker models Fort's deterministic cloud worker protocol.
Package worker models Fort's deterministic cloud worker protocol.
exec
capability
Package capability owns execution-side capability discovery.
Package capability owns execution-side capability discovery.
cloudworker
Package cloudworker runs one exact cloud-leased target through Fort's native runtime without importing any provider credential or cloud database client.
Package cloudworker runs one exact cloud-leased target through Fort's native runtime without importing any provider credential or cloud database client.
cluster
Package cluster composes a machine's local runtime with remote runtimes for its peers (spec 022).
Package cluster composes a machine's local runtime with remote runtimes for its peers (spec 022).
codexsubscription
Package codexsubscription implements the isolated, subscription-backed Primary Channel execution contract.
Package codexsubscription implements the isolated, subscription-backed Primary Channel execution contract.
fake
Package fake is an in-memory runtime.Runtime for fast, deterministic unit tests (backlog AO-014: "Interface is mockable — a FakeRuntime powers fast unit tests").
Package fake is an in-memory runtime.Runtime for fast, deterministic unit tests (backlog AO-014: "Interface is mockable — a FakeRuntime powers fast unit tests").
gateway
Package gateway is an optional runtime.Runtime decorator (backlog AO-042) that puts spend caps, tracing, and failover in front of any underlying runtime — the role agentgateway/plano play in front of providers.
Package gateway is an optional runtime.Runtime decorator (backlog AO-042) that puts spend caps, tracing, and failover in front of any underlying runtime — the role agentgateway/plano play in front of providers.
meshjoin
Package meshjoin hosts the spec-024 enrollment endpoints on the hub daemon:
Package meshjoin hosts the spec-024 enrollment endpoints on the hub daemon:
native
Package native is Fort's NativeRuntime (backlog AO-014): it spawns agent CLIs itself — no Multica — normalizes their stdout into runtime.RunEvents, injects stdin for Signal (human-in-the-loop), and tracks exit codes.
Package native is Fort's NativeRuntime (backlog AO-014): it spawns agent CLIs itself — no Multica — normalizes their stdout into runtime.RunEvents, injects stdin for Signal (human-in-the-loop), and tracks exit codes.
node
Package node exposes a Fort's local runtime over HTTP so another Fort — the control plane — can dispatch runs to this machine (spec 022).
Package node exposes a Fort's local runtime over HTTP so another Fort — the control plane — can dispatch runs to this machine (spec 022).
relay
Package relay maintains fort serve's outbound tunnel to the 028 gateway: one WebSocket to the broker, per-client-session Noise IK handshakes (exec/relay/secure), and sealed HTTP/SSE service against an injected http.Handler — the transport never imports ui (seam: it moves bytes).
Package relay maintains fort serve's outbound tunnel to the 028 gateway: one WebSocket to the broker, per-client-session Noise IK handshakes (exec/relay/secure), and sealed HTTP/SSE service against an injected http.Handler — the transport never imports ui (seam: it moves bytes).
relay/secure
Package secure is Fort's E2E crypto contract for the relay (spec 028): a Noise IK handshake (X25519) between a client and the daemon's pinned static key, then ChaCha20-Poly1305 AEAD framing.
Package secure is Fort's E2E crypto contract for the relay (spec 028): a Noise IK handshake (X25519) between a client and the daemon's pinned static key, then ChaCha20-Poly1305 AEAD framing.
remote
Package remote dispatches runs to another Fort over HTTP (spec 022).
Package remote dispatches runs to another Fort over HTTP (spec 022).
runtimemux
Package runtimemux keeps legacy execution and the isolated Primary Channel subscription lane mutually exclusive.
Package runtimemux keeps legacy execution and the isolated Primary Channel subscription lane mutually exclusive.
watchdog
Package watchdog bounds silent runtime invocations.
Package watchdog bounds silent runtime invocations.
Package ui is Fort's interface module (backlog Phase 3): the event/command contract (AO-031), the live board (AO-032), the SSE live-feed transport (AO-033), the chat surface (AO-034), the gate inbox (AO-035), and the OpenClaw inbound channel (AO-036).
Package ui is Fort's interface module (backlog Phase 3): the event/command contract (AO-031), the live board (AO-032), the SSE live-feed transport (AO-033), the chat surface (AO-034), the gate inbox (AO-035), and the OpenClaw inbound channel (AO-036).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL