Skip to content
Technical command center showing distributed system topology, force-directed knowledge graph, and Dash0 OpenTelemetry trace spans in warm charcoal and bronze editorial styling.

agent first development systemObe: How We Developed an Agent-First Development System with Dash0

How Obe built an agent-first engineering system combining OpenWiki progressive zoom, AST constraint ratchets, Dash0 OpenTelemetry observability, and hermetic offline guarantees.

Most engineering teams trying to build high-volume legal software with autonomous AI coding agents hit an invisible wall after the initial prototype: the agents break the system after ten minutes of real-world work.

Drop an autonomous agent like Claude Code, Codex, or Factory Droid into a 100,000-line legal intake monorepo, and standard failure modes immediately cascade:

  • Context Saturation: The model receives conversational instructions, hallucinates private module boundaries, confuses frontend shims with Convex database logic, and writes code that compiles locally but violates critical state-bar ethics invariants.
  • The Ephemeral Daemon Trap: An agent spins up a background dev server or visualizer daemon on an ephemeral port. Ten minutes later, the process idle-times, dies, or gets reaped by task managers, leaving the user with broken links and offline dashboards.
  • Untracked File Churn: In multi-agent environments, agents commit half of their generated artifacts and leave the rest untracked. A subsequent rebase or hard reset cleanly deletes the missing files, leaving downstream developers wondering why yesterday's working deliverable disappeared from disk.
  • Silent Multi-Agent Regressions: Parallel agents working on intake pipelines, vector sidecars, and state jurisdiction rules silently revert each other's changes because there is no mathematical ground truth governing commits.

At Obe, we build programmatic legal intake software for consumer mass arbitration. Our platform processes thousands of retainers, truth-in-lending disclosure statements, and dispute records. We cannot afford silent regressions or hallucinated business logic.

To solve this, we engineered an agent-first development system from first principles. By pairing a strict Progressive Zoom Architecture, an Active Hook-Driven Context Injection layer, Hermetic Offline Artifact Guarantees, and enterprise OpenTelemetry observability through Dash0, we gave autonomous agents the guardrails needed to build and maintain production legal software at full speed.

Here is the exact architecture we built and how it operates in production.


1. The Progressive Zoom Architecture: $L_0 \rightarrow L_1 \rightarrow L_2$

The single biggest mistake in AI-assisted development is treating the codebase as flat text. When an LLM has to search across dozens of packages to understand how a document extraction pipeline works, it fills its context window with noise and hallucinates outdated implementations.

In our repository (github.com/timottowitz/obe), we enforce a unidirectional, three-tier zoom hierarchy:

┌─────────────────────────────────────────────────────────────┐
│             L0: Bird's-Eye System Topology                  │
│       Macro navigation, package boundaries, visual graph    │
└──────────────────────────────┬──────────────────────────────┘
                               ▼
┌─────────────────────────────────────────────────────────────┐
│             L1: Canonical Subsystem Authorities             │
│      OpenWiki domain specs (backend, catalog, latency)      │
└──────────────────────────────┬──────────────────────────────┘
                               ▼
┌─────────────────────────────────────────────────────────────┐
│          L2: Deterministic Parity Fixtures & AST            │
│       Golden JSON fixtures, holdout corpora, AST ratchets   │
└─────────────────────────────────────────────────────────────┘

Level 0: Bird's-Eye System Topology

Every agent session begins at $L_0$. The agent is oriented via openwiki/quickstart.md, openwiki/architecture/monorepo-map.md, and an interactive force-directed graph. This topology provides the macro coordinates: where the Convex core begins, where the LanceDB vector retriever sits, and how worker nodes communicate without burdening the model with implementation trivia.

Level 1: Subsystem Deep-Dive (OpenWiki Canonical Truth)

Before modifying or debugging any subsystem, the agent is strictly prohibited from guessing. It must consult the designated canonical document under openwiki/:

  • Convex Core & Persistence: openwiki/architecture/backend-convex.md and openwiki/architecture/data-truth-hierarchy.md
  • Document Extraction & Citation Engine: openwiki/domain/legal-document-intelligence.md
  • Retrieval & Vector Sidecars: openwiki/integrations/agents-storage-and-services.md
  • Living Legal Knowledge Graph: openwiki/domain/catalog-architecture.md
  • Queue Latency Budgets: openwiki/operations/intake-queue-latency.md
  • Secrets Management & RBAC: openwiki/operations/secrets-management-infisical.md

Level 2: Deterministic Parity Fixtures & Typed Contracts

