Connect by JBRH Open Connect

Structured memory

Structured memory means storing what is known as typed records — a fact with a scope, an owner and a tag — instead of keeping a transcript and re-reading it. The difference is not storage efficiency. It is that a record can be queried, corrected, scoped, audited and deleted, and a transcript can only be searched and re-read.

Status
Reference What this means
Audience
both, developer
In the app
#/data
Last verified
Product version
6.3.2

The same knowledge, two ways to keep it#

OperationTranscriptRecord
Find what applies to this contactSearch text and hope the phrasing matchesSelect by scope and key
Correct something wrongAppend a correction and hope the later one winsEdit the row; the old value stops applying at once
Forget one thingEffectively impossible without deleting the conversationDelete the row
Apply a rule narrowlyNo mechanismSet it at the narrower scope
Explain why the agent did thatReconstruct from proseShow the row that applied
Cost per turnGrows with historyBounded by the budget you set

The second column is how most conversational systems remember, and it is why they drift. A correction buried at turn forty competes with the original statement at turn three, and the model resolves that competition however it resolves it. Making the correction a write to a record removes the competition instead of arbitrating it.

Does Connect use structured memory?#

Used, as the only memory design in the product. connect_memory.py holds four tiers, resolved narrowest-first: workspace → channel → endpoint → contact. An endpoint is one mailbox or one phone number. tiers() returns everything that applies to a piece of work, split by the tier that owns it — and an empty tier comes back empty rather than being dropped, so 'nothing is set at this level' is a visible answer instead of an absence you have to infer.

That hierarchy is the same one autonomy uses, deliberately. A person who has learned that the narrowest scope wins for what Connect may *do* already knows the rule for what Connect *knows*.

The design detail that shows the pattern best is blocking. Blocking a contact on a channel is not a column. It is a memory row against that contact, tagged block:<channel> in its tag list — because directives() reads only the tags, never the body. Keeping it as a tagged record rather than a boolean field is what makes a block hold across channels and across conversations that have not happened yet, and what makes it visible in the same place as everything else Connect knows about that person.

A person can read every tier and forget any of it, from the memory viewer mounted on the mailbox row, the channel screen and the contact panel. Memory that cannot be inspected is indistinguishable from a model's mood.

What becomes possible#

  • Scoped rules. 'Never quote lead times to this one customer' is a contact-tier row that overrides a workspace-tier one, without a special case anywhere in the code.
  • Answerable questions about the agent. What does Connect know about this mailbox? — a query, not an investigation.
  • Corrections that stick. The next answer changes because the row changed. See making a correction actually change behaviour.
  • A bounded prompt. Memory contributes a fixed budget to each call — 700 characters on the voice path — rather than a growing history.
  • Deletion that means something. A deleted row stops applying immediately, which is a claim a transcript-based system cannot honestly make.
  • A grid over the whole of it. Memory is one of the 13 sheets on Files and data, alongside companies, people, leads, prospects, follow-ups, deals, conversations, calls, cases, onboarding, knowledge and files.

The costs, stated plainly#

Something must decide what to keep
A transcript keeps everything by default. Records require an extraction step, and anything not extracted is not remembered.
Scope choice is a real decision
A fact filed at the workspace tier that belonged at the contact tier will apply where it should not, quietly.
Contradiction becomes explicit
Two rows disagreeing at the same tier is a state you have to design for. In a transcript the same contradiction hides in prose.
Migrations
Records have a schema and a schema changes. migrate.py runs on every boot for exactly this reason.

Questions#

Does structured memory mean the agent forgets the conversation?

No — the conversation is still a record in its own right, with its messages and its timeline. The distinction is which one is consulted when Connect needs to know something durable. Reading the thread tells you what was said; reading memory tells you what is true.

Why keep a block as a tag rather than a field?

Because a field belongs to one table and one channel. A tagged row against the contact travels with the person, holds on channels that did not exist when it was set, and appears wherever memory appears. directives() reading only the tag list is what makes the behaviour reliable rather than dependent on wording.

What stops memory growing until it costs too much?

The per-call budget, not the store. What is kept can grow; what is sent on any one call is capped, and tier resolution decides which rows earn the space.