Multi-user memory isolation method and system based on cross-thread delivery of message metadata
Patent Information
- Application Number
- CN202611062373.0
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-07-17
- Publication Date
- 2026-08-21
AI Technical Summary
第一,该方案以消息内容本身作为处理对象,对每一消息进行独立的一次性敏感度判定,其消息流转过程为无状态传递,未涉及用户身份标识在异步线程切换过程中的跨线程传递问题,也未涉及将用户标识作为长期记忆隔离主键的绑定与传递机制,无法解决响应式编程框架下因线程切换导致用户上下文丢失或串扰的问题
关于信息承载对象,现有技术中的消息为一次性数据载体,各模块依次处理完成后消息即完成使命,不具备承载跨模块、跨生命周期状态信息的能力,其元数据属性亦未被赋予传递用户身份标识的功能定义。本申请以Msg对象作为响应式流中持续传递的数据载体,Msg对象具有键值映射结构的元数据属性,该元数据属性被专门用于存储用户标识信息。用户标识信息一旦写入Msg元数据,便与Msg对象绑定,Msg对象在响应式流中流转至何处,用户标识信息即传递至何处,使Msg对象成为有状态、跨生命周期的上下文载体。
Smart Images

Figure CN122615902A_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the field of data processing technology, and in particular to a multi-user memory isolation method and system based on cross-thread transmission of message metadata. Background Technology
[0002] With the rapid development of large language model (LLM) agent technology, long-term memory has become a key support for agents to achieve continuous dialogue across conversations and personalized services. In enterprise-level agent platforms, concurrent access by multiple users is the norm. The dialogue history and long-term memory of different users must be strictly isolated to prevent user A's memory data from being retrieved by user B, which could lead to serious data leakage and privacy compliance risks. Meanwhile, enterprise applications commonly use reactive programming frameworks to handle high-concurrency streaming processing demands. These frameworks, through dynamic scheduling of thread pools and non-blocking asynchronous processing mechanisms, cause frequent switching of request processing threads, making it impossible to guarantee that the same request is always bound to a fixed thread. Against this technical backdrop, how to reliably transmit user identity identifiers to the long-term memory module during the reactive asynchronous streaming processing of large model agents, thereby achieving precise isolation of multi-user memories, has become a key engineering technical problem restricting the large-scale deployment of LLM agents in enterprise-level scenarios.
[0003] Currently, Chinese patent application CN114282262A discloses a message forwarder for identifying message sensitivity. This scheme involves using a message forwarder as an intermediary node between the message sender and receiver, performing keyword matching and regular expression matching on the message content, calculating the message sensitivity, and determining whether to forward the message to the receiver or intercept and report back to the sender based on whether the sensitivity exceeds a threshold. This scheme can identify sensitive content during message flow, preventing the leakage of messages carrying sensitive data.
[0004] However, the above-mentioned existing technical solutions still have the following technical problems: First, this solution treats the message content itself as the processing object, performing an independent one-time sensitivity determination on each message. Its message flow process is stateless and does not involve the cross-thread transmission of user identity identifiers during asynchronous thread switching, nor does it involve the binding and transmission mechanism of user identifiers as long-term memory isolation primary keys. Therefore, it cannot solve the problem of user context loss or crosstalk caused by thread switching under reactive programming frameworks.
[0005] Second, the scheme uses fixed keywords and regular expression rules to match message content, which is a passive, one-time matching mechanism. It cannot identify the user's intention to recall and actively trigger memory retrieval accordingly. As a result, when the user clearly expresses the need to recall, it still relies on the LLM to determine whether to call the retrieval tool, resulting in insufficient retrieval triggering.
[0006] Third, in this solution, when the message sensitivity exceeds the threshold, the message is directly intercepted and a technical result is fed back to the sender. There is no friendly degradation prompt mechanism for memory service retrieval failure scenarios. When the memory service is abnormal or no retrieval result is found, an exception may be thrown directly or an empty result may be returned, which will affect the user experience and the continuity of the conversation. Summary of the Invention
[0007] To address the shortcomings of the existing technology, this invention provides a multi-user memory isolation method and system based on cross-thread message metadata transmission.
[0008] On one hand, this invention provides a multi-user memory isolation method based on cross-thread message metadata transmission. This method is executed within a reactive programming framework, using a Msg object as the data carrier for carrying user messages and continuously transmitting them in a reactive stream. The Msg object has metadata attributes, which are key-value mapping data structures used to store user identification information. The method includes the following steps: S1. At the request entry point, obtain the user identification information associated with the current request. The user identification information includes at least a user ID. Write the user identification information into the metadata field of the Msg object, and input the Msg object as a data element to be transmitted in the reactive stream. The metadata field is explicitly transferred between asynchronous threads as the Msg object is chained through reactive operators such as map and flatMap in the reactive stream. At the same time, construct an immutable request context object at the request entry point. The request context object holds the user identification information and is bound to the memory retrieval tool instance created for the request.
[0009] S2. When the long-term memory retrieval method is invoked, the retrieval method receives a Msg object as an input parameter, forcibly extracts user identification information from the metadata field of the Msg object, and performs a non-empty check on the extraction result.
[0010] If the metadata field of the Msg object is empty, or the metadata field does not contain a user ID key, or the value corresponding to the user ID key is empty or an empty string, it is determined that the user identifier is missing, and no access request is sent to the long-term memory service; instead, an empty search result is returned directly.
[0011] If the verification passes, the extracted user ID is used as the isolation primary key to call the retrieval interface of the long-term memory service to perform the retrieval operation. During the retrieval, the user ID is passed as the memory isolation primary key to the long-term memory service, so that the long-term memory service only returns the historical memory data corresponding to the user ID, thereby realizing user-based isolation retrieval on the server side, and the memory data corresponding to different user IDs are not visible to each other.
[0012] In the write path, when the long-term memory write method is called, the write method receives a list of Msg objects as input parameters, searches for the last user message from the Msg object list backwards, forcibly extracts the user identification information from the metadata field of the user message and performs a non-empty check. If the extraction result is empty, the write is skipped and an alarm log is recorded. If the check passes, the write operation is performed by calling the long-term memory service's write interface with the user ID as the isolation primary key, so that the written memory data is associated with the user ID for storage.
[0013] S3. During the retrieval process in step S2, recall intent recognition is performed on the incoming query text. The recall intent recognition adopts a two-layer concatenated mechanism: The first layer is the tool call admission layer, which imposes tool call constraints on the large model in the system prompts. The large model will call the memory retrieval tool only when the user inputs a clear intention to recall. The clear intention to recall includes at least asking about past conversation content, asking about personal information, and asking about previously mentioned matters. This layer decides whether to initiate long-term memory retrieval. A retrieval will be triggered at most once per round of conversation.
[0014] The second layer is the query rewriting layer. Only after the first layer has decided to initiate a retrieval and the memory retrieval tool has been invoked, does it perform a matching operation of a preset regular expression on the incoming query text within the long-term memory module. The regular expression is used to identify phrases such as "recall chat history about X", "recall X mentioned before", "find X's record", and "view X mentioned before". When a match is found, the keyword X is extracted from the query text, and the search term is rewritten as X with the addition of a time-limited word to replace the original query text, serving as a more focused search term for retrieval. If the regular expression is not matched, the original query text is retained as the search term. This layer does not initiate new retrievals independently, but only optimizes the queries already triggered by the first layer. The first and second layers are sequentially connected in a pipeline relationship, and no duplicate search requests are generated within a single round of dialogue.
[0015] S4. Obtain the retrieval execution results from step S3 and determine the retrieval execution results: If the retrieval is successful and returns a non-empty result, the retrieval result is returned to the large model agent, which then integrates the retrieval result into the final answer generation process.
[0016] If the search fails or returns an empty result, a preset friendly downgrade prompt text is generated. The downgrade prompt text is at least one of "No relevant historical memory found" or "Memory service is temporarily unavailable, please try again later". The downgrade prompt text is returned to the large model agent, which politely informs the user of the search results when generating a response, and the dialogue process continues without interruption.
[0017] The failure of the retrieval execution includes at least one of the following situations: the long-term memory service call times out, the long-term memory service returns a non-success status, the long-term memory service returns an error in result parsing, and the long-term memory service returns an empty result.
[0018] On the other hand, the present invention also provides a multi-user memory isolation system based on cross-thread message metadata transmission, the system comprising: The metadata writing module is used to obtain user identification information associated with the current request. The user identification information includes at least a user ID. The user identification information is written into the metadata field of the Msg object, and the Msg object is input into the reactive stream as a data element to be transmitted in the reactive stream. The metadata field is explicitly transferred across threads with the Msg object during the chained calls of reactive operators. The metadata writing module is also used to construct an immutable request context object at the request entry point. The request context object holds the user identification information and is bound to the memory retrieval tool instance created for the request.
[0019] The context passing module is used to pass the Msg object as a data element in the reactive stream and participate in the chained flow of reactive operators, so that the metadata fields of the Msg object are passed across threads in the reactive stream along with the message, and the reliable migration of user context is achieved between different threads through the passing of the data elements of the Msg object.
[0020] The user identifier extraction module is located at both the retrieval and write entry points. The retrieval entry point receives a Msg object as input and forcibly extracts user identifier information from the Msg object's metadata field. It performs a non-empty check on the extraction result. If the metadata field is empty, does not contain a user ID key, or the corresponding value for the user ID key is empty, the user identifier is considered missing, the retrieval is rejected, and an empty retrieval result is returned. If the check passes, the user ID is used as the isolation primary key to call the long-term memory service's retrieval interface. The write entry point receives a list of Msg objects as input and searches for the last user message in the list from right to left. It forcibly extracts user identifier information from the metadata field of that user message and performs a non-empty check. If the extraction result is empty, the write operation is skipped, and an alarm log is triggered. If the check passes, the user ID is used as the isolation primary key to call the long-term memory service's write interface, thus associating the memory data with the user ID for storage.
[0021] The recall intent recognition module is used to perform a matching operation of a preset regular expression on the input query text during the retrieval process. The regular expression is used to recognize the sentence patterns "recalling chat history about X", "recalling X mentioned before", "finding the record of X", and "viewing the X mentioned before". When a match is found, the keyword X is extracted from the query text and rewritten as X with the addition of a time-limited word to replace the original query text. When no match is found, the original query text is kept as the search term. The recall intent recognition module only performs query rewriting after the LLM has decided to initiate a retrieval through tool invocation. It does not initiate a retrieval request independently, thus forming a two-layer recall intent recognition mechanism in series with the LLM tool invocation admission layer.
[0022] The degradation processing module is used to obtain the retrieval execution results. When the retrieval execution is successful and a non-empty result is returned, the retrieval result is returned to the large model agent for generating an answer. When the retrieval execution fails or an empty result is returned, a preset friendly degradation prompt text is generated and returned to the large model agent. The large model agent integrates the degradation prompt text when generating an answer, so that the dialogue process is not interrupted.
[0023] The write control module receives a list of Msg objects as input parameters and iterates through the list from back to front to locate the last user message. It forcibly extracts user identification information from the metadata field of the user message. If the extraction result is empty, it skips the write operation and triggers an alarm log. If the verification is successful, it calls the write interface of the long-term memory service with the user ID as the isolation primary key, so that the memory data is stored in separate warehouses according to the user ID, ensuring that the memory data of different users maintains physical isolation at the persistence level.
[0024] Compared with the prior art, this application has the following advantages: Regarding the information carrier, existing technologies treat messages as one-time data carriers. Once each module has processed the message sequentially, its mission is complete. They lack the ability to carry cross-module, cross-lifecycle state information, and their metadata attributes are not defined to transmit user identification. This application uses the Msg object as a continuously transmitted data carrier in a reactive stream. The Msg object has a key-value mapping structure for its metadata attributes, which are specifically used to store user identification information. Once user identification information is written to the Msg metadata, it is bound to the Msg object. Wherever the Msg object flows in the reactive stream, the user identification information is transmitted there as well, making the Msg object a stateful, cross-lifecycle context carrier.
[0025] Regarding the context passing path, existing message flow technologies employ a synchronous processing mode, which does not involve asynchronous thread switching scenarios, cross-thread context passing mechanisms, or the technical problem of context loss due to thread switching. This application uses the Msg object as a data element passed in the reactive stream. During the chained calls of operators such as map and flatMap in the reactive stream, the Msg object is explicitly transferred between various asynchronous threads. Since the context is bound to the Msg object rather than the thread, its metadata fields naturally migrate to the new thread when the Msg object is passed between operators, requiring no additional context transfer operations. Simultaneously, an immutable request context object is constructed at the request entry point and bound to the memory retrieval tool instance, forming a double-protected path.
[0026] Regarding user identifier extraction and verification, existing technologies use whether the message content matches keywords or regular expressions as the matching object and whether the sensitivity value exceeds a threshold as the decision criterion, without involving the extraction and verification of user identifier information. This application forcibly extracts user identifier information from the Msg metadata and performs non-empty verification at the entry point of the long-term memory retrieval method. Specifically, it includes a three-fold determination of whether the metadata is empty, whether it contains a user ID key, and whether the value corresponding to the user ID key is empty. If the retrieval path is missing, an empty result is returned directly without accessing the memory service; if the write path is missing, the write is skipped and an alarm log is recorded. The judgment process does not rely on ThreadLocal.
[0027] Regarding recall intent recognition, existing technologies passively match message content using fixed keywords and regular expressions, which is a reactive, one-time matching mechanism that does not distinguish user need types and does not involve retrieval trigger decisions. This application adopts a two-layer chain mechanism: the first layer is determined by a large model based on tool call constraints in the system prompts, deciding whether to call the memory retrieval tool and whether to initiate a retrieval, triggered at most once per round of dialogue; the second layer only occurs after the first layer has decided to initiate a retrieval, when the long-term memory module performs preset regular expression matching on the query text, identifies recall-type sentences, extracts topic words and adds time-limited words to replace the original query text when a match is found, the second layer does not initiate a retrieval independently, but only optimizes the already triggered retrieval.
[0028] Regarding failure handling mechanisms, existing technologies directly intercept messages and send technical results to the sender when the sensitivity exceeds a threshold, which is a blocking approach. This application generates a pre-defined, friendly degradation message when the retrieval fails. This message is naturally integrated into the response generated by the large model agent and politely informs the user, allowing the dialogue to continue uninterrupted.
[0029] The aforementioned technical features are not simply superimposed, but rather have an interdependent and synergistic relationship: The cross-thread passing of Msg metadata and the forced extraction of user IDs form an interlocked and coordinated mechanism. The metadata passing mechanism provides a reliable context source for forced extraction, enabling the extraction module to safely obtain the user ID at any asynchronous execution stage; forced extraction and non-null checks provide architectural-level correctness guarantees for the passing mechanism, and the closed-loop rule of rejection for missing keys ensures that there are no dirty read or write paths due to missing or incorrect primary keys. The two are interlocked: the former makes forced extraction "traceable," and the latter ensures that metadata passing "stops any errors," jointly eradicating the path of cross-user pollution caused by thread errors.
[0030] User identification isolation and recall intent recognition work synergistically. Recall intent recognition, based on the reliably transmitted user ID in the Msg metadata, ensures that the search is always performed within the correct user scope; while recall intent recognition extracts and rewrites the keywords of the query text, enabling searches using user ID as the isolation key to achieve a higher hit rate within the correct user space. User identification isolation guarantees "correct search scope," while recall intent recognition improves "relevance of search results." The combination of the two ensures that the search is both "accurate" and "findable."
[0031] Forced isolation and friendly degradation fault tolerance work in synergy. Forced isolation refuses to execute when the user ID is missing, ensuring that cross-user error checks are not performed under normal circumstances; degradation processing generates a friendly prompt when the retrieval fails, allowing the conversation to continue without interruption. Forced isolation exempts the degradation mechanism from handling technical anomalies caused by missing primary keys, while the degradation mechanism ensures that forced isolation can safely return an empty result without affecting the user experience when the user ID is missing, together forming an end-to-end fault tolerance closed loop.
[0032] The three sets of collaborative relationships described above are interconnected in a chain of "reliable context transmission → mandatory primary key verification → recall relevance optimization → anomaly smoothing and fault tolerance". A break in any of these collaborations would prevent the simultaneous achievement of strong isolation and proactive recall. The superposition of multiple collaborative effects produces an integrated technical effect that surpasses the simple addition of individual technical features. Attached Figure Description
[0033] Figure 1 This is an overall flowchart of the method of the present invention; Figure 2 Write a detailed flowchart for writing metadata for step S1, bound to the context; Figure 3 A detailed flowchart for step S2, which involves forced extraction and non-empty verification of the user identifier; Figure 4 A detailed flowchart of the two-layer concatenated mechanism for recalling intent recognition in step S3; Figure 5 This is a detailed flowchart of step S4, which involves determining and downgrading search results. Figure 6This is a diagram showing the overall architecture of the system of the present invention. Detailed Implementation
[0034] To enable those skilled in the art to more clearly understand the technical solution of this application, some terms involved in this embodiment are explained as follows.
[0035] In a reactive programming framework, a Msg object is a data carrier that delivers user messages continuously within a reactive stream. A Msg object is a regular Java object that includes at least role, content, name, and metadata attributes. As a data element passed in a reactive sequence, the Msg object flows explicitly between upstream and downstream threads through reactive operators, and its metadata attributes migrate asynchronously along with the Msg object. The Msg object is not limited to the lifecycle of a single request but can span multiple rounds of dialogue within the same session. It is generated or reused from a unified entry point in each round and continuously delivered with the message stream.
[0036] Metadata attributes: These are key-value mapping data structure attributes belonging to the Msg object, used to store user identification information. The keys of metadata attributes are centrally managed by a unified constant class, including keys corresponding to user IDs, user types, and session IDs, to avoid spelling inconsistencies and silent failures caused by string distribution. Metadata attributes are an integral part of the Msg object, passing as a whole with the Msg object in the reactive stream without requiring additional context handling. Metadata attributes are specifically used to carry system-level metadata related to multi-user memory isolation, and are fundamentally different from the content attributes of the Msg object: content attributes store the dialogue text input by the user or output by the agent, belonging to user-generated data; metadata attributes store control data used by the system for logical isolation and routing decisions. The two differ in data nature, purpose, and management methods.
[0037] Reactive programming frameworks refer to asynchronous, non-blocking programming frameworks based on the reactive stream specification, including Project Reactor and RxJava. These frameworks handle concurrent requests through dynamic scheduling of thread pools and non-blocking asynchronous processing mechanisms. The processing of the same request may span multiple asynchronous threads, and it cannot be guaranteed that it will always be bound to a fixed thread.
[0038] Reactive operators: These are processing units in reactive programming frameworks used to transform, filter, and merge data elements in a reactive stream. They include the map operator, flatMap operator, and filter operator. During chained calls, reactive operators process the input data elements and output new data elements, with data elements explicitly flowing between operators.
[0039] An immutable request context object is an object constructed at the request entry point to hold user identification information associated with the current request. All member variables of this object are declared as final fields and initialized in the constructor. Once constructed, the user identification information it holds remains unchanged throughout the entire request processing and does not change with thread switching. This request context object is bound to a memory retrieval utility instance created for the request, allowing the memory retrieval utility to obtain user identification information from this request context object at any asynchronous execution phase without relying on thread-local storage.
[0040] Long-term memory service: refers to an external service or internal module that provides persistent storage and retrieval functionality for historical dialogue memories of large language model agents. The long-term memory service provides at least a retrieval interface and a write interface. The retrieval interface is used to retrieve historical memory data based on the query text and the isolation key, while the write interface is used to associate and store the memory data of the current dialogue with the isolation key. Specific implementations of the long-term memory service include Mem0 and self-built memory banks with similar functionality.
[0041] An isolation key is a key value used in a long-term memory service to distinguish the data storage range of different users' memory data. The long-term memory service uses the isolation key as the basis for data partitioning or isolation. Memory data corresponding to the same isolation key belongs only to the user identified by that isolation key, and memory data corresponding to different isolation keys are not visible to each other. In this application, the isolation key includes at least the user ID. During retrieval and write operations, the user ID is also passed to the long-term memory service as the memory isolation key.
[0042] Memory intent refers to a user's subjective need to review or retrieve past conversation content, as expressed in the dialogue. User input with a clear memory intent includes at least asking about past conversation content, asking for personal information, and asking about previously mentioned matters.
[0043] Tool Invocation Admission Layer: This refers to the mechanism that imposes tool invocation constraints on the large model through system prompts. This mechanism stipulates that the large model can only invoke memory retrieval tools via tool invocation when the user's input clearly indicates a recall intent; otherwise, the large model must not invoke memory retrieval tools. The tool invocation admission layer determines whether to initiate long-term memory retrieval, and a retrieval can be triggered at most once per turn of dialogue.
[0044] Query rewriting layer: This refers to the mechanism within the long-term memory module that performs predefined regular expression matching and rewriting operations on the input query text. The query rewriting layer only executes after the tool invocation admission layer has decided to initiate a retrieval and the memory retrieval tool has been invoked. It does not initiate new retrievals independently; it only optimizes queries that have already been triggered.
[0045] Friendly degradation message text: This refers to the pre-defined text generated by the system to replace technical error messages when a search fails or returns empty results. The friendly degradation message text uses natural language and includes phrases such as "No relevant historical memory found" or "Memory service is temporarily unavailable; please try again later." This text is naturally integrated into the large model agent's response generation, politely informing the user of the current search status, allowing the dialogue to continue uninterrupted.
[0046] Example 1 This embodiment provides a multi-user memory isolation method based on cross-thread message metadata transmission. The method is executed within a reactive programming framework, using a Msg object as the data carrier for carrying user messages and continuously transmitting them in a reactive stream. The Msg object has meta-attributes, and these metadata attributes are key-value mapping data structures used to store user identification information. For example... Figure 1 As shown, the method includes the following steps.
[0047] Step S1: Metadata writing and context binding Figure 2 The process of writing user identification information into the metadata field of the Msg object at the request entry point and constructing an immutable request context object bound to the memory retrieval tool instance is shown in the following steps: At the request entry point, authentication information is first extracted from the current HTTP request. Specifically, the JWT token is parsed from the request header, decoded, and verified to obtain the user ID, user type, and session ID. The user identification information includes at least the user ID. The user type is used to distinguish between internal employees and external visitors to support differentiated memory strategies for different user groups; the session ID is used for contextual association within a single session, facilitating subsequent retrieval and filtering by session dimension.
[0048] After obtaining user identification information, a Msg object is constructed using the Msg object builder pattern. During construction, the user ID, user type, and session ID are stored as key-value pairs in the metadata field. The key names of the metadata attributes are centrally managed by a unified constant class. This constant class is defined as a final constant class, containing three public static final string constants, corresponding to userId, userType, and sessionId, respectively, and includes a private no-argument constructor to prevent external instantiation. Using a unified constant class to manage key names avoids the spelling inconsistencies caused by hard-coding strings in different classes. If an incorrect spelling is used elsewhere, it cannot be matched, making it easy to detect during compile-time static checking.
[0049] After writing the metadata, the user-input dialogue content is written to the `content` property of the `Msg` object, and the role attribute is set to "user". Then, this `Msg` object is used as a data element to be passed in the reactive stream, and input into the reactive stream through the publisher interface of the reactive programming framework.
[0050] Once a Msg object is input into the reactive stream, it begins to flow through the chain of reactive operators. When the reactive stream passes through the map operator, the map operator receives the input Msg object, processes it, and outputs a new Msg object or a derived object. Since the Msg object is a regular Java object, its metadata fields, as part of the object, are migrated as a whole when passed between operators. When the execution thread of the map operator is different from the execution thread of the upstream operator, the metadata fields of the Msg object are passed to the new thread along with the object reference, without any additional context copying or moving operations. Similarly, when the flatMap operator flattens a single Msg object into multiple Msg objects, each output Msg object inherits or carries the same metadata fields. Thus, user identification information is bound to the Msg object throughout the entire chain of the reactive stream, and any operator that can obtain the Msg object can extract the user identification information from it.
[0051] Simultaneously, an immutable request context object is constructed at the request entry point. This class definition includes three final string member variables to store the user ID, user type, and session ID, respectively; a public constructor to initialize these three member variables upon object creation; and three public getter methods to return the values of the user ID, user type, and session ID, respectively. It does not contain any setter methods. All member variables of this object are final fields, initialized in the constructor, ensuring thread safety.
[0052] The request context object is bound to the memory retrieval tool instance created for that request. Specifically, each time a request arrives, the system creates a new memory retrieval tool instance, passing the request context object in via constructor injection. This memory retrieval tool instance is registered in the tool list of the large language model agent, ensuring that when the large model needs to invoke the memory retrieval tool, it invokes the instance bound to the current requesting user's context.
[0053] Through the aforementioned dual-write mechanism, namely the writing of Msg metadata and the binding of the request context object, a dual-guarantee path for the transmission of user context is formed: Msg metadata is explicitly transmitted between operators along with the reactive stream, ensuring that the context is not lost during the streaming processing stage; the request context object is bound to the tool instance, ensuring that the context is available during the tool invocation stage.
[0054] Step S2: Forced extraction and non-empty verification of user identifier Figure 3 This illustrates the complete process of extracting user identification information from the Msg object and performing triple non-empty checks in both the retrieval and write paths, specifically: When the long-term memory retrieval method is invoked, it receives a Msg object as an input parameter. The input parameter of the retrieval method is declared as queryMsg, representing a query message carrying user identification information. The return type is a reactive single-value stream used to encapsulate the retrieved memory text. User identification extraction begins at the method entry point to ensure that any unverified requests cannot enter the subsequent memory service access process.
[0055] The core logic of the extraction process is defined as a function named `extractUserId`. This function takes a `Msg` object as input and outputs either the extracted user ID string or an empty value. The specific execution flow of this function is as follows: First, it checks whether the input `Msg` object is empty. If it is empty, it directly returns an empty value. If it is not empty, it retrieves its metadata field and checks whether the field is empty. If the metadata field is not empty, it further checks whether the metadata field contains a user ID key defined by a constant class. If it contains the key, it retrieves the value corresponding to the key and performs a triple non-empty check: the first check is whether the value is empty, the second check is whether the value is an empty string, and the third check is whether the value is an empty string. If any of the above triple checks is not met, an empty value is returned. If the metadata main path extraction fails, i.e., the metadata field is empty, does not contain a user ID key, or the corresponding value is empty, it further reads the name field of the `Msg` object as a compatibility source. In some legacy message formats, the user identifier may be stored in the name field; if the name field is not empty and is not a blank string, it is returned as the user ID; if the name field is also blank or an empty string, an empty value is ultimately returned.
[0056] In the retrieval path, the core logic of the retrieval method is a function called `retrieve`. This function takes a `Msg` object as input and outputs the retrieval results. The function first calls the `extractUserId` function to extract the user ID from the input `Msg` object and performs a non-empty check on the extracted result. If the `extractUserId` function returns an empty value, it is determined that the user identifier is missing. The retrieval method logs a warning message containing the phrase "userIdmissing" and then directly returns an empty retrieval result. This empty retrieval result is an empty response containing no retrieval records, i.e., `Mono.empty()` or an empty response containing no records. Through this closed-loop rule of rejection for missing information, the possibility of performing a retrieval operation when the user identifier is unknown is completely eliminated, fundamentally eliminating the risk of dirty reads across users.
[0057] If the verification passes, the retrieval method calls a function named `rewriteRecallQueryIfNeeded` to rewrite the query text. This function takes the original query text as input and outputs the rewritten search terms. Then, the retrieval method calls the long-term memory service's retrieval interface with the rewritten search terms and the extracted user ID as parameters. The retrieval method also protects against retrieval calls using error handling operators, returning an empty result if the retrieval call fails. During the retrieval, the user ID is passed as the memory isolation primary key to the long-term memory service. The server filters the memory based on the user ID, returning only the historical memory data corresponding to that user ID. Memory data corresponding to different user IDs are not visible to each other on the server, thus achieving strict user-based isolation retrieval on the server side.
[0058] In the write path, when the long-term memory write method is called, it receives a list of Msg objects as input parameters. The input parameter of the write method is a list of messages, and the return type is a reactive null stream, used to indicate the completion status of the write operation. At the method entry point, it first checks if the message list is empty; if empty, it directly returns an empty completion signal. If not empty, it searches for the last user message in the Msg object list from the end to the beginning. Specifically, it uses a reverse loop to traverse from the last element of the list, obtaining the role attribute of each message and checking if it belongs to the user role. Once the first message with a user role is found, the traversal stops immediately, and this message is identified as the target to be extracted.
[0059] The core logic of the write path is a function named `record`, which takes a list of `Msg` objects as input and outputs the completion status of the write operation. This function first extracts the last user message from the input message list and calls the `extractUserId` function to extract the user ID from that message. If `extractUserId` returns null, the write method skips this write operation, records an alert log containing the message "userIdmissing", and then returns an empty completion signal (`Mono.empty()`), without initiating any write request to the long-term memory service. If the verification passes, the write method uses the user ID as the isolation key and calls the long-term memory service's write interface, passing the message list and the last user message as memory data. The write method also protects against write calls using error handling operators; when a write call fails, it returns an empty completion signal without throwing an exception.
[0060] User identification information is forcibly extracted from the metadata fields of the user message, and the extraction and verification logic is completely consistent with the retrieval path. If the extraction result is empty, the write method skips this write operation and records an alarm log in the logging system. The alarm log content includes the operation type as memory write skipped, session ID, user ID, and the skipped reason as missing user identification. Then, an empty completion signal is returned, and no write request is initiated to the long-term memory service.
[0061] If the verification passes, the write method uses the user ID as the isolation primary key and calls the write interface of the long-term memory service to perform the write operation. Specifically, a write request object is constructed, which contains two core fields: the list of messages to be written and the user ID. The request is sent to the long-term memory service, and the server associates the memory data with the user ID for storage, so that the data can only be retrieved by that user ID in subsequent searches.
[0062] The above extraction and verification process does not rely on thread-local storage. Its input source is the method parameters, namely the Msg object passed with the reactive stream. Therefore, it will not lose context or read the user context on the wrong thread due to thread switching of the reactive programming framework.
[0063] Step S3: Recall Intent Recognition Figure 4 The pipeline relationship between the tool invocation admission layer and the query rewriting layer is illustrated, specifically: During the retrieval process in step S2, recall intent recognition is performed on the incoming query text. The recall intent recognition adopts a two-layer serial mechanism, which is a pipeline relationship that is sequentially connected rather than a parallel triggering relationship.
[0064] The first layer is the tool invocation admission layer. Tool invocation constraints are imposed on the large model within the system prompts. These prompts include the following rule: when a user explicitly inquires about past conversations, personal information, or previously mentioned matters, the memory retrieval tool should be invoked to retrieve long-term memory; when a user engages in general question-and-answer, casual conversation, or seeks new knowledge, the memory retrieval tool should not be invoked. This rule is embedded in the system prompts as a natural language instruction and is followed by the large model during inference. The tool invocation admission layer determines whether to initiate long-term memory retrieval. Only if this layer's determination is successful will subsequent processes trigger memory retrieval; if the layer's determination fails, the system directly generates an answer based on the large model's own knowledge or general capabilities, without initiating any memory retrieval. A single turn of dialogue triggers at most one retrieval. This rule is implemented by explicitly stating in the system prompts that the retrieval tool is invoked only once per turn of dialogue, thus avoiding resource waste and result conflicts caused by repeated retrievals from the outset.
[0065] The second layer is the query rewriting layer, whose core logic is a function named `rewriteRecallQueryIfNeeded`. This function only performs a matching operation of a preset regular expression on the input query text within the long-term memory module after the first layer has decided to initiate a retrieval and the memory retrieval tool has been called. The regular expression is used to identify the following sentence patterns: recalling chat history about X corresponds to the regular expression recalling. about (.) chat history, recalling the previously mentioned X corresponds to the regular expression recalling the previously mentioned (.), finding the record of X corresponds to the regular expression find the record of (.), viewing the previously mentioned X corresponds to the regular expression view the previously mentioned (.). The capture group in the above regular expression is used to extract the topic word X.
[0066] The function's execution flow is as follows: the input is the original query text, and the output is the rewritten search terms. The function first matches the original query text against the four regular expressions mentioned above. If a match is successful, the topic term X is extracted from the capture group of the regular expression, and the search term is rewritten as the chat history format of topic term X, and returned as output. If none of the regular expressions are matched, the original query text is retained as the search term output. The query rewriting layer does not independently initiate new searches; it does not contain logic for calling the long-term memory service search interface, and only optimizes searches already triggered in the first layer. When the first layer is not triggered, the second layer logic is not executed at all; when the first layer is triggered and the second layer regular expression matches, the rewritten search terms are used to execute the current search; when the first layer is triggered but the second layer regular expression does not match, the original query text is used to execute the current search. Thus, the two-layer mechanism constitutes a pipeline that first determines whether to search, and then optimizes the search query. No duplicate search requests are generated within a single round of dialogue, avoiding the inconsistency between two search results that may result from parallel triggering.
[0067] The overall processing flow in a single-turn dialogue scenario is represented by a function called `handleUserTurn`. This function receives the user's text input as input and outputs the agent's response. The function first calls the large model's decision logic to determine whether to invoke the memory retrieval tool. If the large model decides not to invoke the retrieval tool, it directly generates an answer based on standard question-and-answer format and returns it. If the large model decides to invoke the retrieval tool, it calls the `retrieveFromMemory` function to perform the retrieval, integrates the retrieval results into the answer generation process, and then returns it.
[0068] Step S4: Determining and Downgrading Search Results Figure 5 The process of determining the search result and handling success, failure, or empty result is shown in the following steps: Obtain the retrieval execution results from step S3 and evaluate them. The retrieval execution results are transmitted in a reactive stream.
[0069] If the retrieval is successful and returns a non-empty result (success means the long-term memory service call returned a success status code and the response body parsed normally; non-empty means the returned list of memory entries is not empty), then the retrieval result is returned to the large model agent. When generating the answer, the large model agent incorporates the retrieval result as contextual information into the memory portion of the prompt words, and generates the final answer according to the instructions for answering the user's question based on the following historical memories.
[0070] If the retrieval fails or returns an empty result, a preset friendly degradation message is generated. Retrieval failure includes the following scenarios: long-term memory service call timeout, long-term memory service returning an unsuccessful status, long-term memory service returning a result parsing error, and long-term memory service returning an empty result. In any of these scenarios, the degradation processing module captures the exception or empty result using the error handling operators of the reactive programming framework and converts it into a preset friendly degradation message. The degradation message includes at least one of the following: "No relevant historical memory found" or "Memory service is temporarily unavailable, please try again later."
[0071] The downgrade processing module returns the downgrade prompt text to the large model agent. The return method uses the same interface and data format as the normal search results, facilitating unified processing by the large model agent. Upon receiving the downgrade prompt text, the large model agent seamlessly integrates it into the response generation process. For example, it might generate polite responses such as, "I haven't found your previous chat history regarding the return policy. Could you please describe the specific situation again?" or "The memory service is temporarily unavailable. Please try again later. I will continue to serve you." The dialogue continues uninterrupted, and the user will not perceive any technical anomalies.
[0072] It should be further explained that in the retrieval path of step S2, when the user identifier is missing, an empty retrieval result is returned. This empty retrieval result is captured by the degradation processing module in step S4, triggering the generation and return of a friendly degradation prompt text. In the write path of step S2, when the user identifier is missing, this write operation is skipped and an alarm log is recorded, without affecting the main dialogue flow.
[0073] It should also be noted that, in steps S1 to S4 above, the metadata field of the Msg object, after the user identification information is written in step S1, maintains its binding relationship with the Msg object throughout the entire process from steps S2 to S4. In the retrieval path of step S2, the Msg object received by the retrieval method is the Msg object input into the reactive stream in step S1 or its derived object after being processed by the reactive operator. The user identification information in its metadata field is always present and can be extracted as it flows through each reactive operator. In the writing path of step S2, the Msg objects included in the list of Msg objects received by the writing method also carry the user identification information written in step S1. Thus, the user identification information is continuously passed along with the Msg object throughout the entire reactive stream processing process, without relying on thread-local storage.
[0074] The following example of a complete actual call chain illustrates the execution flow of this method. Suppose user A enters into the enterprise intelligence platform, "Please help me recall the return policy I asked about before": First, the request ingress controller parses the JWT token, obtains user A's user ID, constructs a Msg object, writes the user ID into the metadata attribute, constructs a request context object and binds it to the memory retrieval tool instance, and inputs the Msg object into the reactive stream.
[0075] Second, the reactive stream passes the Msg object to the large model agent via the map operator. Since the map operator executes on an asynchronous thread different from the entry thread, the metadata attributes of the Msg object are automatically migrated to that thread along with the object.
[0076] Third, based on the tool call constraints in the system prompts, the large model agent determines that the current input has a clear intention to recall, calls the retrieval method of the memory retrieval tool, and passes in the query text to help me recall the return policy I asked about before.
[0077] Fourth, the memory retrieval tool obtains the user ID from the bound request context object, constructs a query Msg object, writes the user ID into its metadata attribute, and calls the retrieval method of the long-term memory module.
[0078] Fifth, the retrieval method of the long-term memory module extracts the user ID from the metadata attribute of the query Msg object, performs a non-empty check, and the check passes.
[0079] Sixth, the long-term memory module executes the query rewriting layer: regular expressions recall chat logs related to (.), extract the keyword "return policy", and rewrite the search terms into chat logs related to the return policy.
[0080] Seventh, the long-term memory module calls the long-term memory service's retrieval interface using the user ID and the search term "return policy" in the chat history. The long-term memory service filters by user ID and returns the user's historical return policy related memories.
[0081] Eighth, the search results are returned to the large model agent. The large model agent integrates the search results to generate an answer. According to your previous consultation records, you inquired about the policy on 30-day no-reason return. The specific rules are...
[0082] Ninth, after the dialogue ends, the write method receives the list of Msg messages from this round of dialogue, searches for the last user message from the back of the list, extracts the user ID, verifies it, and calls the write interface of the long-term memory service to write it into memory.
[0083] Example 2 This embodiment provides a multi-user memory isolation system based on cross-thread message metadata transmission, such as... Figure 6 As shown, the system includes a metadata writing module, a context passing module, a user identifier extraction module, a recall intent recognition module, a degradation processing module, and a writing control module. The specific functions of each module and the interaction relationships between them are described below. For technical details not described in detail in this embodiment, please refer to the relevant descriptions in Embodiment 1.
[0084] Metadata writing module: The metadata writing module is used to obtain user identification information associated with the current request. This user identification information includes at least a user ID. The module writes this user identification information into the metadata field of a Msg object and inputs the Msg object as a data element to be transmitted in the reactive stream. This allows the metadata field to explicitly flow across threads during the chained calls of reactive operators along with the Msg object. The metadata writing module is also used to construct an immutable request context object at the request entry point. This request context object holds the user identification information and is bound to a memory retrieval tool instance created for that request.
[0085] Specifically, the metadata writing module is implemented as a web filter or interceptor, triggered upon each incoming request. The module retrieves the current request from the server exchange object, parses the authorization field in the request header to extract the JWT token, and calls the JWT decoding library to decode and verify the token. If verification is successful, the user ID, user type, and session ID are extracted from the token's declaration. If verification fails or the token lacks necessary fields, the metadata writing module directly returns an unauthorized response without further processing.
[0086] After extracting user identification information, the metadata writing module performs metadata writing using the builder pattern of the Msg object. The metadata writing module calls the builder's metadata methods to store the user ID, user type, and session ID into metadata fields. The keys for metadata attributes are managed by a unified constant class, which contains three public static final string constants corresponding to userId, userType, and sessionId, and includes a private parameterless constructor. Using a unified constant class to manage key names avoids spelling inconsistencies caused by hard-coding strings across different classes. The Msg object, having completed metadata writing, is input into a reactive stream via the publisher method of the reactive programming framework. This stream is then passed to the route handler for further processing.
[0087] The metadata writing module is also used to construct an immutable request context object. This class definition includes three final-state string member variables, a public constructor to initialize all member variables, and three public getter methods to return the values of each member variable. This object is bound to a memory retrieval tool instance via constructor injection. This memory retrieval tool instance is added to the agent tool set for the current request through registration, ensuring that subsequent tool calls from the larger model invoke this instance. Because this instance is only valid within the scope of the current request, memory retrieval tool instances from different requests are isolated from each other, preventing crosstalk.
[0088] Context passing module: The context passing module is used to pass the Msg object as a data element in the reactive stream, participate in the chained flow of reactive operators, and enable the metadata fields of the Msg object to be passed across threads in the reactive stream along with the message. Reliable migration of user context is achieved between different threads through the passing of the data elements of the Msg object.
[0089] Specifically, the context passing module is built into the execution engine of the reactive programming framework, requiring no explicit coding by the user. When a Msg object is transformed using the map operator, the map operator receives a function as an argument. The input of this function is the Msg object passed from upstream, and the output is the transformed new object. During function execution, the original Msg object reference is passed to the function body, which can read any properties of the object, including metadata properties, and pass them downstream. When the execution of the map operator is scheduled by the scheduler to a thread different from the upstream thread, the Msg object reference itself, as a heap memory object, is unaffected by thread switching. Therefore, the user identification information in the metadata properties remains readable in the new thread.
[0090] Similarly, when the `flatMap` operator flattens a Msg object into multiple Msg objects, each output Msg object is derived from the original Msg object. Within the `flatMap` function body, developers can call the Msg object's builder method to copy all attributes from the original Msg object, including metadata attributes, and replace some attributes before outputting a new Msg object. The metadata attributes of this new Msg object are completely identical to those of the original Msg object, ensuring that user identification information persists in the branch paths of the stream.
[0091] When the flatMap operator flattens multiple inner publishers into a single publisher, the Msg object produced by the inner publisher also carries metadata attributes passed from upstream. Thus, the context-passing module ensures that user identification information is continuously passed along with the Msg object throughout the reactive stream, regardless of the combination of reactive operators.
[0092] User ID extraction module: The user ID extraction module is positioned at both the retrieval and write entry points, serving as a pre-protection layer for the long-term memory module. At the retrieval entry point, the user ID extraction module is implemented as an aspect-oriented programming (AOP) aspect or method pre-interceptor, triggered before the long-term memory retrieval method is executed. Its input is a Msg object, and its output is the extracted user ID string or an empty value.
[0093] The extraction logic implemented by the user identifier extraction module at the retrieval entry point is the process defined by the `extractUserId` function. This logic includes the following steps: First, check if the input parameter `Msg` object is empty; if so, return an empty value. Second, obtain the metadata attributes of the `Msg` object and check if they are empty. Third, if the metadata attributes are not empty, check if they contain a user ID key. Fourth, if the key is contained, obtain the corresponding value and perform triple non-empty checks, including checking if it is empty, if it is a blank string, and if it is an empty string. If any of the above conditions are true, return an empty value. Fifth, when the extraction of the main metadata path fails, read the name attribute of the `Msg` object and perform the same non-empty checks; if the name attribute is valid, return it as the user ID; otherwise, return an empty value.
[0094] When verification passes, the user ID extraction module returns the user ID to the caller, the retrieval method, which then passes the user ID to the long-term memory service. When verification fails, the user ID extraction module does not throw an exception but returns a null value, which the retrieval method uses to determine whether to return an empty result.
[0095] At the write entry point, the user identifier extraction module is implemented similarly to the retrieval entry point, but the input is a message list. It first checks if the message list is empty; if not, it performs a reverse traversal to locate the last message whose role is user. If no user message is found, it directly returns an empty value. If a user message is found, it performs the same extraction and validation logic as the retrieval entry point, i.e., calls the `extractUserId` function. If validation passes, the user ID is returned to the write method; if validation fails, an alarm log is triggered and an empty value is returned, causing the write method to skip this write operation.
[0096] Memory Intent Recognition Module: The recall intent recognition module is used to perform a pre-defined regular expression matching operation on the incoming query text during the retrieval process. It only performs query rewriting after the LLM has decided to initiate a retrieval through tool invocation, and does not initiate a retrieval request independently. Thus, it forms a two-layer recall intent recognition mechanism in series with the LLM tool invocation admission layer.
[0097] Specifically, the recall intent recognition module is located within the long-term memory module and executes after the memory retrieval tool is invoked but before an actual retrieval request is sent to the long-term memory service. The query text received by the recall intent recognition module is the original query text passed in by the memory retrieval tool. Internally, the recall intent recognition module implements the logic defined by the `rewriteRecallQueryIfNeeded` function. This logic maintains a configurable list of regular expressions, which by default include: recalling chat logs related to (.), recalling previously mentioned (.), retrieving (.) records, and viewing previously mentioned (.).
[0098] The recall intent recognition module matches the original query text against the aforementioned regular expressions sequentially. If a match is successful, it extracts the topic term X from the capture group of the regular expression, rewrites the search term as topic term X plus chat history, and returns the rewritten search term. If a match fails, it returns the original query text. The recall intent recognition module then passes the rewritten search term to the long-term memory service's retrieval interface.
[0099] Degradation processing module: The degradation processing module is used to obtain the retrieval execution results. When the retrieval execution is successful and a non-empty result is returned, the degradation processing module returns the retrieval result to the large model agent for generating a response. When the retrieval execution fails or an empty result is returned, the degradation processing module generates a preset friendly degradation prompt text and returns it to the large model agent. The large model agent then incorporates the degradation prompt text when generating a response, ensuring that the dialogue flow is not interrupted.
[0100] The retrieval failure includes at least one of the following: long-term memory service call timeout, long-term memory service returning an unsuccessful status, long-term memory service returning a result parsing error, or long-term memory service returning an empty result. The friendly degradation message is at least one of the following: no relevant historical memory was found or the memory service is temporarily unavailable; please try again later.
[0101] Specifically, the degradation processing module captures exceptions during the retrieval process using error handling operators from a reactive programming framework, including timeout exceptions, server-returned error status codes, and response body parsing exceptions. The module uniformly converts these exceptions into empty results or failure statuses, thereby triggering the generation of a friendly degradation message. Instead of throwing these technical exceptions outwards, the module returns the friendly degradation message as a normal retrieval result to the upper-layer caller.
[0102] Write to the control module: The write control module receives a list of Msg objects as input and iterates through the list from last to first to locate the last user message. It then forcibly extracts the user identifier information from the metadata field of that user message. If the extraction result is empty, the write control module skips the write operation and triggers an alarm log. If the verification passes, the write control module uses the user ID as the isolation primary key to call the long-term memory service's write interface, ensuring that the memory data is stored in separate warehouses by user ID, thus maintaining physical isolation of the memory data of different users at the persistence level.
[0103] Specifically, the write control module executes at the end of the reactive stream. After a round of dialogue ends, the system automatically calls the write control module to write a summary of the current dialogue into the long-term memory service. The Msg object list received by the write control module contains all messages from the current dialogue, including user messages and agent messages. The write control module traverses backward from the end of the list, searching for messages whose role is user. Once found, it stops traversing and extracts the user identification information from the metadata field of that message. The extraction logic calls the extractUserId function. If no user message is found after traversing the entire list, or if the user identification information in the metadata field of the found user message is missing (extractUserId returns a null value), the write control module determines that it cannot determine the user to whom the write belongs, skips this write operation, and records an alarm log.
[0104] In this embodiment, the data flow between modules is as follows: the Msg object output by the metadata writing module serves as the input to the context passing module; the context passing module passes the Msg object to the user identifier extraction module via a reactive operator; the user identifier extraction module extracts the user identifier information and then passes it to the recall intent recognition module and the writing control module; the recall intent recognition module passes the rewritten search terms and user identifier information to the degradation processing module; the degradation processing module returns the search results to the large model agent; and the writing control module writes the memory data to the long-term memory service according to the user ID at the end of the dialogue. All the above modules work together to achieve multi-user memory isolation functionality based on cross-thread message metadata passing within the reactive programming framework.
[0105] Example 3 This embodiment uses an actual deployment scenario of an enterprise-level intelligent agent platform connecting to the Mem0 long-term memory service as an example to illustrate the complete implementation process of the technical solution of this application under the Reactor reactive programming framework.
[0106] This enterprise-level intelligent agent platform serves the internal employees of a large enterprise. The platform uses Spring WebFlux as its reactive programming framework, Project Reactor to handle high-concurrency streaming requests, and Mem0 as its long-term memory service. The platform processes tens of thousands of concurrent dialogue requests from employees daily. Each employee has a unique user ID, and the history of multiple conversations with the same employee needs to be persistently stored by the long-term memory service and retrieved as needed in subsequent conversations.
[0107] In the actual deployment of the platform, the request entry point is the WebFlux-based controller layer. When the controller layer receives an HTTP request, it first parses the JWT token from the request header and extracts the user ID, user type, and session ID from the JWT token. The controller layer then constructs the first Msg object using the Msg object builder pattern: the user input is written to the content property of the Msg object, the role type is marked as user, and the user ID, user type, and session ID are written to the metadata property of the Msg object as key-value pairs. The keys of the metadata properties use standardized key names defined in the unified constant class; the key for user ID is userId, the key for user type is userType, and the key for session ID is sessionId. After completing the metadata writing, the controller layer inputs the Msg object into the reactive stream through a static method of the publisher.
[0108] Meanwhile, the controller layer constructs an immutable request context object. This object's member variables include user ID, user type, and session ID. All member variables are declared as final fields and initialized in the constructor. The controller layer creates a separate memory retrieval tool instance for the current request, injecting the request context object into this memory retrieval tool instance through the constructor. This allows the memory retrieval tool instance to hold user identification information throughout the request processing. This memory retrieval tool instance is registered in the agent's tool list for the larger model to invoke when needed.
[0109] During reactive stream processing, the Msg object is chained through the map and flatMap operators. The map operator preprocesses the content of the Msg object, such as filtering sensitive words and truncation; the flatMap operator calls the large model generation service. Because Reactor's scheduler uses a dynamic thread pool, the map and flatMap operators may execute on different asynchronous threads. However, since user identification information is stored in the metadata properties of the Msg object, and the Msg object is explicitly passed between operators as a data element, when the Msg object is passed from the map operator to the flatMap operator, its metadata properties migrate along with the entire Msg object to the thread executing the flatMap operator. User identification information is automatically passed between different threads without any additional context handling.
[0110] When the large model determines that the current user input has a clear intention to recall based on the tool call constraints in the system prompts, it invokes the retrieval method of the memory retrieval tool instance specific to the current request through a function call mechanism. During the retrieval, the memory retrieval tool instance retrieves the user ID, user type, and session ID from its held request context object, constructs a query Msg object, sets the user identification information in the metadata attributes of this query Msg object to be consistent with the request context object, and then calls the retrieval method of the long-term memory module, passing the query Msg object as an input parameter.
[0111] After receiving the query Msg object, the retrieval method of the long-term memory module calls the extractUserId function to extract the user ID from the metadata attribute of the Msg object and performs a non-empty check on the extracted result. The non-empty check includes three checks: first, whether the metadata attribute is empty; second, whether the metadata attribute contains the userId key; and third, whether the value corresponding to the userId key is empty or an empty string. If all three checks pass, the check passes; if any check fails, it is determined that the user identifier is missing, the retrieval method directly returns an empty result, and no access request is sent to the Mem0 service.
[0112] After successful validation, the retrieval method performs the second-level operation of recall intent recognition on the input query text, namely, calling the `rewriteRecallQueryIfNeeded` function. Internally, the retrieval method maintains a configurable list of regular expressions, which by default include: recalling chat logs about (.), recalling previously mentioned (.), finding (.) records, and viewing previously mentioned (.). The retrieval method matches the original query text against these regular expressions sequentially. If a match is successful, the topic term X is extracted from the capture group of the regular expression, and the search term is rewritten as X plus the chat log format; if a match fails, the original query text is retained as the search term.
[0113] The retrieval method calls the Mem0 service's retrieval interface using the rewritten search terms and user ID as parameters. The Mem0 service performs isolated retrieval of memory data based on the user ID, returning only the historical memory data corresponding to that user ID. Memory data corresponding to different user IDs are not visible to each other on the Mem0 service. The retrieval results returned by the Mem0 service are encapsulated as reactive objects and continue to be transmitted in the reactive stream.
[0114] The subsequent processing of search results is handled by the degradation processing module. If the Mem0 service call succeeds and returns a non-empty result, the degradation processing module returns the search results to the large model agent, which incorporates the search results as contextual information into the final answer generation process. If the Mem0 service call times out, returns a non-success status code, experiences a response body parsing error, or returns an empty result, the degradation processing module captures these situations, generates a preset friendly degradation prompt text, such as "No relevant historical memory was found or the memory service is temporarily unavailable, please try again later," and returns the degradation prompt text to the large model agent. When generating the answer, the large model agent converts the degradation prompt text into polite natural language expressions, such as "Sorry, I haven't found the relevant historical record yet. Could you please describe what you mentioned earlier?" The dialogue continues without interruption.
[0115] When a conversation ends normally, the system automatically calls the write method of the long-term memory module. The write method receives a list of Msg objects as input, containing all messages from the current conversation. It iterates backward from the end of the list, searching for messages with the user's role, stopping once found. After finding the last user message, the write method calls the extractUserId function to extract the user ID from the message's metadata attributes and performs a non-null check. If extractUserId returns null, the write method skips the write operation and logs an alert containing the session ID and timestamp for later investigation. If the check passes, the write method uses the user ID as the isolation primary key and calls the Mem0 service's write interface to associate the current conversation summary with the user ID, ensuring that the written memory data is partitioned by user ID at the persistence level.
[0116] Throughout the entire implementation process described above, whether in the retrieval or write path, the long-term memory module obtains user identification information from the metadata attributes of the Msg object or the request context object, and never reads from the thread-local storage. Because the context is bound to the Msg object and the request context object rather than the thread, any thread switching in the Reactor will not result in the loss or contamination of user identification information. Since deploying this solution, this enterprise-level intelligent agent platform has not experienced any cross-user memory misdetection incidents due to thread switching, even under the pressure of tens of thousands of concurrent requests per day.
[0117] Example 4 This embodiment takes the deployment scenario of a multi-tenant SaaS intelligent agent platform as an example to illustrate the implementation of the technical solution of this application in the tenant-level memory isolation extension scenario.
[0118] This SaaS intelligent agent platform serves multiple enterprise clients, each operating as an independent tenant. The platform needs to achieve memory isolation not only between different users but also between different tenants to prevent employees of tenant A from recalling memory data from tenant B. The platform employs a multi-tenant architecture, where each tenant has a unique tenant ID, and each employee within the same tenant has a unique user ID. User IDs are unique within a tenant but may be duplicated globally.
[0119] In this scenario, the platform's technical solution is extended from Embodiment 3. In addition to storing the user ID, user type, and session ID, the metadata attributes also store the tenant ID. The key corresponding to the tenant ID is `tenantId`, which is also managed by a unified constant class. At the request entry point, the metadata writing module parses the tenant ID and user ID from the request's authentication information and writes both into the metadata attributes of the `Msg` object. The immutable request context object also holds both the tenant ID and user ID.
[0120] In the design of the isolation primary key for the long-term memory service, the platform adopts a composite primary key strategy, concatenating the tenant ID and user ID into the form of tenantID_userID as the isolation primary key. In the retrieval path, the user identifier extraction module extracts the tenant ID and user ID from the metadata attributes of the Msg object, performing a non-null check on both. If either is missing, it is determined that the user identifier is missing, and the retrieval is rejected. After successful verification, the retrieval method combines the tenant ID and user ID into the isolation primary key and calls the retrieval interface of the long-term memory service. The long-term memory service uses this composite primary key as the isolation basis, returning only the historical memory data of the user under that tenant. In the write path, the write control module similarly extracts the tenant ID and user ID, combines them, and calls the write interface using the composite primary key, enabling the memory data to be partitioned and stored according to a two-level dimension: tenant and user.
[0121] Regarding recall intent recognition, this embodiment is consistent with Embodiment 3. The two-layer concatenation mechanism for recall intent recognition is independent of the tenant dimension, performing query rewriting only at the user dimension. The degradation processing of search results is also consistent with Embodiment 3.
[0122] The implementation and verification of this SaaS platform in a multi-tenant scenario demonstrates that the metadata protocol of this technical solution has good scalability. Adding a new tenant ID field does not require modifying the signature of the business method or altering the existing call chain; only the tenant ID writing logic needs to be added at the request entry point, and the tenant ID concatenation needs to be added to the isolated primary key combination logic of the long-term memory module. This fully demonstrates the low-intrusion and high-flexibility of this technical solution in terms of field expansion.
[0123] Example 5 This embodiment uses a real-world dialogue scenario of an intelligent customer service system as an example to illustrate the workflow of the two-layer sequential mechanism for recall intent recognition in the technical solution of this application during a specific user interaction process.
[0124] This intelligent customer service system is deployed on an e-commerce platform to provide consumers with pre-sales consultation and after-sales service. The system integrates a long-term memory service to store consumers' historical consultation records, order issues, and complaint records. In a typical dialogue scenario, consumers may make recall-based requests after multiple rounds of conversation, such as asking about the return policy they previously inquired about, recalling the coupon they mentioned last time, or remembering the order number they previously mentioned.
[0125] When a consumer inputs the aforementioned memory-related request, the request is first encapsulated as a Msg object. Information such as the user ID is written into the Msg object's metadata attributes. The Msg object is then input into a reactive stream and passed to the large model agent. Upon receiving the user input, the large model agent performs inference based on the tool invocation constraints specified in the system prompts. The system prompts explicitly define the tool invocation rules: when the user explicitly inquires about past conversations, personal information, or previously mentioned matters, the memory retrieval tool is invoked to retrieve long-term memory; when the user engages in ordinary question-and-answer sessions, the memory retrieval tool must not be invoked.
[0126] For example, if a user inputs "Please help me recall the return policy I asked about before," the large-scale agent recognizes that this input clearly points to past conversation content, indicating a recall intent. Therefore, it invokes the memory retrieval tool via a function call mechanism, passing "Please help me recall the return policy I asked about before" as the query text. Conversely, if a user inputs "How's the weather today?", the large-scale agent recognizes that this input does not involve any past conversation content and does not indicate a recall intent. Therefore, it does not invoke the memory retrieval tool but directly generates an answer based on its own knowledge. Thus, the first-layer tool call admission layer accurately determines whether a retrieval is initiated, preventing ordinary question-and-answer sessions from being mistakenly triggered.
[0127] After the memory retrieval tool is invoked, the long-term memory module receives the query text and performs a second-level query rewriting. The long-term memory module's internal regular expression engine matches the query text. For the query text "Help me recall the return policy I asked about before," a variant of the regular expression `recall.(.)`, after being configured and adapted, matches the text, capturing the keyword "return policy." The query rewriting layer rewrites the search terms into chat logs related to the return policy, replacing the original query text "Help me recall the return policy I asked about before." This rewritten search term is more focused than the original query text, removing non-informative words like "Help me recall," while retaining the core topic of "return policy," enabling more accurate matching of relevant historical memory fragments within the long-term memory service.
[0128] Regarding the query text "What is the order number?", as I mentioned before, the regular expression (.) hits, capturing the keyword "order number" and rewriting the search term as "chat history with order number". Regarding the query text "Can that coupon still be used?", if the query text is not determined by the first layer to be a memory intent, the system will not initiate a search; if it is determined to be a memory intent, the second layer of regular expression matching may not hit, in which case the original query text is retained as the search term.
[0129] After the query rewriting layer completes the rewriting, the long-term memory module uses the rewritten search terms and the user ID extracted from the Msg metadata as the isolation primary key to call the long-term memory service's retrieval interface. The long-term memory service performs the retrieval within the correct user space and returns historical memory fragments related to the user's return policy. If the retrieval is successful and returns a non-empty result, the retrieval result is returned to the large model agent. The large model agent integrates the retrieval result into the answer generation process and finally returns a personalized answer containing historical information to the consumer. If the retrieval fails or returns an empty result, the degradation processing module returns a friendly degradation prompt text, and the large model agent politely informs the consumer that no relevant historical records have been found.
[0130] This embodiment clearly demonstrates the connection between the first-layer tool call admission layer and the second-layer query rewriting layer: the first layer determines whether to initiate a search, and the second layer optimizes the search terms if a search has already been initiated. The two layers have separate responsibilities and are seamlessly connected, resulting in at most one search request per round of dialogue, eliminating the issues of duplicate searches or conflicting results.
[0131] Example 6 This embodiment takes an abnormal scenario of long-term memory service as an example to illustrate the workflow of the linkage and coordination mechanism between mandatory isolation protection and friendly degradation fault tolerance in the technical solution of this application under abnormal conditions.
[0132] In real-world production environments, long-term memory services may become temporarily unavailable due to network fluctuations, service overload, internal errors, or other reasons. During the actual operation of this intelligent agent platform, scenarios have occurred where the Mem0 service returned timeout errors due to the exhaustion of the downstream database connection pool, as well as requests timed out due to network jitter. In these abnormal scenarios, the degradation processing module in this application's technical solution ensures stable system operation and a good user experience.
[0133] Let's take the Mem0 service call timeout as an example. When the long-term memory module's retrieval method sends a retrieval request to the Mem0 service, a timeout limit is set. If no response is received from the Mem0 service within the timeout limit, the timeout operator of the reactive programming framework will trigger a timeout exception. The degradation handling module catches this timeout exception through the error handling operator and does not throw the timeout exception outwards. The degradation handling module generates a preset friendly degradation prompt text, "Memory service is temporarily unavailable, please try again later," and returns this degradation prompt text as a normal retrieval result to the large model agent.
[0134] Upon receiving the downgraded prompt text, the large model agent seamlessly integrates it into the response generation process. For example, the large model agent might generate the following response: "Sorry, I am temporarily unable to retrieve your historical memories, possibly due to system overload. You can try again later, or simply tell me what you need to know, and I can answer your questions based on the current information." This response politely informs the user that the retrieval is currently unavailable while maintaining the continuity of the conversation. The user will not perceive the details of the technical anomaly, and the dialogue continues uninterrupted.
[0135] Let's take the example of the Mem0 service returning an empty result. When a user uses the system for the first time and has never generated any historical memories, the Mem0 service's search interface normally returns an empty list. The degradation processing module determines that the search was successful but the result is empty, generates a friendly degradation message "No relevant historical memories found," and returns this text to the large model agent. Based on this, the large model agent generates the following response: "I haven't found any relevant historical records for you. If you need more information, please tell me what you'd like to know, and I'll help you." This response also maintains the coherence and politeness of the conversation.
[0136] In abnormal write path scenarios, when the write interface call of the Mem0 service times out or returns an error, the write control module catches the exception using error handling operators and does not throw it externally. The write control module records an alarm log containing the user ID, session ID, exception type, and timestamp, facilitating subsequent troubleshooting by operations and maintenance personnel. The write control module then returns an empty completion signal, and the main dialogue response flow remains unaffected; the user will not be aware of the technical details of the write failure.
[0137] In exceptional scenarios where a user identifier is missing, if the metadata attributes of the Msg object do not contain a user ID for some reason, the user identifier extraction module directly returns an empty search result in the retrieval path without initiating access to the Mem0 service. This empty search result then triggers the degradation processing module to generate a friendly degradation prompt text. In the write path, when a user identifier is missing, the write control module skips the write operation and records an alarm log, without initiating a write request to the Mem0 service or throwing any exceptions. The above processing ensures that even in boundary cases where a user identifier is missing, the system will not experience dirty reads or dirty writes without a primary key, while guaranteeing that the user's dialogue experience is not interrupted.
[0138] This embodiment fully demonstrates the synergistic effect of mandatory isolation protection and friendly degradation fault tolerance: mandatory isolation protection refuses to execute when the user ID is missing, avoiding technical anomalies caused by missing primary keys; the degradation processing module generates a friendly prompt instead of throwing an exception when the retrieval execution fails, allowing the dialogue to continue without interruption. The two work together to form an end-to-end fault-tolerant closed loop from retrieval to response.
[0139] Example 7 This embodiment takes a memory writing scenario as an example to illustrate the transmission process of Msg metadata in the writing path and the working mechanism of the writing control module in the technical solution of this application.
[0140] In the dialogue process of the intelligent agent platform, after each round of dialogue, the system needs to write a summary of that round of dialogue into a long-term memory service so that it can be recalled in subsequent dialogues. Taking a dialogue containing multiple rounds of question and answer as an example, in this dialogue, the user sends three messages, the intelligent agent replies with three messages, and the Msg object list contains a total of six messages, arranged in chronological order as follows: User message 1, Intelligent agent message 1, User message 2, Intelligent agent message 2, User message 3, and Intelligent agent message 3.
[0141] When the dialogue ends normally, the system automatically calls the write method of the long-term memory module, passing the list of Msg objects as input parameters. After receiving the list, the write control module traverses backward from the end of the list. The traversal begins with agent message three, checks its role attribute, and finds that the role is agent rather than user, so it continues traversing backward. When it reaches user message three, it checks its role attribute, finds that the role is user, stops traversing, and locates user message three as the last user message.
[0142] The write control module calls the `extractUserId` function to extract user identification information from the metadata attributes of user message three. The metadata attributes of user message three, containing the user ID, user type, and session ID, are written at the request entry point and remain bound to the `Msg` object throughout the response stream transmission. The write control module performs a non-empty check on the return result of `extractUserId`. If the check passes, the write control module uses the user ID as the isolation primary key, stores the summary content of this conversation as memory data, and calls the write interface of the long-term memory service. The long-term memory service associates this memory data with the user ID, ensuring that the memory data can only be retrieved using that user ID in subsequent searches.
[0143] If `extractUserId` returns an empty value, the write control module determines that the user identifier is missing, skips the write operation, and does not initiate any write request to the long-term memory service. The write control module records an alarm log through the logging system. The alarm log includes: operation type "memory write skipped", session ID, a brief description of the message list, and the reason for skipping: missing user identifier. After this alarm log is recorded, the write control module returns an empty completion signal. The main dialogue flow is unaffected, and the user will not be aware that the write operation has been skipped.
[0144] In batch write scenarios, if the Msg object list contains multiple user messages, the write control module only extracts the user identification information of the last user message and does not check the user identification information of other user messages in the list. This is because the user identification information in the metadata attributes of all Msg objects remains consistent within the same session, as it is written uniformly at the request entry point and does not change during the reactive stream transmission. Therefore, extracting only the user identification information of the last user message is sufficient to represent the user affiliation for the entire session, eliminating the need to traverse all messages for repeated verification, thereby improving the processing efficiency of the write path.
[0145] In the confirmation scenario after write completion, if the long-term memory service's write interface returns a success status, the write control module records a debug-level log entry containing the user ID and write time of the successful write. If the long-term memory service's write interface returns a failure status or throws an exception, the write control module catches the exception, records an error-level log entry containing the user ID, exception type, and exception stack trace, and then returns an empty completion signal without propagating the exception upwards.
[0146] This embodiment fully demonstrates the transmission path of Msg metadata in the write path, the extraction and verification process of user identifiers, and the handling mechanism for write failures, verifying that the technical solution of this application also achieves reliable transmission and forced isolation of user context in the write path.
[0147] It should be noted that the above embodiments are merely preferred embodiments of the present invention and are not intended to limit the scope of protection of the present invention. Those skilled in the art can make equivalent substitutions or obvious modifications to the technical features described in the above embodiments without departing from the basic principles of the present invention, and these equivalent substitutions or modifications should also fall within the scope of protection of the present invention.
Claims
1. A multi-user memory isolation method based on cross-thread message metadata transmission, characterized in that, Executed within a reactive programming framework, using message objects as the data carrier continuously transmitted in the reactive stream, the message objects possess metadata attributes with a key-value mapping structure, the method includes: At the request entry point, user identification information is written into the metadata field of the message object, so that the metadata field is explicitly transferred across threads as the message object is chained through reactive operators; at the same time, an immutable request context object is constructed to hold the user identification information and is bound to the memory retrieval tool instance of the current request. During retrieval, the user identifier is extracted from the message object's metadata field and a non-empty check is performed. If the metadata is empty, does not contain a user ID key, or the corresponding value is empty, the retrieval is rejected and an empty result is returned. After the check passes, the long-term memory service is called with the user ID as the isolation primary key, so that the server only returns the memory data corresponding to that user ID. During writing, the last user message is searched from the message object list from the end to the beginning, the user identifier is extracted and a non-empty check is performed. After the check passes, the write interface is called with the user ID as the isolation primary key, so that the memory data is associated with the user ID for storage. The recall intent recognition adopts a two-layer chain mechanism: the first layer is determined by the large model based on the tool call constraints in the system prompt words to determine whether to call the memory retrieval tool; the second layer only performs regular expression matching on the query text after the retrieval has been triggered, and extracts the subject words to rewrite the search terms when a match is found. Retrieve search results. If successful and not empty, return a large model to generate an answer. If unsuccessful or empty, generate a friendly downgrade prompt text and return a large model, allowing the dialogue to continue without interruption.
2. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, The forced extraction of user identification information and the execution of non-empty validation specifically include: checking whether the input parameter message object is empty; obtaining the metadata field and checking whether it is empty; checking whether the metadata field contains a user ID key; checking whether the value corresponding to the user ID key is empty, a blank string, or an empty string; if any condition is true, return an empty value; if the extraction of the main path of the metadata fails, read the message object name field as a compatibility source, and return it as the user ID if the name field is valid, otherwise return an empty value.
3. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, Regular expressions are used to identify phrases such as "recalling chat history about X", "thinking back to X mentioned before", "finding X's records", and "viewing X mentioned before". When a match is found, the keyword X is extracted from the query text, and the search term is rewritten as "X's chat history" with the addition of time-limited words to replace the original query text.
4. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, In the first layer, a single round of dialogue triggers at most one search; in the second layer, searches are not initiated independently, but only the already triggered searches are optimized; the first and second layers are in a sequential pipeline relationship, and no duplicate search requests are generated within a single round of dialogue.
5. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, All member variables of an immutable request context object are final state fields. Once constructed, the user identification information it holds remains unchanged throughout the entire request processing and does not change with thread switching.
6. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, The key names of metadata attributes are centrally managed by a unified constant class. The constant class contains public static final string constants for user ID key, user type key, and session ID key, and also contains a private parameterless constructor.
7. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, The message object is a Java object that contains at least role attributes, content attributes, name attributes, and metadata attributes.
8. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, The following are some of the situations in which the retrieval execution fails: the long-term memory service call times out, returns an unsuccessful status, returns an abnormal result parsing, or returns an empty result; the friendly degradation prompt text is at least one of "No relevant historical memory found" or "Memory service is temporarily unavailable, please try again later".
9. The multi-user memory isolation method based on cross-thread message metadata transmission according to claim 1, characterized in that, The user identification information also includes the tenant ID. The tenant ID and user ID are extracted in the retrieval and write paths and combined into an isolation primary key in the form of "tenant ID_user ID" to achieve two-level memory isolation at both the tenant and user levels.
10. A multi-user memory isolation system based on cross-thread message metadata transmission, characterized in that, include: The metadata writing module is used to write user identification information into the metadata field of the message object, so that the metadata field can be explicitly transferred across threads during the chained calls of the reactive operator along with the message object, and is used to construct an immutable request context object and bind it to the memory retrieval tool instance of the current request. The context passing module is used to pass message objects as data elements in the reactive stream to participate in the chained flow of reactive operators, so that metadata fields can be passed across threads with the message, and the user context can be reliably migrated. The user identifier extraction module is set at the retrieval entry and the write entry. It is used to forcibly extract user identifier information from the metadata field of the message object and perform non-empty verification. After the verification is successful, the user ID is used as the isolation primary key to call the retrieval interface or write interface of the long memory service. The recall intent recognition module is used to perform a pre-defined regular expression matching operation on the query text during the retrieval process. When a match is found, the subject words are extracted and the search terms are rewritten. The query rewriting is only performed after the language model tool has decided to initiate a retrieval. Together with the tool call admission layer, it forms a two-layer recall intent recognition mechanism. The degradation processing module is used to return the large model when the retrieval is successful and returns a non-empty result, and to generate a friendly degradation prompt text and return the large model when the retrieval fails or returns an empty result. The write control module is used to locate the last user message from the message object list from the end to the beginning and extract the user identifier. After verification, the write interface is called with the user ID as the isolation primary key, so that the memory data is stored in separate warehouses according to the user ID.
Citation Information
Patent Citations
Message repeater for identifying message sensitivity
CN114282262A