Open Harness
Guides

Persistence Configuration

Configure signal stores for durable workflows

Persistence Configuration

Open Harness can persist signal traces for recording and replay.

In-Memory Store (Development)

Use MemorySignalStore for quick iteration:

import { MemorySignalStore } from "@open-harness/core";

const store = new MemorySignalStore();
  • Fast, no setup
  • Data lost on restart
  • Perfect for tests

Recording a Workflow

Enable recording during execution:

import { createWorkflow, ClaudeHarness, MemorySignalStore } from "@open-harness/core";

const store = new MemorySignalStore();

const result = await runReactive({
  agents: { analyzer },
  state: initialState,
  harness: new ClaudeHarness(),
  recording: {
    mode: "record",
    store,
    name: "my-workflow",
    tags: ["production", "analyzer"],
  },
});

console.log("Recording ID:", result.recordingId);

Replaying a Workflow

Replay without harness calls:

const result = await runReactive({
  agents: { analyzer },
  state: initialState,
  harness: new ClaudeHarness(), // Not called during replay
  recording: {
    mode: "replay",
    store,
    recordingId: "rec_abc123",
  },
});

Custom Signal Store

Implement the SignalStore interface for other backends:

import type { SignalStore, Recording, RecordingMetadata } from "@open-harness/core";

class PostgresSignalStore implements SignalStore {
  async saveRecording(recording: Recording): Promise<void> {
    await this.pool.query(
      "INSERT INTO recordings (id, data) VALUES ($1, $2)",
      [recording.id, JSON.stringify(recording)]
    );
  }

  async loadRecording(id: string): Promise<Recording | null> {
    const result = await this.pool.query(
      "SELECT data FROM recordings WHERE id = $1",
      [id]
    );
    return result.rows[0]?.data ?? null;
  }

  async listRecordings(options?: ListOptions): Promise<RecordingMetadata[]> {
    // Implement filtering and pagination
    return [];
  }

  async deleteRecording(id: string): Promise<void> {
    await this.pool.query("DELETE FROM recordings WHERE id = $1", [id]);
  }
}

What Gets Persisted

  • Signal Trace: Every signal emitted during execution
  • Metadata: Recording name, tags, timestamps, metrics
  • Final State: The state at workflow completion

Trade-offs

StoreProsCons
MemorySignalStoreFast, zero setupLost on restart
Custom DBScalable, durableMore ops work
File-based (coming soon)Simple persistenceSingle-process

Migrating to Production

  1. Start with MemorySignalStore locally
  2. Use recording/replay for deterministic tests
  3. Implement a custom store for production persistence

Next Steps

On this page