Inspiration

AI assistants are very good at responding to what a user asks right now, but they are less reliable when the user asks them to remember something that should happen later.

For example:

When Legal approves version 7 and Finance approves deal 043, prepare Dana’s redline draft—but do not interrupt me during focus time.

This is more complicated than a normal reminder. It includes two separate future conditions, exact entity and version requirements, an interruption policy, a human-approval requirement, and a rule that the action must happen only once.

I was inspired to build Latch because similarity-based memory is not enough for these situations. A marketing approval, an older contract version, or approval for a different finance deal might look similar while still being incorrect.

I wanted to create a memory system that could explain both sides of agent behavior:

  • Why did the agent act?
  • Why did the agent correctly remain silent?

That idea became Latch: prospective memory that is typed, inspectable, versioned, and controlled by the user.

## What It Does

Latch converts an ordinary natural-language commitment into a structured Intention Program.

Each program contains:

  • The exact future cue or combination of cues.
  • The action that should be prepared.
  • Entity, document, deal, and version constraints.
  • Conditions that can block the action.
  • Focus-time and interruption preferences.
  • Human-approval requirements.
  • Absence rules for events that fail to happen.
  • Provenance connecting compiled fields to the user’s original words.
  • Version history, replay evidence, and a forgetting rule.

The included ten-step contract scenario demonstrates:

  1. Rejecting a related marketing approval.
  2. Rejecting a stale legal document version.
  3. Accepting the correct Legal approval.
  4. Rejecting approval for the wrong Finance deal.
  5. Starting a focus block.
  6. Accepting the correct Finance approval.
  7. Waiting until the focus block ends.
  8. Requesting human approval before creating a draft.
  9. Rejecting a duplicated webhook so the action happens only once.
  10. Detecting a 48-hour absence condition.

Latch also includes screens for creating commitments, inspecting active memory, reviewing the event timeline, running the simulator, evaluating reliability, and inspecting the deployed system architecture.

## How I Built It

I built Latch as a Next.js and React application deployed on Cloudflare Pages. A Cloudflare Worker provides the backend API and coordinates the system’s state, retrieval, quotas, telemetry, and replay evidence.

The OpenAI pipeline assigns a separate responsibility to each GPT-5.6 model role:

  1. GPT-5.6 Luna quickly routes the user’s request as a new commitment, update, cancellation, or explanation.
  2. GPT-5.6 Sol converts the natural-language commitment into strict structured output.
  3. A deterministic validator verifies triggers, tools, risk levels, limits, and mandatory approval.
  4. GPT-5.6 Terra performs semantic review and creates a concise explanation.
  5. OpenAI text-embedding-3-small generates cue embeddings for selective retrieval.

The models never directly authorize or execute an external action. They produce structured proposals, while deterministic code controls lifecycle transitions, permissions, approval, idempotency, and execution.

Cloudflare services have specific responsibilities:

  • Pages hosts the frontend.
  • Workers provides the API and orchestration layer.
  • D1 stores intentions, versions, events, and traces.
  • KV stores lightweight operational evidence.
  • Durable Objects atomically enforce global and per-visitor quotas.
  • Vectorize stores and retrieves cue embeddings.
  • Queues processes telemetry events.
  • R2 stores sanitized replay artifacts.
  • Workflows coordinates replay generation.
  • AI Gateway routes and observes OpenAI requests.
  • Cron Triggers perform scheduled runtime checks.

The interface was designed with black typography, white backgrounds, electric-lime state accents, responsive navigation, and a story-first Overview that lets judges understand the product quickly.

## How I Used Codex

Codex helped me move from an earlier provider-specific prototype to a complete OpenAI and Cloudflare implementation.

I used Codex to:

  • Inspect the existing frontend and backend contracts.
  • Design the GPT-5.6 model-role architecture.
  • Replace the previous inference integration with the OpenAI Responses API.
  • Add strict structured-output schemas.
  • Separate model judgment from deterministic authorization.
  • Implement Cloudflare AI Gateway routing.
  • Add quota enforcement and a safe deterministic fallback.
  • Preserve the original simulator’s safety invariants.
  • Redesign the user interface.
  • Write unit, integration, and Playwright browser tests.
  • Diagnose Cloudflare Pages routing and cross-platform build problems.
  • Deploy and verify the production application.
  • Prepare the README, project story, and demonstration script.

