Context Memory

Every SmrtObject can store and retrieve small pieces of learned context — a parsing strategy that worked, a per-source override, a cached decision — keyed by a scope and a key, with a confidence score. It is built into the base class and persists to the _smrt_contexts system table.

When to reach for it

Context memory is for knowledge an object accumulates over time, not for its primary fields. Typical uses: remembering which CSS selector extracted an article from a given site, caching the shape of a third-party response, or recording a strategy an agent should reuse on its next run. Each entry carries a confidence so you can prefer high-confidence knowledge and discard the rest.

remember

Store a value under a scope and key. The value is any JSON-serializable data. confidence defaults to 1.0.

typescript
// Remember a parsing strategy that worked for this document's source
await document.remember({
  scope: 'parser/example.com',
  key: 'article-selector',
  value: { pattern: '.article-content p' },
  confidence: 0.9
});

The full options:

OptionTypeNotes
scopestringSlash-delimited path, e.g. 'parser/example.com/article'.
keystringLookup key within the scope.
valueanyJSON-serialized on write.
confidencenumber0–1. Default 1.0. Higher entries win on recall.
versionnumberDefault 1. Part of the upsert key, so versions coexist.
metadataanyOptional JSON sidecar.
expiresAtDateOptional expiry timestamp stored with the entry.

recall and hierarchical scopes

recall() returns the best matching value — highest confidence, then highest version — or null. Its most useful feature is includeAncestors: when the exact scope has no entry, it walks up the scope path one segment at a time, ending at global.

typescript
const strategy = await document.recall({
  scope: 'parser/example.com/article',
  key: 'article-selector',
  includeAncestors: true, // tries example.com/article -> example.com -> parser -> global
  minConfidence: 0.7      // ignore low-confidence entries
});

if (strategy) {
  // use strategy.pattern
}

This lets you store a general default at a broad scope and override it at a narrower one — the narrowest match wins, with graceful fallback.

recallAll, forget, forgetScope

Bulk-read or clear remembered context:

typescript
// Read every entry in a scope as a Map<key, value>
const all = await document.recallAll({
  scope: 'parser/example.com',
  includeDescendants: true, // also include parser/example.com/*
  minConfidence: 0.5
});

// Delete a single entry
await document.forget({ scope: 'parser/example.com', key: 'article-selector' });

// Delete an entire scope (and optionally its descendants); returns the count
const removed = await document.forgetScope({
  scope: 'parser/example.com',
  includeDescendants: true
});
MethodReturnsPurpose
remember(options)voidUpsert one entry.
recall(options)any | nullBest single match, with optional ancestor fallback.
recallAll(options)Map<string, any>All entries in a scope (optionally including descendants).
forget(options)voidDelete one entry by scope + key.
forgetScope(options)numberDelete a whole scope; returns rows removed.

Confidence and expiry

confidence is how you let knowledge improve over time: re-remember the same scope/key with a higher score as evidence accumulates, and read with minConfidence to filter out weak entries. Because version is part of the upsert key, you can also keep multiple versions of an entry side by side.

Worked example: an agent that learns

typescript
@smrt()
class Scraper extends Agent {
  protected config = {};

  async scrape(url: string): Promise<string> {
    const host = new URL(url).host;

    // Try a previously-learned selector for this host (falling back upward)
    const learned = await this.recall({
      scope: `parser/${host}`,
      key: 'selector',
      includeAncestors: true,
      minConfidence: 0.6
    });

    const selector = learned?.pattern ?? '.content';
    const text = await this.extract(url, selector);

    // If extraction looked good, reinforce the strategy
    if (text.length > 500) {
      await this.remember({
        scope: `parser/${host}`,
        key: 'selector',
        value: { pattern: selector },
        confidence: 0.9
      });
    }
    return text;
  }
}

Related

Verified against SMRT v0.29.34.