Make Your Own Event-Sourced Agent Harness — Everything in the Agent as Events (Jonas Templestein / Iterate)

AI Engineer Europe 2026 (London) Workshop — May 14, 2026

Jonas Templestein · 03:00 "Every agent should have a URL from the moment it's born. Otherwise you end up inventing 'Slack integration' as a connector concept, in reverse, after the fact."

From the Day 1 workshop track at AI Engineer Europe 2026 (Queen Elizabeth II Centre, London, April 8 to 10, 2026; published May 14, 2026). A joint session by Jonas Templestein (co-founder and CEO of Iterate, formerly CTO of Monzo) and Misha (Iterate), about 64 minutes. Demo repo: iterate/ai-engineer-workshop. Live service: events.iterate.com.

Jonas Templestein co-founded Monzo Bank as CTO (2015 to 2023, about nine years) and in 2024 co-founded Iterate A UK / Switzerland software startup co-founded in 2024 by Jonas Templestein and Oliver Beattie (formerly Nustom). Seed investors include OpenAI, Index Ventures, Accel, General Catalyst, and Naval Ravikant. No public product yet, but exploring the direction of redesigning the underlying foundation for agent harnesses. with Oliver Beattie. Seed investors include OpenAI, Index Ventures, Accel, General Catalyst, and Naval Ravikant. This workshop, given while Iterate has yet to ship a public product, takes the form of an open live exercise — "if we were designing an agent harness, this is how we'd build it."

As Templestein himself declared a minute in, the session ran on "pure chaos" — invited to speak a week before, prep done in a hurry, the SDK pushed one minute before stage, Cursor freezing during the live demo, OpenAI quota errors, a laptop acting up that required a restart and swap. As a demo it was half-broken, but the central claim — "if every failure can be recorded as an event, you can debug from that moment on" — came through with unusual clarity, precisely because of the collapse of the live run.

1. Event-sourced = debuggable + extensible. The design rewrites the entire agent harness in terms of an append-only event stream, reducers, and after-append hooks. LLM streaming chunks, tool calls, errors, UI feedback — all saved as events. Debuggability goes up by orders of magnitude, at the cost of a fairly radical developer experience.

2. Distributed by design. Plug-ins can run on different machines and in different languages. A worldview where a Rust safety checker communicates with a TypeScript coding agent: "I'm giving you 200ms before your next LLM call — if you have something to say, append an event." Avoiding before-hooks sidesteps the context-cache breakage problem.

3. Deploy as event. Append an event carrying source code to a Cloudflare dynamic worker, and processing logic is attached to the stream. There's no "set up a server" concept; the agent itself can rewrite its own logic as events. Within reach: have the LLM generate source code for a new processor and let the agent extend itself.

Key Observations

"Every agent should have a URL from the moment it's born" (03:00)

Templestein's starting point. Existing agent SDKs (Pi, Claude Code, OpenCode, and others) hold an event log internally but expose function calls or MCP as their outward interface. As a result, Slack integration or webhooks end up implemented as a separate "connector concept" added later.

Iterate's claim runs the other way: design the agent from the start as "an entity that speaks to the world over HTTP," and Slack integration and webhooks unify as special cases of "appending events to the stream." The same instinct underlies Viktor (Fryderyk Wiatrowski, AI Engineer Code Summit) and the company-AI-that-lives-in-Slack — positioning the agent not as "a function called from other systems" but as "an independent entity that converses with the world over HTTP."

"The reducer is state + event → new_state, side effects go in after_append" (33:00)

The heart of processor signature design. Cleanly separate "the pure function that updates state" from "the function that produces side effects." It's a functional programming staple, but it matters especially in an agent harness — pause, resume, and replay all become easier.

The example Templestein gave: a circuit-breaker processor. The reducer accumulates timestamps for the most recent 100 events; the after_append checks "have the last 100 happened within one second?" — and on detection appends a pause event. Even the logic that controls the stream itself is expressed as events.

"Before-hooks are the worst — they destroy the context cache. Better to wait 200ms in after-append" (47:30)

