# Reflection loops

Scheduled or triggered reflect jobs.

Reflection is SurrealDB Agent Memory's mechanism for synthesising higher-order insights from accumulated memory. Unlike retrieval - which surfaces facts that already exist - reflection runs an LLM reasoning pass over a scope's memory and produces new insights that can be persisted back as experiential memory attributes. It is how SurrealDB Agent Memory moves from storing individual facts to producing understanding.

> [!NOTE]
> `Spectron` was the project name for SurrealDB Agent Memory. These type names
> will be renamed in a future release.

## What reflection does

A reflection request takes a query, a scope, and optional parameters, then:

1. Retrieves relevant memory items across the scope.
2. Sends them to a reasoning model alongside your query.
3. Returns a synthesised response.
4. If `persist: true`, stores the synthesised insights as new attributes on the relevant entities.

This is different from `context()`, which retrieves and ranks existing facts. Reflection reasons across facts to produce conclusions that are not explicitly stored anywhere.

## Basic reflection call

```python
from surrealdb import Spectron

memory = Spectron(context="support", api_key="sk-...")

result = await memory.reflect(
    query="What are Alice's most frequently reported frustrations?",
    persist=False)

print(result.reflection)
```

```typescript
import { Spectron } from "@surrealdb/spectron";

const memory = new Spectron({ context: "support", apiKey: "sk-..." });

const result = await memory.reflect({
    query: "What are Alice's most frequently reported frustrations?",
    persist: false });

console.log(result.reflection);
```

The `reflection` field is a free-form text response from the reasoning model. When `persist: false`, nothing is written back to memory - useful for exploratory analysis or generating one-off summaries.

## Persisting synthesised insights

Set `persist: true` to write the insights back as experiential memory attributes. The reasoning model produces structured attribute suggestions which are reconciled against the existing memory state before being committed.

```python
result = await memory.reflect(
    query="Summarise this customer's product preferences and risk of churn.",
    persist=True)
```

```typescript
const result = await memory.reflect({
    query: "Summarise this customer's product preferences and risk of churn.",
    persist: true });
```

`persist` is the only routing control: reflect writes back against the entities its
own evidence names, and returns them in `persistedAttributes`. There is no
`target_entity_type` / `target_attribute_key` - you cannot pin the write to a
chosen attribute. The persisted attributes appear in future `profile()` and
`context()` calls, enriching responses with synthesised understanding rather than
just raw facts.

## Cross-user reflection with supervisor keys

Supervisor API keys have broader scope access - they can reflect across multiple users or the entire organisation scope. This enables pattern analysis across your user base.

```python
supervisor_memory = Spectron(
    context="support",
    api_key="supervisor_sk_...",
)

result = await supervisor_memory.reflect(  # No user - reflects across all users in the org
    query="What are the most common product complaints this week?",
    persist=True)
```

```typescript
const supervisorMemory = new Spectron({
    context: "support",
    apiKey: "supervisor_sk_...",
});

const result = await supervisorMemory.reflect({
    // no user segment - reflects across everything the key can read
    query: "What are the most common product complaints this week?",
    persist: true,
});
```

## When to run reflections

Reflection is a compute-intensive operation. Appropriate trigger points:

- **End of session** - after a conversation closes, reflect to produce a session summary and update the user's churn risk or sentiment attributes.
- **Daily batch** - run a nightly reflection across all active users to update aggregate attributes.
- **Event-triggered** - run a targeted reflection when a specific event occurs (a complaint, a high-value purchase, an escalation).
- **Weekly insights** - broader organisational reflections that surface cross-user patterns.

### Scheduling as a background job

```python
import asyncio
from datetime import datetime, timezone

async def nightly_reflection(memory, org_id: str):
    """Run nightly reflection for all users in an org."""
    # GET /entities filters on type only - the key's read region bounds the rest
    entities = await memory.entities.list(type="Customer")

    for customer in entities:
        await memory.reflect(
            query="Update this customer's satisfaction score and churn risk based on recent interactions.",
            persist=True)
        # Respect rate limits between requests
        await asyncio.sleep(0.5)

    print(f"[{datetime.now(timezone.utc).isoformat()}] Nightly reflection complete for {len(entities)} customers.")
```

```typescript
async function nightlyReflection(memory: Memory, orgId: string): Promise<void> {
    // GET /entities filters on type only - the key's read region bounds the rest
    const entities = await memory.entities.list({ type: "Customer" });

    for (const customer of entities) {
        await memory.reflect({
            query: "Update this customer's satisfaction score and churn risk based on recent interactions.",
            persist: true });

        await new Promise(r => setTimeout(r, 500));
    }

    console.log(`Nightly reflection complete for ${entities.length} customers.`);
}
```

## Example reflection queries

| Use case | Query |
|---|---|
| Session summary | "Summarise this conversation and any commitments the agent made." |
| Customer health | "Rate this customer's satisfaction and likelihood to renew (1-10)." |
| Project risk | "What risks or blockers have been mentioned about this project?" |
| Complaint patterns | "What product issues have been raised most frequently this month?" |
| Learning trajectory | "What topics has this learner mastered and what gaps remain?" |

## Reflection versus retrieval

| | `context()` / `recall()` | `reflect()` |
|---|---|---|
| What it does | Retrieves existing facts | Reasons across facts to produce new conclusions |
| Output | Ranked memory items | Free-form synthesis (+ optional persisted attributes) |
| Cost | Low (retrieval only) | Higher (LLM reasoning pass) |
| When to use | Before every LLM call | Periodically or on specific events |
