Synsema docsENES

Memory & state

Persistent agent state is declared, not implicit. One line at the top of the program names the memory and unlocks the whole family — memory, owner rules, and progress:

require memory("support-agent")

The declared name is the identity: state persists in <program-dir>/.synsema/state/<name>.db (gitignore .synsema/), keyed by that name — not by the filename. remember() in one run is found by recall() in the next; renaming the .syn file changes nothing; two entry points that declare the same name share one memory.

memory.syn
-- Doc example: DECLARED agent memory, progress, and owner rules (persist to SQLite).
-- The declared name IS the identity: state lives in .synsema/state/doc-memory.db,
-- keyed by the name below — not by this file's name. Without the declaration the
-- whole family fails with `Capability not granted: memory` and creates no files.
intent: "doc example: declared memory, namespaces, progress, rules"
require memory("doc-memory")

remember("learning", "demo note from run", ["demo"])
print("recalled → " + text((recall("learning", ["demo"])[0])["content"]))

test "remember then recall — newest first ([0] is the most recent)"
    remember("learning", "API is slow on Mondays", ["api"])
    let notes be recall("learning", ["api"])
    assert_eq((notes[0])["content"], "API is slow on Mondays")

test "recall named args: limit caps results; from filters by writer namespace"
    remember("context", "note-a", ["ns"])
    remember("context", "note-b", ["ns"])
    assert_eq(length(recall("context", ["ns"], limit = 1)), 1)
    -- top-level writes source = "main"; agents write under their own name
    assert(length(recall("context", ["ns"], from = "main")) >= 2)
    assert_eq(length(recall("context", ["ns"], from = "nobody")), 0)

test "progress: resume_point returns the step to resume from"
    create_progress("import", ["ingest", "validate", "load"])
    start_step("import", "ingest")
    complete_step("import", "ingest", "100 rows")
    assert_eq(resume_point("import"), "validate")

test "owner rules: a numeric must-rule flags a violation"
    add_rule("max_discount", "must", "discount <= 0.20", "pricing")
    assert(length(check_rules("pricing", {"discount": 0.25})) > 0)

The declaration (know this before anything else)

Persistent memory

require memory("assistant")
remember("learning", "API slow on Mondays", ["api", "performance"])
let notes be recall("learning", ["api"])        -- newest first ([0] = most recent)
let hits  be recall(nothing, nothing, "Monday") -- free-text search (skip args with nothing)
forget_memory(entry_id)

A recall entry is a map with id, category, content, source, tags.

recall takes 6 argsrecall(category, tags, search, mode, limit, from) — all optional, all usable as named args (recall("learning", limit = 10)):

ArgMeaning
categoryone of the fixed categories (below)
tagslist; OR by default
searchfree-text substring match
mode"all" = every tag must match (AND)
limitmax entries, default 200
fromsource namespace to read (see next section)
Categories are a fixed English set: preference, rule, learning, decision, context. Any other string (e.g. "preferencia") raises an error.

Per-agent namespaces (source / from)

Each entry records its writer in source: inside agent X a remember writes source = "X"; top-level code (and serve handlers) write "main". Reads are namespaced by default, so agents sharing one memory don't confuse each other's notes:

require memory("newsroom")

agent Writer
    remember("context", "draft done")        -- source = "Writer"

agent Analyzer
    let mine   be recall()                   -- only Analyzer's own entries (default)
    let theirs be recall(from = "Writer")    -- explicit cross-namespace read
    let all    be recall(from = "*")         -- everything

spawn Writer
spawn Analyzer
let everything be recall()                   -- top-level sees ALL by default

Rules and progress are not namespaced — one rulebook, one plan board per program.

Progress (crash-resumable)

require memory("import-agent")
create_progress("import", ["ingest", "validate", "load"])
start_step("import", "ingest")
complete_step("import", "ingest", "100 rows")     -- or fail_step(...)
let where be resume_point("import")               -- "validate" — where to resume after a restart

Owner rules

require memory("pricing-agent")
add_rule("max_discount", "must", "discount <= 0.20", "pricing")
let violations be check_rules("pricing", {"discount": 0.25})   -- non-empty → violated

Levels: must (hard block), should (warning), avoid / prefer (preferences). Numeric conditions are evaluated against the context map. get_rules(category?) lists them; memory_summary() prints an overview of everything stored.

Serve state (per-process, in-memory)

Under serve, state_* builtins (e.g. state_incr("visits")) share in-memory state across requests — see HTTP server. (They're a serve feature, not available in plain run, and they need no memory declaration — they never touch disk.) For durable state, use the declared memory/progress builtins above or a database.