Getting started
This page walks you from "I have an LLM-producing app" to "feedback events are flowing through the framework" in five steps. Allow ~30 minutes the first time.
1. Decide what you want to capture
The framework records events shaped like (actor, action, artifact, payload, time). You will be capturing things like:
- A human approves a draft email the assistant produced.
- A human edits a draft and sends the edited version.
- The system silently sends a draft after no edit for N hours.
- A human regenerates an answer (negative implicit signal).
Before installing anything, write down two lists on paper:
- Actions you want to record. The framework ships with
approve,edit,reject,regenerate,expired,silent_accept, anddisuse. You can add more later viaActionRegistry. - Artifact types you want to record. Examples:
draft,summary,email,brief,decision,recommendation. Each artifact type gets its own retention policy.
If your two lists fit on a sticky note, you are ready.
2. Install
pnpm add @ai-feedback-middleware/core @ai-feedback-middleware/in-memoryAdapter packages are independent, so install only what you need. For a real deployment you will likely also want:
pnpm add @ai-feedback-middleware/postgres @ai-feedback-middleware/redis-pubsub pg ioredis3. Compose the framework
The framework is built around createFeedback(options): FeedbackPort. Wire in an event store, a projection store, and your registries:
import { createFeedback, DEFAULT_ACTIONS } from "@ai-feedback-middleware/core";
import {
createInMemoryEventStore,
createInMemoryProjectionStore,
} from "@ai-feedback-middleware/in-memory";
const feedback = createFeedback({
eventStore: createInMemoryEventStore(),
projectionStore: createInMemoryProjectionStore(),
actions: DEFAULT_ACTIONS,
artifactTypes: [{ name: "draft" }],
});That is enough to capture and read events. Add a bus and outbox when you need projections or async subscribers (next page).
4. Capture an event
await feedback.capture({
action: "approve",
artifact_type: "draft",
artifact_id: "draft-123",
artifact_version: 1,
producer: "secretary-agent",
task_type: "email_draft:warm",
payload: { artifact_hash: "sha256:..." },
});The framework:
- Validates the input via the registered action's payload schema.
- Classifies the event (deterministically) into source / polarity / inference.
- Appends the event to the event store.
- Updates registered sync projections.
- Optionally enqueues for async dispatch via the bus + outbox.
5. Read it back
for await (const event of feedback.readStream("draft-123")) {
console.log(event.event_id, event.action, event.inference);
}That is the round trip. Everything else in the docs is about scaling this to real production: storage adapters, transactional outbox patterns, inference rules, projections, middleware, and stream operators.
Where to go next
- Concepts: the 2x2 framework - the classification model that drives everything downstream.
- Concepts: event sourcing basics - why the event log is the source of truth.
- Concepts: ports and adapters - how storage, transport, and side-effects are isolated.
- Adapters: Postgres setup - the most common production storage adapter.
- Cookbook: threshold crystallization - promote an
observepattern toblacklistafter N negative events.