Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Meza-dev/Ghostly/llms.txt

Use this file to discover all available pages before exploring further.

Every time Ghostly completes an assisted run successfully, it has learned something valuable: the exact sequence of browser actions that achieves a given goal on a specific application. Assist Memory is the system that captures this knowledge and puts it to work on future runs. Instead of asking the LLM to plan the entire flow from scratch each time, Ghostly seeds the planner with the steps that worked last time — turning what was once a multi-horizon planning exercise into a near-instant replay that only falls back to AI planning when the remembered flow breaks.

Three Memory Modes

The memoryMode field controls how aggressively Ghostly persists and reuses learned flows:
Memory is completely disabled. Every run starts from scratch — the strategist plans the full flow from the initial page snapshot with no prior knowledge. Use this when you explicitly want the AI to explore the application without any bias from past runs, or when testing that a UI change is reflected in new plans.
assist: {
  v2: true,
  goal: "Create a new project and verify it appears in the list",
  memoryMode: "off",
}

How Memory Is Persisted

After a run completes with status: "pass", the API checks whether memoryMode is not "off" and then upserts the learned flow into the database:
// From apps/api/src/store/runs.ts (upsertAssistMemory)

await upsertAssistMemory({
  userId: user.id,
  project,                     // e.g. "my-app"
  baseUrl: parsed.data.baseUrl,// e.g. "https://staging.example.com"
  goal: assistV2.goal,         // The exact natural-language goal string
  steps: memoryCandidateSteps, // learnedFlow from the assisted result
});
The upsert uses a UNIQUE constraint on (userId, project, baseUrl, goal) — so each unique combination of user, project, URL, and goal has at most one memory entry. When a new passing run arrives, the stored steps are overwritten with the freshest successful flow.

The assist_memories Database Table

-- From apps/api/prisma/schema.prisma

model AssistMemory {
  id        String   @id @default(cuid())
  userId    String           -- Owning user (memories are per-user)
  project   String           -- Project slug
  baseUrl   String           -- Base URL the flow ran against
  goal      String           -- Exact goal string (case-sensitive)
  stepsJson String           -- JSON array of Step objects
  hits      Int      @default(0) -- How many times this memory was loaded
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@unique([userId, project, baseUrl, goal])
}
The hits counter increments every time a memory entry is loaded for replay. This makes it easy to identify the most frequently reused flows and to monitor memory health over time.

How Replay Works at Runtime

When a run starts with memoryMode: "adaptive", the API looks up existing memory before launching the browser:
1

Memory Lookup

getAssistMemory({ userId, project, baseUrl, goal }) queries the assist_memories table. If no entry exists, the lookup returns an empty array.
2

Seed Injection

If steps are found, they are passed into the assisted run input as seedMemorySteps and replayFromMemory: true. The pipeline treats these as the initial pendingSteps queue rather than the seed goto step.
3

Memory Hit or Miss Event

The pipeline emits either a memory_hit event (with candidates count and source: "durable") or a memory_miss event. Both are visible in the live event stream and stored in the run’s event log.
4

Replay Execution

The replayed steps execute exactly as they did in the original successful run. If a step fails (because the UI changed), the healer activates and self-healing begins — effectively updating the remembered flow in real time. The new successful steps are written back on the next pass.
5

Post-Run Upsert

If the run passes again, the memory entry is updated with the current learnedFlow — which may include healed steps that replaced the old selectors.

Memory Hit and Miss Events

// memory_hit payload
{
  horizon: 1,
  candidates: 7,           // Number of seed steps loaded
  source: "durable"        // "durable" = from DB; "runtime" = in-process cache
}

// memory_miss payload
{
  horizon: 1               // No memory found; AI plans from scratch
}
Assist memory is per-user. Two users with identical goals and project names have separate memory entries and cannot share flows. Team-shared memory is not yet supported — it is on the Ghostly roadmap.

Sanitization Rules

Before a flow is stored, sanitizeMemorySteps() applies two filters:
  1. No [REDACTED] values — fill steps where the value was redacted (e.g. passwords) are excluded to avoid storing useless placeholders that would break replays.
  2. Deduplication and size cap — identical consecutive steps are collapsed and at most 40 steps are stored per memory entry.
Use adaptive mode (the default) in CI environments. After the first run teaches Ghostly the flow, all subsequent runs for the same goal skip the planning horizons entirely and execute from memory — making regression runs significantly faster and consuming far fewer LLM tokens.

Build docs developers (and LLMs) love