Prose alone is insufficient because LLMs still misinterpret words. At $L_2$, truth is mathematical.

Our legal issue engine is pinned by immutable parity fixtures (__fixtures__/parity/{federal,tx,ca,az,ky,ok}.json). If an agent refactors an extraction pipeline or alters fact-frame resolution, Vitest asserts the snapshot hash down to the byte. If the fixture goes red, the agent cannot push.


Legal SaaS platforms trap firm workflows inside closed proprietary databases. OBE gives law firms permanent source code ownership with complete customization freedom.

Tim OttowitzSchedule a Software Architecture Consultation →


2. Active Hook Injection: Pushing Knowledge at the Point of Contact

Telling an agent in a markdown instruction file to "remember to read the docs" fails 20% of the time under high cognitive load. Agents get tunnel vision on the specific file they were instructed to edit.

To eliminate this friction, we implemented an active context injection hook (tooling/skill-router/route.mjs) governed by a machine-readable routing manifest (skills/routing.json).

The moment an agent edits a file, the PostToolUse hook intercepts the operation, matches the file path against repository routing regexes, and actively injects the canonical OpenWiki authority and stack constraints directly into the prompt context:

{
  "skill": "convex-obelisk",
  "match": ["packages/backend/convex/"],
  "hint": "Convex backend: schema-first codegen, .withIndex only, typed internal.* refs, parity-locked legal engine, advisory altitude. Canonical authority: openwiki/architecture/backend-convex.md and openwiki/domain/legal-document-intelligence.md. Read skills/convex-obelisk/SKILL.md before editing."
}

The agent does not need to search for documentation. The documentation meets the agent the microsecond its virtual fingers touch the code.


3. The Hermetic Artifact Guarantee

One of the most frustrating experiences in autonomous development is opening a deliverable created by an agent only to find it broken because the agent relied on an ephemeral local server or unbundled module imports.

In standard environments, when an agent creates an interactive visualizer or topology diagram, it typically runs an ad-hoc local server on port 4321 or generates an index.html referencing <script type="module" src="./client.js"> and fetch("./graph.json").

When a human user opens that file via file:/// in Google Chrome or Safari:

  1. CORS Protocol Failure: Modern browsers assign an opaque origin: null to local files, immediately blocking ES module imports and fetch() requests.
  2. Process Death: If the file relied on a background daemon, that daemon was terminated when the agent's task completed.

We solved this by establishing The Hermetic Artifact Guarantee:

The Rule: Any architectural deliverable or visual report emitted by agents must be hermetic, single-file, and completely offline-ready.

For our interactive topology explorer (docs/diagrams/openwiki-graph/index.html), our custom exporter (scripts/export-openwiki-graph.mjs) compiles the entire knowledge graph into a standalone deliverable:

  • Inlined visualizer stylesheet rules.
  • Inlined JSON topology (<script id="openwiki-graph-data" type="application/json">).
  • Bundled classic script controllers that bypass ES module cross-origin limitations.

To ensure this invariant never regresses, we added an automated security check (tooling/workflow-security/hermetic-diagrams.test.mjs) to our pre-push gate:

test('docs/diagrams/openwiki-graph is hermetic, tracked, and offline-ready', () => {
  const content = readFileSync(indexPath, 'utf8')
  assert.ok(content.includes('id="openwiki-graph-data"'), 'Must embed inline graph data')
  assert.ok(!content.includes('<script type="module" src="./client.js"></script>'), 'Must avoid CORS blocks on file://')
})

A developer can double-click openwiki-graph/index.html on an airplane with no internet connection and no background processes running, and the entire interactive force-directed graph renders at 60 frames per second.


Inspect Our Event-Driven Telemetry and Intake Harness

Our modern stack processes high-volume intake events with full distributed tracing, OpenTelemetry standards, and reactive Convex state updates.

Tim OttowitzBook a System Architecture Call with Tim Ottowitz →


4. End-to-End Observability with Dash0 and Agent0

Writing code with agents is only half the battle, and maintaining distributed systems touched by AI requires deep, real-time observability.

Historically, AI pipelines relied on disconnected MLflow trackers or bespoke logging scripts that sat in silos away from application performance metrics (APM). If an agent introduced a subtle database query regression in document parsing, nobody noticed until client queries timed out.

We eliminated MLflow and retired legacy tracing entirely, migrating our production APM end-to-end to Dash0 utilizing native OpenTelemetry specifications.