The most important product decision was keeping GPT models outside the authorization boundary. Models can understand and propose, but deterministic code and human approval control what is allowed to happen.

## Challenges I Faced

### Turning Natural Language Into Safe Memory

Natural language is flexible and ambiguous, but future actions require exact conditions. A loosely interpreted commitment could cause an action to happen for the wrong contract, version, person, or deal.

I addressed this with strict structured outputs followed by deterministic validation. Invalid tools, unsupported predicates, unsafe risk levels, and missing approval requirements are rejected before the program enters active memory.

### Proving Correct Silence

Most AI demonstrations focus on a successful response. Latch also needed to demonstrate why the system did nothing.

I created an event timeline that records failed constraints such as:

  • Wrong communication channel.
  • Wrong entity.
  • Incorrect deal ID.
  • Stale document version.
  • Rejected status.
  • Active focus-time policy.
  • Duplicate event ID.

This makes correct silence as visible as successful action.

### Preventing Duplicate Actions

Real systems frequently receive duplicated webhooks or retry the same work. Without idempotency, an agent might prepare or send the same action multiple times.

Latch uses deterministic event deduplication and an atomic Durable Object claim so an approved action can be claimed only once.

### Protecting a Public Demo From Unexpected Cost

A public hackathon demo can be called repeatedly by anonymous visitors. I added per-visitor and global daily quotas, small input and output limits, disabled payload logging, and an explicitly labeled deterministic fallback.

If OpenAI credits or quotas are unavailable, the application continues demonstrating the complete product without pretending the fallback was a live GPT response.

### Deploying Across Different Environments

Next.js static exports produced different route-payload layouts on Windows and Linux. This caused Cloudflare route- prefetch errors and initially caused GitHub Actions to fail.

I added a cross-platform post-build normalization step, verified it locally and in GitHub Actions, and used Playwright to confirm that production had no console or network errors.

## Accomplishments I Am Proud Of

  • Built a complete ten-step, reproducible prospective-memory demonstration.
  • Created an inspectable program rather than another opaque chat response.
  • Reliably rejected tempting but incorrect cue events.
  • Implemented compound Legal-and-Finance conditions.
  • Respected focus time before requesting approval.
  • Kept every external effect as an approval-bound draft.
  • Prevented duplicate actions using exactly-once claims.
  • Created visible evidence for both action and silence.
  • Deployed a responsive seven-screen application on Cloudflare.
  • Preserved functionality when promotional model credit is unavailable.
  • Achieved passing unit tests, production builds, GitHub CI, and Playwright browser verification.

## What I Learned

I learned that reliable agent memory is less about storing more conversation history and more about representing future conditions precisely.

Embeddings are useful for retrieving possible candidates, but similarity should not decide whether a future condition is true. Typed predicates and deterministic constraints must make that decision.

I also learned that a multi-model architecture becomes easier to understand when every model has one narrow responsibility. Routing, structured compilation, semantic review, and embedding retrieval can be observed and evaluated separately.

Another major lesson was that observability is part of the product experience. Showing versions, provenance, constraint failures, approval gates, lifecycle transitions, model traces, and replay evidence makes an AI system significantly easier to trust.

Finally, I learned that fallbacks should be honest. When live inference is unavailable, the product should remain demonstrable while clearly explaining which mode produced the result.

## What’s Next

The next version of Latch would add:

  • Authenticated private workspaces.
  • Real connector permissions for email, calendars, CRM, and document systems.
  • User-defined evaluation datasets.
  • Richer time, recurrence, and absence operators.
  • Private tenant-specific memory.
  • Configurable approval workflows.
  • Portable Intention Programs that can run across different agent frameworks.
  • Production monitoring and administrator controls.

The long-term goal is to make prospective memory a reusable safety layer for any long-running AI agent.

Built With

  • cloudflare-ai-gateway
  • cloudflare-cron-triggers
  • cloudflare-d1
  • cloudflare-durable-objects
  • cloudflare-kv
  • cloudflare-pages
  • cloudflare-queues
  • cloudflare-r2
  • cloudflare-vectorize
  • cloudflare-workers
  • cloudflare-workflows
  • github-actions
  • gpt-5.6
  • lucide-react
  • next.js-16
  • openai-codex
  • openai-responses-api
  • openai-sdk
  • playwright
  • react-19
  • text-embedding-3-small
  • typescript
  • vitest
Share this project:

Updates