← Series contents · Complete reading view
Memory: what was said, what was shown and what is true
A guest is shown three properties. Several turns later, after asking about parking and changing the dates, they say: “Let’s go with the second one from the earlier dates.”
The visible transcript may contain property names, but internal IDs are deliberately excluded from guest-facing text. Re-reading that transcript is not enough to determine the exact listing, the search it belonged to or whether its old checkout link is still valid.
This is a memory problem, but a vector database is not the first answer. The missing information is structured operational state.
Four different stores of meaning
The platform distinguishes conversation history, retrieved knowledge, working state and live domain records.
History says what was communicated. Knowledge contains property manuals and FAQs. Working state records the options and actions relevant to the current conversation. Domain records determine whether a reservation exists, a task is assigned or a calendar slot is available.
They can disagree because they represent different times and purposes. A message saying “available” is historical evidence of an offer, not a permanent availability guarantee. A guest’s statement “I paid” is conversational evidence, not the payment system’s state.
Hermes’ persistent memory is a useful external reference for separating durable personal context from the current exchange. The hospitality design needed an additional emphasis: structured state with business identifiers and freshness rules, rather than treating operational facts as free-form remembered prose. Hermes persistent memory
From a recent working set to booking memory
A useful first memory layer recovers recently presented options from completed tool results. It restores the link between the conversation and the exact business objects involved. The next design step is to preserve separate searches, their dates and the order in which choices were shown, so a later search does not silently redefine an earlier reference.
Three common failures show why a flat “recent properties” list is insufficient. Truncation can discard an option the guest still remembers. A new date range can overwrite the meaning of an old ordinal. A stored base price can be mistaken for the calendar’s quoted total. Treat search identity, presentation history and price provenance as distinct fields.
Retention should be bounded by relevance and decision value. Keep searches still referenced by the conversation, expire stale quotes, and summarise older discussion without discarding the identity of unresolved choices. A limit on stored records is a resource policy; it should not silently change what “the second option from earlier” means.
{
"search_key": "city|2026-10-10|2026-10-13|4",
"params": {"guests": 4, "nights": 3},
"shown_upto": 3,
"total_available": 7,
"results": [
{"ordinal": 1, "listing_id": "property-a", "name": "Harbour House"},
{"ordinal": 2, "listing_id": "property-b", "name": "Garden Apartment"},
{"ordinal": 3, "listing_id": "property-c", "name": "Courtyard Studio"}
]
}
The names and dates here are fictional teaching data. The structural point is that an ordinal is meaningful inside a particular search. It should not be a global “second property” variable that silently changes after every query.
Resolve references, then revalidate facts
Reference resolution and business validation are separate steps. The memory can identify what “the second one” referred to. It cannot establish that the option is still bookable.
A compact resolver can make ambiguity explicit:
def resolve_ordinal(searches, search_key, ordinal):
search = next((s for s in searches if s["key"] == search_key), None)
if search is None:
return {"status": "unknown_search"}
matches = [r for r in search["results"] if r["ordinal"] == ordinal]
if len(matches) != 1:
return {"status": "ambiguous_option"}
return {"status": "resolved", "listing_id": matches[0]["listing_id"]}
The next step is a fresh calendar read. This is why memory should retain provenance and timestamps, not just a confident sentence. A cached fact can be useful for conversation continuity while still requiring revalidation before an action.
A guest can have more than one stay
The stay flow adds another distinction: the set of stays the guest is entitled to reference and the current focus of the conversation. The backend may attach one reservation to a thread, but the guest may be asking about another legitimate stay.
The resolver should use explicit references, recent choices and confirmation context. When more than one stay is plausible, an action needs clarification. It should not silently apply the complaint or checkout request to whichever reservation happened to be first.
The tool layer receives the resolved focus and the guest’s own stay set. That is stronger than asking the model to keep the correct ID in mind. A property-specific knowledge read must remain inside that scope, and access information can require an additional stay-window check.
Issue state remembers commitments
For maintenance, useful memory includes the issue title, associated task, reservation, assignee, slot, escalation and updates already sent. This lets a later “any news?” refer to a known issue instead of listing all tasks at a property and guessing which belongs to the guest.
The memory record does not replace a current status fetch. It supplies the identifier and conversational continuity for that fetch. The answer can then say what changed since the last update without treating the last update as current truth.
An issue record should preserve the difference between created, proposed, deduplicated and escalated outcomes. Flattening them to success=true loses the information needed for an honest response.
Freshness is specific to the source
Conversation working state changes within a turn and often needs a read after a write. Authored property descriptions can tolerate caching; availability and action status require their own freshness rules. Cache by the decision that consumes the data, rather than applying one expiry to every form of memory.
The right question is not “how long should memory live?” It is “what decision will use this fact, and how stale can the fact be for that decision?” A property description can survive longer than a nightly price. A previous search can remain in memory while every selection is rechecked.
Retention also has a user boundary. State should be keyed by tenant and the appropriate conversation or actor identity. A helpful memory shared across unrelated guests is a data leak, not a feature.
Keep memory behind a capability contract
A memory provider should answer a narrow contract: load the relevant state, apply a validated update, and expose provenance and version. Retrieval can use a search adapter while operational state uses transactional storage. Neither provider should require the model to know where the data lives.
This separation makes replacement practical. Changing a search index should not alter the authority of a reservation record. Replacing a state store should preserve conflict detection and reference resolution. Test these guarantees at the boundary instead of treating a particular memory product as the architecture.
State updates need concurrency rules
A stateless harness does not make the state store race-free. Two turns can read the same version, make different updates and overwrite one another. Booking and issue state therefore need an explicit update strategy: a database transaction, version check, serialised session lane or a carefully designed merge.
One implementation option is to load the latest state inside a database transaction, apply a reducer and increment a version. Another is an optimistic update conditioned on the expected version. Both protect the state update itself; neither automatically serialises external actions across an entire turn. Test retries and competing updates against the required guarantee.
For a reference implementation, make updates reducers over typed state and test them independently. Then test two competing updates against the actual storage implementation. The first tests business logic; the second tests the concurrency guarantee.
What good memory enables
The practical benefit is continuity with evidence: earlier options stay addressable, property facts remain scoped, a later issue update has a known task, and selection can be revalidated against current data.
Memory is valuable when it reduces repeated questions without creating stale authority. That is the standard against which a more elaborate vector or graph layer should be judged.