A claim Templestein leaned into during Q&A. He cited cases where pre-prompt hooks in tools like OpenCode invalidate the context cache and inference costs jump as a result.

The alternative design: the agent loop waits up to 200ms before its next LLM call. During that window, other processors can append events of the form "I have context I want to add." Past the deadline, the agent goes ahead and calls the LLM. The philosophy is the same as the agent observability discussion and as RAG pipelines that inject context from "an indexed version of the Notion knowledge base, if it makes the deadline." The core is "design the whole system as eventually consistent."

"The workshop falling apart is itself the proof that event-sourcing is needed" (the arc around 38:00)

Mid-demo, Cursor froze, OpenAI returned a quota error, the laptop had to be restarted, and Templestein eventually swapped laptops with Misha to keep going. Even so, the message — "as long as you have a stream that records every failure as an event, you can debug after the fact" — came through more clearly, by way of the live demo's collapse, not in spite of it.

A rare case in which "polish as a demo product" and "persuasiveness of the idea" are orthogonal. Audience Q&A had Templestein himself admit "we don't yet know if this is dumb or cool," leaving the session as a proposal of an idea.

Video outline (main sections)

  • (00:00) Jonas and Misha self-introductions, "pure chaos" declared, SDK pushed one minute before stage
  • (02:15) Four design principles — event-sourced (= debuggable) / extensible / edge-rootable / distributed
  • (05:00) events.iterate.com basics — agent path = filesystem hierarchy, append via curl, subscribe via SSE with live=true
  • (11:00) Mechanics of idempotency keys, pause/resume, and the circuit breaker (fires on 100 events in 1 second)
  • (15:00) Scheduled events, 5-second heartbeat, plug-ins like a JSONata transformer
  • (18:00) Entering the demo-collapse phase — Cursor freezes, laptop swap, computer restart
  • (28:00) Plan B — verbal walkthrough of the agent-input-added event bridging to the OpenAI responses API
  • (33:00) Reducer signature explained — state + event → new_state, side effects in after_append
  • (40:00) Dynamic-worker-configured event — a script string carried in an event, deployed as a Cloudflare worker
  • (47:30) Q&A — why no before-hooks (context cache breakage, the 200ms-timeout approach)
  • (58:00) Standardization discussion around durable streams (relation to Electric SQL / Jetstream NATS)

Sources

Glossary

Event-sourced agent harness
A design pattern that expresses the agent's state and behavior entirely as an append-only event stream. LLM calls, tool calls, errors, UI feedback — everything is stored as events. Pause, resume, and replay become easy, and debuggability goes up by orders of magnitude. Proposed by Templestein at Iterate.
Reducer + after_append hook
The two functions of a processor. The reducer is a pure function (state + event → new_state) with no side effects, returning the same result no matter how many times it's called. The after_append hook then produces side effects (appending new events, calling the LLM, hitting an external API, etc.). The functional separation of pure and effectful code, brought into the agent harness.
Durable Stream
A proposed web standard for append-only event logs with offset tracking. Kafka, Jetstream NATS, and Electric SQL are similar implementations. Iterate's events.iterate.com is close to this spec but uniquely also supports push subscriptions (server-to-client notifications).
Dynamic-worker-configured event
A special event type on events.iterate.com. The payload carries JavaScript processing logic as a string; once appended to the stream, it runs on Cloudflare Workers. A "deploy without provisioning a server" model for changing stream processing. Within reach: have the LLM itself generate source code for a new processor and self-extend.
Circuit breaker (Iterate's implementation)
A reducer accumulates timestamps for the last N events; when high-frequency bursts are detected, the stream is paused automatically. An example of implementing "stream-level safety to prevent infinite loops" in terms of events themselves.
Before-hooks and the context cache breakage problem
The phenomenon where implementing a pre-prompt hook subtly changes the context on each call, defeating the provider's context cache and pushing inference costs up. Templestein avoids this by "not having before-hooks, and waiting 200ms in after-append" instead.