Jared Frieden · AI Systems Architect & Engineer
jared / engine / agent-operating-system

The Agent Operating System

A hub-and-spoke orchestration layer where one architect model routes work to executor agents through a plain-markdown message bus, with deterministic machinery holding the state.

in daily use System · 2026, ongoing Claude CodeObsidianPowerShellGitMulti-CLI executors
Human decisions, gates,course corrections Orchestrator — Claude Code framing · planning · dispatchquality gates · memory Executor CLIs implementation lanes Media / research lanes bounded fan-out Vault — message bus task files + frontmatterfolder = lifecycle state Daemon deterministic state machineno LLM in the loop Review swarm tiered: auto / agent / humanverdicts gate closure Persistent memory file-based, git-backedrules · projects · workarounds brief / sign-off writes TASK-*.md claim & execute deliverables recall / persist moves files on state change verdicts solid = agents and state · dashed = knowledge · amber = deterministic machinery and gates

The problem

One person working across a pile of AI tools ends up with coordination scattered through chat histories that die at the end of each session. There is no shared state, no queue, no audit trail, and every new session starts from nothing. I decided to treat it as an operating-system problem instead: give it processes, a scheduler, a filesystem, and a way to handle interrupts.

The shape

The system is hub-and-spoke. An architect model, Claude Code, makes the decisions, frames the work, and writes the routing artifacts. It does not implement anything. An Obsidian vault of plain markdown files is both the message bus and the state store. Executor CLIs, Codex and Kilo Code among others, claim tasks from the vault asynchronously and hand back deliverables. A PowerShell daemon advances the lifecycle state on its own schedule, and review swarms check completed batches before anything is allowed to close.

Design decisions I would defend

Files instead of services. Every task is a markdown file with frontmatter: assigned model, priority, batch id, risk level, and a scope contract. That keeps the whole coordination layer human-readable, greppable, versioned in git, and safe from any single tool dying on it. There is no coordination database to migrate and no API to break.

The folder is the state machine. A task's directory is its lifecycle stage: pending, blocked, actionable, done. An agent changes state by editing one frontmatter field, and the daemon notices the edit and moves the file. Agents never move files themselves, so two writers cannot race the state, and the daemon repairs any illegal state value on its next sweep. I migrated this contract onto 354 live task files with no data loss, checked by a 184-test suite.

Scope contracts with a drift catcher. Each task declares which files it is allowed to touch, and a script diffs the actual changes against that declaration after the work runs. Expanding scope is fine, but it has to be written down and explained rather than happening quietly.

Tiered review. A batch closes through one of three tiers: automatic when every task was low risk and no drift fired, agent sign-off when the risk is mixed, and human-required for anything high risk, security-sensitive, or spanning projects. The default is the lightest tier that still holds, and what raises it is the declared risk, not how I happen to feel about the batch.

No model in the monitoring loop. Heartbeats, polling, file-watching, reaping stale lanes: all of that is daemon work. Spawning a language model to watch a folder is the most expensive imaginable way to run a cron job.

Continuity across context death

Sessions end, but the work should not. A session that stops partway through an arc writes a structured handoff: what shipped, what is still in flight, and what the next session has to read first. A session-start hook then surfaces pending handoffs, actionable tasks, and batches waiting on review as a briefing, before any new work starts. The system has carried 41 of these handoffs across different models and sessions.

Scale

As of July 2026 the bus has carried more than 440 tasks across 83 batches, over 340 of them completed, backed by 154 purpose-built automation scripts. The task-ID allocator has its own collision-prevention tooling, because parallel sessions reserving the same id turned out to be a genuine failure mode, twice.

What it taught me

Let the deterministic machinery do everything it possibly can, and give the models only the work the machinery cannot do. Every time I moved a responsibility off an agent and onto a script, the system got more reliable and the token bill dropped. What the agents are actually there for is judgment.