Osy#the first language built for agents
Agents firstAgentic appsWorkflowsDurable Execution — built inSecurityTestingThe editorThe UI modelOne program

Reference / Config

identifier patterns (app.Memory)

app.Memory = new MemoryConfig { Identifiers = [ @"ORD-\d{6}" ] };

`app.Memory` tells search what an identifier looks like in YOUR data — an order number, a part code, an SKU. Search already spots identifier-shaped tokens in a query and matches them exactly, but it has to guess at the shape; declaring the patterns replaces the guess with an answer, and turns the guessing off.

stable2 examples compiled by CIconfigmemorysearch

Summary#

Some tokens carry meaning no amount of language understanding can recover: ORD-004471, AB1234X, 000346. A search engine that only understands meaning cannot find them reliably, so the platform also matches such tokens EXACTLY, and weights that match heavily — but only when it is confident the query contains one.

Left alone it decides by shape: a token with a digit and at least four characters. That works, and it is a guess about your data. app.Memory lets you state the shapes instead.

Signature#

app.Memory = new MemoryConfig {
  Identifiers = [ @"ORD-\d{6}", @"[A-Z]{2}\d{4}[A-Z]" ]
};

Description#

Each entry is a regular expression. A query is scanned for them, and anything found is matched exactly against the corpus alongside the ordinary meaning-based search.

Declaring turns the built-in guessing OFF. You have answered the question the guess was standing in for, and running both would put the guesses back on exactly the queries your patterns did not match — the ones you have implicitly said contain no identifier.

That matters because the shape guess is not perfect on real language. Measured against a public benchmark, it fired on 6 of 470 questions and five of those were not identifiers at all — 15th, 10th, 5-day, pre-1920. Those now abstain, but a corpus whose codes look like ordinary numbers is still better served by saying so.

Patterns are checked when you compile. A pattern that is not a valid regular expression is a compile error naming it — not a search that fails later, in production, on the first query that happens to reach it.

They are also checked for SPEED. Patterns run once per query against text a caller supplied, so a pattern that can take exponential time on an unlucky input is refused at compile time rather than becoming a way to stall your app. In practice this rules out backreferences and lookaround; ordinary character classes, quantifiers and anchors are all fine.

Use @"…" for a pattern, as in every example here. Inside @"…" a backslash is just a backslash, which is what a regular expression is made of.

Removing the declaration puts you back to the built-in behaviour — the stored patterns go with it.

Examples#

using Osyrin.Memory;

entity Order {
  [MaxLength(64)] string Reference;
  [Searchable(Memory)] string? Notes;
}

app.Memory = new MemoryConfig {
  Identifiers = [ @"ORD-\d{6}", @"[A-Z]{3}-\d{4}" ]
};
using Osyrin.Memory;

List<SearchHit> Chase(string question) {
  // "did we ever sort out the packaging fault on ORD-004471?" matches that order's notes on the token
  // itself — not merely on sounding like a packaging complaint.
  return Memory.Search(question, limit: 5);
}

See also#

Related

using Memory (semantic search)

Opt into semantic (vector) search over your app's content. `using Memory;` adds a searchable store to the app…

[Searchable]

Mark a text field searchable. `[Searchable]` gives a String or Markdown property the best relevance search the app can…

How retrieval works

What happens between `Memory.Search("…")` and the list you get back — indexing, matching, ranking and the two…

per-environment config (app.Config)

`app.Config` declares your app's per-environment settings — values that differ between development and production, like…