Next.js, Fastify, PostgreSQL, Redis, BullMQ, Docker
Agent Office
Solo architect · Full-stack engineer · Jun 2026 – present
Agent Office is the operator surface of ovari-governance-system: a local-first, Dockerized AI company I designed and built alone. It is not a single chatbot wrapper. The user talks to a seeded organization — root supervisor CsabaOfficer, 17 department leaders, and 55 work-only subagents (73 agents). A request is recalled against Diamond Memory, routed to a leader, executed by subagents, summarized by the leader, then approved by CsabaOfficer before anything reaches the user. Subagents never emit a final answer. Memory, persona, and skill changes that originate from AI are proposals, not writes. PostgreSQL is the operational source of truth; an Obsidian vault is the human-editable mirror. Claude, OpenAI, Gemini, or Codex CLI can run as the provider-agnostic LLM runtime, with per-agent model resources, token ceilings, and prompt caching.
User → CsabaOfficer (root supervisor)
→ Diamond Memory recall + policy
→ Department leader → work-only subagents
→ Leader summary → CsabaOfficer approval → User
Four processes, one contract:
Web (Next.js) → presentation only
API (Fastify) → domain, AI routing, governance
Worker (BullMQ)→ schedules; jobs call the API over HTTP
Converter → FastAPI + MarkItDown document sidecarDeep dive
Why not just a chatbot
Execution goes through organizational rules: delegation, leader summary, supervisor approval. Knowledge is atomized and searchable. Every AI-originated change is a proposal. Untrusted text that enters a prompt is intentionally not treated as instruction. The goal is controllable, auditable, local AI operations — not an unbounded agent.
Hierarchy and org chart
The seeded organization is CsabaOfficer + 17 leaders + 55 work-only subagents. Subagents cannot emit a user-facing answer. Legal or public-sector sensitive output and production-impacting actions take an extra approval. Manual gates such as production_change and host_fs_access can never be auto-approved. The React Flow org chart maps the same hierarchy the runtime uses: status, delegation edges, and per-agent model resources with token ceilings.
Architecture
A TypeScript pnpm monorepo with shared-types (domain), schemas (Zod requests), and config (env + queue names). The web app is presentation-only: every screen loads from the REST API. The Fastify 5 API owns business logic, AI routing, and governance on Drizzle ORM over PostgreSQL 16 (pgvector, FTS, trigram) with ~70 additive SQL migrations. BullMQ workers schedule work but hold no domain logic — jobs call the API over HTTP. A Python FastAPI + Microsoft MarkItDown sidecar converts documents to Markdown. Docker Compose runs web, api, worker, postgres, redis, and converter; host ./data keeps Postgres, Redis AOF, the vault, and uploads local.
The isometric office
The office view is a live Canvas 2D pixel floorplan: department rooms, desks, walking hand-offs, approval queues, and activity chips (thinking, waiting for approval, idle). Full chat sits under the canvas — Live, History, Timeline — so a cascade is visible in the room and in the thread at the same time. The bilingual (hu/en) command center spans 30+ governance screens: dashboard, org chart, workflow canvas, approvals, audit, project workspaces, document library, memory, skills, MCP connectors, Telegram bridge, and cloned public repositories.
Diamond Memory
Knowledge is stored as typed atoms — one decision, rejected idea, lesson, preference, or fact in one or two sentences, scored for salience and linked to topics. Recall runs before CsabaOfficer answers or delegates, via Postgres full-text and trigram search — not vector RAG. Old decisions are superseded, never deleted. Manual and pinned atoms outrank automation. The Obsidian vault mirrors PostgreSQL for human editing; the database remains authoritative.
Rules the runtime actually enforces
Untrusted text — persona, recalled memory, prior agent output, extracted files, repo summaries — is defanged and wrapped in an HMAC-based, unguessable per-call fence before it enters a prompt. Otherwise an uploaded file or memory atom would behave like an instruction. Audit events are append-only, enforced by a database trigger. Provider keys and OAuth tokens never appear in prompts, logs, or the vault. Production is fail-closed: without CORS_ORIGIN, operator/internal tokens, and SECRET_ENCRYPTION_KEY the API will not start; without the encryption key stored credentials are unreadable. Git clone/pull is SSRF-guarded.
Workspaces, workflows, and long AI runs
A project is a versioned file workspace with a team of agents. Runs execute auto, plan, or step; output is written back as an immutable file version. Workflows are drag-and-drop agent chains (including cron) that stream into the same cascade. Uploaded documents and bound public Git repositories are extracted and offered as fenced context, not as instructions. Long AI work is fire-and-forget with a durable pending marker and boot recovery — the UI polls; the HTTP request does not stay open.
Engineering discipline
Migrations are additive and numbered SQL only; status CHECK constraints widen carefully because TypeScript will not catch them. The shared contract flows shared-types → Zod → API → client. Vitest covers API and pure web modules; pnpm check runs typecheck, tests, and a production build together.