Event-Driven AI

The Universal Event Model: Making AI-Generated Code Observable

domain.entity.action:version

The universal syntax for observable AI systems

Here's a question that should terrify you: When AI generates code, how do you know what it actually did?

You don't. Not really. You read the code (maybe), run it (probably), and hope nothing breaks (definitely). AI coding assistants have become remarkably good at generating plausible-looking code. They've also become remarkably good at generating plausible-looking bugs, security vulnerabilities, and architectural disasters that won't surface until 3 AM on a Sunday.

The problem isn't the AI. The problem is that AI-generated code is fundamentally unobservable. It exists. It runs. But you can't systematically verify what it's doing, track how it behaves over time, or build feedback loops that make the AI better.

We built something to fix this. And it starts with a deceptively simple idea.

The Core Insight

Every meaningful state change in any system can be expressed as:

domain.entity.action:version

Plus typed fields for context.

That's it. Four semantic components. One format. Universal applicability.

1
Event per state change
4
Semantic components
Systems it can model
0
Magic numbers needed

Look at a real example:

auth.user.login:1 payments.order.charged:2 ai.generation.completed:1

auth.user.login:1 is instantly understandable. No lookup table needed. No magic numbers. No "what does event type 47 mean again?" moments at 3 AM.

Why This Structure?

We didn't invent this pattern out of thin air. It emerged from studying how engineers actually think about systems. And it turns out there are exactly four questions that matter:

1. What domain are we in?

The top-level grouping. auth, payments, shipping, ai. This lets you slice your entire system by business function with a single query.

2. What thing is involved?

The entity. user, order, package, model. The noun that something happened to.

3. What happened?

The action. login, charged, delivered, trained. The verb that describes the state change.

4. Which schema version?

The version. :1, :2, :3. Because schemas evolve, and old events need to remain parseable.

The AI Readability Factor

This structure isn't just for humans. It teaches AI models your domain. They learn that auth contains user and session, that things can be created, failed, completed. The format itself becomes training signal.

Hierarchical Queries: The Superpower You Didn't Know You Needed

The dot notation isn't cosmetic. It's functional. Watch this:

-- All auth events WHERE event_id LIKE 'auth.%' -- Everything about orders, across all domains WHERE event_id LIKE '%.order.%' -- All failures across the entire system WHERE event_id LIKE '%.failed:%'

Three queries. Three different cross-sections of your entire system. No joins. No complex lookups. Just pattern matching on strings.

This matters because AI-generated systems are complicated. They have dozens of components, hundreds of state transitions, thousands of potential failure modes. You need to be able to slice and dice all of that with simple, predictable queries.

The Hard Questions

Here's where things get interesting. We spent months asking: Can this model everything? Not just the easy stuff—the weird edge cases from complex event processing, quantum physics, and consciousness research.

We investigated seven categories of potentially unmodelable phenomena. Here's what we found:

Challenge Modelable? Approach
Composite/Complex Events Yes Causality chains in fields
Non-Events (Absence) Yes Generated threshold events
Continuous Streams Yes Emit at semantic boundaries
Spatiotemporal Events Yes Spatial relations as fields
Quantum Observer Effect Yes Measurement IS the action
Recursive/Meta Events Yes Events about events
Subjective Experience No* Outside all observability

*The asterisk matters. Qualia—what it's like to experience something—can't be modeled by any telemetry system. Not ours. Not anyone's. This isn't a limitation of EventIDs. It's a limitation of third-person description itself.

Example: The Car Crash Problem

Consider a complex composite event: A car tire blows out. The car leaves the road. It hits a tree. The driver is thrown from the vehicle. No single sensor detected "occupant thrown in accident"—it's inferred from multiple events combined.

How do you model this?

vehicle.occupant.thrown-in-accident:1 caused_by: [vehicle.tire.blowout, vehicle.motion.stopped, vehicle.driver.left-seat] inference: composite

The EventID names the pattern. The fields capture causality. The system can now query for all composite events, all events caused by tire failures, all events involving driver displacement.

Example: The Non-Event

"User did NOT log in for 30 days" is meaningful. But nothing happened. How do you emit an event for something that didn't occur?

auth.user.inactive:1 last_seen: timestamp threshold_days: 30

Absence becomes a generated event when a threshold is crossed. The system doesn't wait for something to happen—it actively monitors for meaningful non-occurrences.

Why This Changes Everything for AI

"AI generates code. The code runs. Did it work? You have to read logs, parse text, hope the format didn't change."

That's the problem today. And here's the solution:

The AI Feedback Loop

Here's what this enables:

  1. AI generates code that emits well-defined events. Not logs. Not printf debugging. Structured, typed, versioned events that match a catalog.
  2. Events are queryable and verifiable. "Show me all auth failures in the last hour" is a SQL query, not a grep through gigabytes of logs.
  3. Feedback loops become possible. "Event auth.user.login:1 fired 10x more than expected" is actionable intelligence for both humans and AI.
  4. AI can reason about its own output in structured terms. This is the crucial part. When the AI's output is observable, it can learn from its mistakes.

The event catalog becomes:

The Catalog DSL

You define events in a domain-specific language that compiles to EventIDs:

domain auth { entity user { event login:1 { user_id: uuid ip: ip_addr method: string } event logout:1 { user_id: uuid reason?: string } } entity session { event expired:1 { session_id: uuid user_id: uuid } } }

This compiles to: auth.user.login:1, auth.user.logout:1, auth.session.expired:1

The DSL does three things:

  1. Makes event definitions readable and maintainable
  2. Generates type-safe emitters for your language (Rust, TypeScript, Python, Go)
  3. Creates the schema for your event store (Postgres, ClickHouse, etc.)

The Postgres Schema

Events go into a simple table with computed columns that let you query by any component:

CREATE TABLE event_catalog ( event_id TEXT PRIMARY KEY, domain TEXT GENERATED ALWAYS AS (split_part(event_id, '.', 1)) STORED, entity TEXT GENERATED ALWAYS AS (split_part(event_id, '.', 2)) STORED, action TEXT GENERATED ALWAYS AS (split_part(split_part(event_id, '.', 3), ':', 1)) STORED, version INT GENERATED ALWAYS AS (split_part(event_id, ':', 2)::int) STORED, description TEXT, fields JSONB, created_at TIMESTAMP DEFAULT now() ); CREATE INDEX idx_domain ON event_catalog(domain); CREATE INDEX idx_entity ON event_catalog(entity); CREATE INDEX idx_action ON event_catalog(action);

The computed columns mean you never have to manually extract components. The indexes mean queries are fast even with millions of events. The JSONB fields column means schema evolution is trivial.

The Rust Implementation

Type safety matters. Here's the core type:

#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct EventId { pub domain: String, pub entity: String, pub action: String, pub version: u8, } impl Display for EventId { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "{}.{}.{}:{}", self.domain, self.entity, self.action, self.version) } }

From this, we generate macros that provide compile-time validation:

emit!(auth.user.login:1, { user_id: user.id, ip: request.ip(), method: "oauth" });

If auth.user.login:1 isn't in your catalog, this fails at compile time. If you forget a required field, compile error. If you pass the wrong type, compile error.

The AI can generate code that emits events. The type system ensures those events are valid. The feedback loop closes.

The Claim

The Universal Event Model Claim

Any meaningful, observable state change in any system can be expressed as domain.entity.action:version plus typed fields.

The only exception is first-person subjective experience, which is outside the domain of any observability system.

This is a strong claim. We've tested it against quantum physics, consciousness research, complex event processing systems, and edge cases from every domain we could think of. So far, it holds.

What's Next

We're building this in the open. Here's the roadmap:

  1. Lock down the catalog format — The DSL shown above
  2. Build the Rust macro — Type-safe event emitters
  3. Build the collector — Events → Postgres
  4. Build the query CLIsyntax query --event auth.user.login:1 --last 1h
  5. Demo the AI loop — Prompt → Generate → Run → Query → Improve

The spec is available now at /event-model/specification.html. It's dual-purpose: readable by humans, parseable by AI. The format teaches the AI what we want while documenting it for everyone else.

This Is the New Standard

For decades, we've treated observability as an afterthought. Something you add after the code is written. Something that varies from system to system, team to team, company to company.

AI changes the equation. When code is generated at scale, observability can't be an afterthought. It has to be built in from the start. It has to be standardized. It has to be universal.

domain.entity.action:version is that standard.

A Note on AI and This Article

This article was written with AI assistance. We believe in transparency: AI helped draft, edit, and refine this content. The ideas, research, and technical decisions are human-driven, but the words were shaped collaboratively. That's the future we're building toward—humans and AI working together, with clear observability into what each contributes.

syntax.ai — The universal event model for AI-generated code.

EventIDs are the typed, queryable, verifiable syntax that makes AI-generated systems observable and improvable.

Built with conviction. Ship it.

Stay Updated on the Event Model

Get notified when we release new tools, specs, and tutorials for building observable AI systems.