Layer Implementation Observability Mechanism
Frontend Web Vitals (RUM) @dash0/sdk-web Tracks Core Web Vitals, page transitions, and injects W3C traceparent headers into all API requests
Ingress Ingestion AWS us-west-2 OTLP Ingress Standardized OTLP HTTP/protobuf payload ingestion directly to Dash0 Cloud
Backend Tracing @obelisk/telemetry + OpenTelemetry SDK Traces document extraction spans (Reducto), SOC claim resolution, and LanceDB vector searches
Autonomous AI SRE Dash0 Agent0 Real-time AI anomaly detection diagnosing latency spikes and failure bursts down to the exact commit SHA
[Browser Client] 
   │  (W3C traceparent injected via @dash0/sdk-web)
   ▼
[Convex HTTP Router / API]
   │  (OTLP Spans: Reducto Extraction, Prompt Geometry)
   ▼
[LanceDB Vector Sidecars]
   │  (OTLP Spans: Dense Search, RRF Fusion, Zerank Reranking)
   ▼
[Dash0 Ingress] ───► [Agent0 AI SRE Engine] ───► Commit-Level Anomaly Alerts

Trace Context Propagation from Client to Vector Engine

When an intake specialist reviews a 50-page dispute packet in our web application, @dash0/sdk-web initializes the trace context. When the user clicks to re-extract an arbitration clause, the frontend automatically propagates the W3C traceparent header to our Convex backend.

The backend tracing provider (tracingOtel.ts) attaches spans across:

  1. Document OCR geometry and bounding-box validation.
  2. Multi-provider extraction fallback routing.
  3. LanceDB hybrid dense and full-text index retrieval.
  4. Deterministic legal claim mapping.

If an autonomous coding agent optimizes a query but accidentally introduces an unindexed .filter() scan that adds 800ms of latency, Dash0's Agent0 AI SRE flags the anomaly immediately, correlating the exact trace with the offending deployment.

Per the official Dash0 Documentation, having native OpenTelemetry across the entire stack means zero vendor lock-in and instant root-cause analysis across distributed boundaries.


5. Machine-Verifiable Invariants over Polite Prose

Human engineers often rely on code review checklists: "Remember not to do unindexed database scans" or "Remember that external buyers cannot see draft documents."

For LLMs, checklists are suggestions that degrade with context length. In our system, every single architectural constraint is enforced by an Abstract Syntax Tree (AST) ratchet (tooling/constraint-checks/run.ts):

[convex-unindexed-filter]        blocking: 0 new (enforces .withIndex only)
[convex-unbounded-collect]       blocking: 0 new (blocks memory bloat)
[buyer-allowlist]                blocking: 0 new (enforces advisory altitude)
[doc-drift]                      blocking: 0 new (ensures AGENTS.md matches reality)
[hermetic-diagrams]              blocking: 0 new (ensures offline visualizers)

If an agent attempts to commit an unindexed .filter() over a table with 500,000 document records, the local push gate (scripts/prod/gate.sh) halts the push before the code ever touches origin/main.

The agent does not need to guess if its code follows our engineering principles. The machine tells it with an exit code.


Why go to these lengths? Because high-volume consumer arbitration is not a sandbox for sloppy AI experiments.

When a law firm handles 10,000 claimants in a mass arbitration against a tech monopoly or predatory lender, the stakes are immense:

  • Deadlines with arbitration providers (AAA, JAMS) are rigid.
  • Missing a statute-of-limitations window or failing to extract an opt-out clause can compromise an entire portfolio.
  • State-bar ethics rules strictly forbid automated systems from generating unauthorized legal conclusions or practicing law without attorney review.

By building an agent-first development system governed by Progressive Zoom, Hermetic Artifacts, AST Invariants, and Dash0 Observability, Obe can ship features, optimize document extraction benchmarks, and refine intake pipelines with unprecedented speed without sacrificing compliance, accuracy, or uptime.

We don't hope our AI agents build reliable software. We designed an environment where they have no other choice.

Tim OttowitzBook a demo →

Find the Right Intake Software and Developers for Your Firm

Ready to own your intake technology instead of renting SaaS seats?

👉 Tim OttowitzSchedule a Consultation with Tim Ottowitz to Review Your Case Type
We will inspect your current software architecture, review your customization requirements, and show you how permanent codebase ownership eliminates vendor lock-in.

Tim OttowitzBook a demo →

Sources

Agent ArchitectureObservabilityDash0OpenTelemetryLegal Intake

Let us build your intake

Want us to build this exact intake pipeline for your firm?

Send us your intake questionnaire, retainer agreement, and document checklist. We will build, test, and deploy a custom, review-ready intake flow for your practice area.

Tim OttowitzBuild My Intake Pipeline