← Selected work

AgentOS

An operating model for personal AI agents: say what the system is in data, and let drift surface as a diff.

Stack: YAML + JSON Schema · Python validator · git · Hermes cron fleet Status: Canonical, running daily (private) Links: github.com/achagani
Product shot — the ontology, the validator, and a drift diff caught by the daily reconcile pass (recreated from the running system).
Product shot — the ontology, the validator, and a drift diff caught by the daily reconcile pass (recreated from the running system).

01The problem

Personal AI agents fail by accretion. A mail pipeline here, a morning digest there, a browser automation wired to one shell script and a prompt that says "never send money actions" somewhere in the system prompt. Six months in, nobody — including the agent — can answer basic questions: what is this agent allowed to do? Which job writes which file? Which policy is enforced, and which is a hope expressed in prose? Policies drift from behavior, context bleeds across unrelated work, and the failure mode is quiet until it isn't.

02The approach

AgentOS treats the agent fleet as a specification problem. The core is a versioned ontology — v1.4.0 on schema version 3 — written in YAML and validated against a JSON Schema before anything runs. It defines closed vocabularies (domains: local / external / comm; target classes: normal / secret / financial / physical / identity; verdicts: deny / confirm) and a typed graph of services, tools, jobs, channels, threads, and policies. Twelve machine-checkable invariants hold it together; my favorite: a rule with no gate is a wish.

A separate binding file maps every ontology ID to a live harness address: cron job refs, CDP ports, mount points, credential handles. Switching agent harnesses means rewriting only the binding; the ontology rides along untouched. Reconciliation passes diff spec against reality: a cron job that exists but isn't declared, a declared job with no scheduler ref, a policy naming an enforcement mechanism that doesn't exist in the binding. Each is a validator error, so drift shows up as a failing check — a diff, not an incident.

03Trade-offs

Declarative YAML over code — YAML is less expressive, and I've felt that cost. In exchange: every rule is human-readable, git-diffable, and mechanically checkable. An unreadable policy is an unenforceable one.
Policy tiers, and an honest gap — enforcement is graded: T1 is prompt-tier (instructions in the agent's "soul"), T2 is mechanism-tier (allowlists in a bridge config, vault tools), T3 is capability-absence (the script literally has no shred code path). Invariant 9 says no policy may rest solely on T1 — it must name a T2/T3 mechanism or carry an explicit upgrade_path. Several policies are still prompt-tier with a declared upgrade to scope isolation. The ontology doesn't hide that; it tracks it as debt.
The hallucination lesson — the agent once announced a version release that never happened, citing a commit that didn't exist. That produced the load-verification ritual: a post-commit hook regenerates a literal load line — version, schema, commit hash — and every session must open by quoting the freshly-read file verbatim. Composing the line from memory is forbidden; a missing or unparseable load line must be announced as a failure to load. Trust, but read the file.
The ownership firewall — Tasks are human-owned; AgentJobs are agent-owned. An agent may append to a task's log but never mark a task done without explicit human confirmation, and the log is append-only: corrections get a new line, never a rewrite.

04Under the hood

A pre-commit hook blocks any commit that fails schema validation. The cron fleet — mail pipeline, morning digest, news digest, inference watchdog, job-search sweep — each carries its scheduler ref in the binding, and every job's success or failure is routed by explicit route rules or declared silent. Memory is typed the same way: every retain call carries tags like thread:job-search, entity:job-mail-pipeline, rel:serves, so threads are first-class graph nodes and cross-thread links (job-search ⟷ apartment-search) are declared edges, not implied vibes. Personas are enforcement envelopes — each agent declares which stores it can touch, which models it may use, and which channels it may speak on. It's the same discipline I ran at platform scale, pointed inward at one person's life.

← All workNext →