- fetchEvents no longer reverses results (after= returns ASC) - Watcher removes client-side id filtering (server handles it) - Updated test mock to match ASC order
OGraph
Event Sourcing + Projection + Reaction engine for Agent ecosystems.
Part of the Uncaged ecosystem.
Philosophy
- Event is fact — immutable, append-only, no logic
- Projection is cache — lazy, closed-world, on-demand computation
- Intelligence lives in the Agent, not the Engine — Agent-in-the-Loop
Why not Kafka?
| Kafka | OGraph | |
|---|---|---|
| Metaphor | Ballistic missile (design, fire) | Guided missile (adjust in flight) |
| Pipeline | Pre-defined by humans | Agent defines/adjusts at runtime |
| Computation | Eager (continuous update) | Lazy (on-demand) |
| JOIN | ✅ KTable synchronized | ❌ Projections are independently lazy |
| Aggregation | Pre-set materialized views | Actor (Agent) assembles in real-time |
| Core assumption | Humans design everything upfront | Agent-in-the-Loop: runtime decisions |
Traditional Event Sourcing (Kafka, EventStoreDB) assumes pipelines are designed, deployed, and maintained by human developers. OGraph assumes an Agent with decision-making capability dynamically defines Projections, adjusts Watch lists, and assembles aggregations at runtime.
This is not a feature trade-off. It's a paradigm difference.
Lazy Update — a logical necessity
- Agent can define new Projections at any time → can't assume all Projections are deployed
- → Must be Lazy (compute on demand)
- → No consistent cross-Projection snapshot → abandon JOIN
Each step is logically inevitable. From a single assumption — "Agent defines Projections at runtime" — the entire computation model follows.
Three-Layer Modeling
Layer 1: Event — Facts
Immutable records of what happened. No judgment, no derived logic.
Layer 2: Projection — Cache
Deterministic computation over event streams. Core constraint: computational closure — expression inputs are only $state, $event, $params. Cannot query other Projections or make external calls.
Layer 3: Actor — Behavior
Observes multiple Projections, executes complex logic and side effects. Watch lists are dynamic — derived from data, not hardcoded.
Packages
| Package | Description | npm |
|---|---|---|
@uncaged/ograph |
CF Worker engine — events, projections, reactions | |
@uncaged/ograph-cli |
CLI for managing OGraph instances | |
@uncaged/ograph-dispatcher |
Local daemon — polls projections, notifies Agent when idle |
Quick Start
npm install -g @uncaged/ograph-cli
ograph deploy # Deploy to Cloudflare Workers
ograph event-defs list # List event types
ograph events emit # Emit events
ograph schema # View all definitions
Development
npm install
npm test # Run all tests (163+)
cd packages/engine && npm run dev # Local dev server
Architecture
- D1 for storage (events, projections, reactions)
- Hono for API routing
- Lazy incremental reduce — projections track
last_event_idfor O(delta) updates - Projection health — errored projections stop updating, auto-recover when fixed
- Dynamic handlers —
new Function()sandboxed execution with emit/log/kv API injection - API Key —
ogk_prefix, SHA-256 hash, event type whitelist - Structured errors —
{ error: { code, message } }
License
MIT
Built by 小橘 🍊 & 小墨 🖊️ — NEKO + KUMA Teams