A Homeostatic Memory Mechanism for Autonomous Agents

AI memory systems face the “curse of dimensionality.” When viewing entries from various perspectives, potential relationships exist between all of them; however, increasing the number of dimensions or edge types causes these entries to be pulled further apart. Even if one labels these edge types or dimensions, a further challenge arises: determining which of them are actually significant. This is difficult for an autonomous agent reacting to a current scene to ascertain, and the issue often cannot be easily formulated as a query.

To test the memory system, I created a custom dataset based on an RPG session, allowing for the exploration of the bot’s personality and specific actions within a hierarchical structure (e.g., the bot has a daily routine, a profession, etc.). Within the memory system, episodes are stored in a FAISS vector database, having been embedded using the SONAR encoder. At the start of each run, the data undergoes consolidation and generalization. Subsequently, ICA (Independent Component Analysis) is applied across the entire database to reduce the data to five components, aiming to identify normally distributed, independent components. In tests where I reduced the data to three dimensions, the resulting components could be interpreted as representing fields of activity, hierarchy, and social versus solitary states—concepts that plausibly hold relevance for an agent. We aim for variance across these five components; for instance, the bot should engage in a mix of activities—such as farming, mining, or cooking—rather than focusing exclusively on a single task.

The most recently recorded episodes constitute the short-term memory, which also undergoes the initial generalization and ICA processes. The difference in each component is then calculated between the episodes within this short-term memory. If the difference along a specific component was too low, it indicates that the current scene was one-sided in a particular respect; the agent should therefore be encouraged to make decisions with greater variety. Next, a compression is applied across the entire vector database, scaling down all dimensions based on their respective differences. Consequently, the next retrieval is more likely to yield episodes spanning the full spectrum of the compressed component, as the distances along that axis have been reduced. Testing shows that Manhattan distance is well-suited for this purpose, as it is more strongly influenced by these reduced distances. For instance, if a bot has spent the day mining coal, it might consider how to unwind in the evening; since it was alone in the mine, the “social” component is compressed, potentially leading to the retrieval of an episode where it meets friends at a tavern to relax.

This is what the database looks like without compression and using cosine similarity search. The query is marked with a cross, retrieved entries are orange, and episodes in short-term memory are represented by diamonds.

Here, the vector database is shown with compressed dimensions defined by the spacing of episodes in short-term memory. In this images, both height and width have been compressed. The second image shows the results of testing Manhattan distance, which performs best because it is most sensitive to the reduced distances resulting from dimension compression. The retrieved episodes fall precisely within the appropriate range.

The second diagram below illustrates how the five components changed over time. A low relaxation value indicates significant compression. One could interpret the story this way: the bot started a task but then procrastinated; eventually, the pressure to complete it became so great that it finally finished the original task. There is a German saying that translates roughly to: “In the evening, the lazy person becomes diligent.”

Initially, the bot was doing fieldwork—indicated by the yellow-marked IC3 section. One could interpret the subsequent drop in IC3 levels as the bot becoming bored with the fieldwork, prompting it to switch to smelting instead. The log indicates that the agent did not explicitly initialize this change; rather, a compressed dimension caused the retrieval of an entry that altered its behavior: “The bot has shifted from a focus on harvesting wheat, which has resulted in repeated failures, to considering alternative resource management tasks such as smelting cobblestone.” The purple-marked IC4 suggests the bot was concerned about failing to produce enough food or complete its planned tasks before nightfall; this anxiety intensified as it switched to smelting. Finally, realizing that night was imminent, the bot decided to harvest the wheat after all, causing the concern about insufficient food supplies to subside.

The generalization process works similarly to the prompting used in PREMem Memory, or it can be compared to the “reflections” found in Stanford Agents. An LLM views the most recently retrieved entries and can then generate a generalization or an accumulation. However, consolidating entries or removing contradictory ones is ineffective because the process relies on the cosine similarity of embeddings generated by the SONAR encoder.

I did a quick Colab check:


The part I find most interesting here is not ICA by itself, but the fact that the recent trajectory changes the retrieval geometry.

If I understood the mechanism correctly, low recent variation along a component reduces the distance penalty along that component. Memories are then allowed to differ more strongly in that direction while still being constrained by the remaining components. I would think of that as a small state-conditioned adaptive metric over episodic memory.

The small probe above was useful because the basic geometric effect was quite clear: relaxing an ICA coordinate really can change the retrieved neighborhood and increase the freedom along that coordinate. What did not follow automatically was semantic diversity, a different action, or longer-term restoration toward some reference state.

So I think there is a useful evidence chain here that can be tested one piece at a time without changing the architecture:

adaptive geometry changes
        ↓
the state-aligned adaptation matters
        ↓
different memories are retrieved
        ↓
those memories change the next action
        ↓
the closed-loop trajectory changes
        ↓
the intended behavioral imbalance is reduced

For me, the highest-information/lowest-cost next checks would be:

  1. separate query/insight construction from relaxation;
  2. compare the real adaptive relaxation vector against controls that preserve the same amount of deformation but break its relation to the current state;
  3. replay the same agent state with different retrieved-memory packets and compare the next action;
  4. only after that, run a short closed-loop trace.

That would preserve the basic idea while making it much clearer which part is producing the behavior.

There are also a few tiny implementation details that are worth making explicit for reproducibility: whether the database, recent memories, and query share one fitted ICA basis; whether the same component-wise transform is applied consistently to query and stored memories; and what scaling/normalization convention is used before the component differences are compared.

A compact way I would separate the possible goals is:

Goal: stop repetitive / one-sided behavior
    -> recent low variation is already a natural signal

Goal: return toward a preferred or historical state
    -> also measure displacement from some reference

Goal: find alternatives without losing semantic relevance
    -> semantic candidate retrieval, then adaptive reranking

Goal: establish behavioral homeostasis
    -> follow retrieval -> action -> next state over multiple steps

In other words, I would not treat “low variation” and “homeostatic error” as necessarily the same quantity. Low variation can be a perfectly useful anti-repetition signal even if the system has no explicit setpoint.

What I actually tested in the Colab probe

This is not a reproduction of your implementation or corpus. It is only an independent mechanism probe based on the public description.

I used:

  • Meta’s public SONAR text encoder;
  • a deterministic synthetic Minecraft-like episodic corpus;
  • 186 memory entries;
  • 1024-dimensional SONAR embeddings;
  • FastICA reduced to five components;
  • exact weighted-L1 retrieval;
  • six simple activity scenarios.

I deliberately kept the corpus controlled because the question was only: if a recent-state signal relaxes an ICA coordinate, what effects can be separated mechanically?

The probe does not reproduce:

  • your actual episodic corpus;
  • your consolidation/generalization prompts;
  • the exact recent-component-difference statistic;
  • the exact difference-to-relaxation mapping;
  • the exact query-insight average construction;
  • the downstream autonomous-agent loop.

So I would read the numbers below only as mechanism observations.

Main result

Across the six scenarios, relaxing the selected low-spread component changed about 35% of the top-20 membership on average.

The mean standard deviation along the relaxed component increased from approximately:

normal retrieval:   0.411
relaxed retrieval:  0.675

So the interpretation

“make this dimension cheaper and permit more variation along it”

was directly visible.

The effect was also strongly context-dependent. In some scenarios the top-k set changed substantially; in the social scenario it did not change at all, even when the relaxation weight was pushed very low.

That seems useful in itself: changing a metric weight does not guarantee a retrieval change if that coordinate is not rank-decisive in the local neighborhood.

What did not automatically follow

Increasing spread in the ICA coordinate did not consistently increase simple activity-label diversity.

Likewise, selecting the lowest-recent-spread component did not reliably move retrieval toward a longer-term/reference distribution.

That does not contradict the retrieval mechanism. It only separates these statements:

more freedom along an ICA coordinate
        !=
more semantic/activity diversity
        !=
movement toward a reference state
        !=
different agent behavior

The first one was clearly visible in this probe. The later ones need their own measurements.

Controls that would isolate what is actually doing the work

1. Query/insight construction × relaxation

The query-insight average + relaxation label in your figure caught my attention because query construction itself can be a large intervention.

In the probe, simply changing the query center with a controlled query+insight average changed the top-20 neighborhood by a similar order of magnitude to the relaxation.

Mean top-k turnover was roughly:

raw query -> query/insight center
relaxation OFF:  0.317
relaxation ON:   0.392

So I would probably make this the first ablation:

                         relaxation OFF    relaxation ON

raw/pre-insight query           A                 C

query/insight center            B                 D

Then:

A vs B -> query-construction effect
A vs C -> relaxation effect on raw query
B vs D -> relaxation effect on enriched query
full 2×2 -> interaction

This is attractive because it requires almost no architectural change.

2. Preserve the relaxation vector, but break its state alignment

Since the description says the dimensions are scaled according to their respective recent differences, I think a full-vector control is cleaner than changing only one arbitrary component.

For one exact state, compare:

A. identity
   [1, 1, 1, 1, 1]

B. actual adaptive vector
   [w0, w1, w2, w3, w4]

C. component-permuted vector
   same five weights, assigned to different components

D. time-shuffled vector
   adaptive vector from another recent state

E. optional fixed/mean vector
   state-independent average relaxation

The especially useful control is C.

It preserves the same set of relaxation strengths and almost the same overall amount of metric deformation, but destroys the mapping:

current recent state
        ↓
which component gets which weight

So if B consistently behaves differently from C, that is much stronger evidence that the state-to-component alignment matters rather than merely using an anisotropic metric.

My small synthetic probe did not show an automatic large advantage for the selected low-spread axis over generic fixed/shuffled axis changes, which is exactly why I think this control would be informative on the real corpus.

3. Same-state retrieval-packet replay

This may be the cheapest way to connect retrieval to behavior.

Take one recorded state and freeze everything:

same agent state
same recent history
same prompt
same model
same decoding settings

Then replay it with only the retrieved memories changed:

state_t
   ├── baseline retrieval packet -> next action A
   └── adaptive retrieval packet -> next action B

If possible, deterministic decoding makes the comparison especially clean. If generation is stochastic, a small number of repeated samples is enough to estimate how strongly the action distribution moves.

This directly tests:

retrieved memories
        ↓
next action

without waiting for a full long-horizon run to diverge.

There is some related evidence that this kind of mediation is worth measuring explicitly: the ACL 2026 paper How Memory Management Impacts LLM Agents reports an “experience-following” effect where similarity to retrieved experiences is associated with similar downstream agent outputs. That is not evidence about this particular system, but it is a useful reason to log the retrieval-to-action step separately.

4. Retrieval and utilization as separate stages

Likewise, I would avoid collapsing:

good memory was retrieved

and:

the agent actually used that memory

into one metric.

A minimal trace could be:

retrieved IDs/text
        ↓
memory packet supplied to the model
        ↓
next action
        ↓
resulting episode/state

If there is an observable intermediate indication of which memory influenced the decision, even better, but it is not strictly necessary.

The recent Memory Probe work makes a similar methodological distinction between retrieval and utilization failures in agent memory systems. Again, the task is different, but the separation is useful here.

5. A semantic-relevance guardrail

Another control I would try before changing the global retrieval mechanism is:

SONAR semantic search
        ↓ top-M candidates
adaptive ICA/L1 rerank
        ↓ top-k

This asks a narrower question:

Does the adaptive geometry still produce useful alternative memories when it is only allowed to operate inside an originally relevant SONAR neighborhood?

That is different from saying this should be the production architecture. It is just a useful control for distinguishing:

useful state-conditioned reranking

from:

leaving the original semantic neighborhood

For reference, Faiss supports L1 directly, and its standard cosine-search recipe is to L2-normalize both database and query vectors and search with inner product: Faiss metric documentation.

What is being regulated: repetition, displacement, or both?

I think this distinction may help interpret the “homeostatic” part without forcing the design into a different framework.

A low-spread recent component answers something like:

Has the recent trajectory been unusually one-sided along this factor?

A reference-displacement measure answers a different question:

Is the recent trajectory far from some longer-term/contextual state?

These can coincide, but they do not have to.

In the probe, the lowest-recent-spread component and the component with the largest recent-vs-long-term distribution shift were the same in 4 of 6 scenarios, but different in the other two.

A simple conceptual table is:

Recent variation Reference displacement Possible interpretation
low low repetitive, but near the reference
low high repetitive and displaced
high low varied around the reference
high high varied, but globally shifted

So I would treat them as optional separate signals rather than replacing one with the other.

Symmetric relaxation versus directional restoration

There is also a geometric distinction that seems important.

If the same positive component weight is used consistently for the query and memories, weighted Manhattan retrieval has the form:

distance = sum_j weight_j * abs(query_j - memory_j)

Reducing one weight makes differences in either direction along that coordinate cheaper.

So the relaxation itself says:

“allow a wider range along this component”

rather than:

“move specifically back toward this side of the component.”

That is actually a good fit if the goal is anti-repetition / exploratory balancing.

If the intended meaning is instead return toward a preferred/reference state, then a directional signal could be measured separately. It does not necessarily need to replace the current relaxation.

That is also why I would be careful about interpreting a sequence such as:

fieldwork -> smelting -> fieldwork

too early. It could represent a useful closed-loop correction, but similar switching can also arise from exploration or retrieval-rank threshold crossings.

The classical homeostatic-RL literature gives one possible vocabulary for the stronger “restoration” interpretation: it explicitly defines deviation from a reference/setpoint and rewards reduction of that deviation. See Keramati & Gutkin, Homeostatic Reinforcement Learning. I would only use that as a conceptual comparison here; an autonomous memory system does not need a biological-style setpoint in order for the current anti-repetition mechanism to be useful.

A few implementation sanity checks that change the geometric interpretation

These are all small documentation/reproducibility details rather than proposed redesigns.

1. Use one ICA coordinate system for the things being compared

If recent-memory component differences are compared directly with database/query coordinates, it helps if they all use the same fitted ICA transform:

reference/full memory bank
        ↓ fit ICA once
     fitted ICA
      /   |   \
     /    |    \
 database STM  query
       transform()

If ICA is independently refitted on different subsets, component numbers are not inherently aligned across fits.

The scikit-learn FastICA API makes this distinction explicit through fit() and transform().

If the implementation already uses one fitted basis for all of these, then this point is already resolved.

2. Make the component-scale convention explicit

If raw recent spread is compared across ICA components, the scale of those components matters.

Current scikit-learn FastICA defaults to:

whiten="unit-variance"

which rescales recovered sources to unit variance and makes cross-component spread comparisons easier to interpret.

Other whitening conventions or ICA implementations need not have the same component scaling.

A version-independent way of making the feedback quantity dimensionless would be something like:

recent_spread_j / reference_spread_j

or a robust analogue such as a recent/reference MAD ratio.

That would preserve the same idea while reducing dependence on the numerical scale convention of the ICA implementation.

Again, this only matters if raw component spreads are directly compared.

3. Make query/database scaling explicit

If the adaptive transform is applied to both query and stored memories, it has the simple weighted-L1 interpretation above.

If the stored memories are transformed but the query is not, the resulting geometry is different.

So one line documenting:

query and stored memories are transformed by the same adaptive weights

or the opposite would make reproduction much easier.

4. Record whether SONAR normalization happens before ICA

The public SONAR encoder provides the high-dimensional representation, but downstream pipelines can choose different normalization conventions.

So for reproducibility I would record something as simple as:

SONAR raw -> FastICA

versus:

SONAR -> L2 normalize -> FastICA

and independently document normalization for any cosine baseline.

These details are small, but they determine exactly which geometry is being compared.

ICA as selective freedom

I think ICA could have a particularly interesting role here beyond dimensionality reduction.

If the five components are sufficiently factor-separated on the actual memory bank, relaxing one component could allow retrieval to explore that factor while the remaining components continue to preserve scene context.

In other words:

relax one factor
        ↓
more freedom on that factor

keep the other factors expensive
        ↓
retain contextual constraints

A direct diagnostic is possible without interpreting the components semantically.

For component j:

1. retrieve while ignoring/down-weighting j
2. condition strongly on all other components
3. inspect the distribution of j among those neighbors
4. compare it with the global/reference distribution of j

If the conditional distribution of j opens up substantially while the other coordinates remain constrained, that is direct evidence for this “selective freedom” interpretation.

The independent probe looked reasonably encouraging on this diagnostic in 5 of 6 scenarios, although one scenario was noticeably worse. So I would measure it on the real memory bank rather than assume ICA guarantees the effect.

One related recent direction is SAMem: State-Aware Memory, which explicitly conditions memory selection on the agent’s current state. Its mechanism is different, but it provides a useful neighboring vocabulary: the interesting part here may be less “ICA versus another reducer” and more how the current state modifies which memories become locally relevant.

Continuous relaxation does not imply continuous retrieval behavior

One more small observation from the probe: sweeping the relaxation weight continuously produced mostly piecewise-constant top-k sets.

The ranking can look like:

weight decreases
      ↓
same neighbors
      ↓
same neighbors
      ↓
rank boundary crossed
      ↓
several neighbors swap
      ↓
same neighbors again

That is normal nearest-neighbor behavior, but it means a smooth-looking relaxation curve can produce discrete behavioral events.

If this becomes relevant, useful diagnostics are cheap:

first neighbor-swap threshold
rank margin
top-k turnover
activity dwell time

I would only consider smoothing/hysteresis if an actual closed-loop trace shows undesirable rapid switching. There is no need to complicate the controller in advance.

From retrieval geometry to a closed-loop homeostatic result

I would separate three increasingly strong tests.

Stage 1 — open-loop mechanism test

Freeze the recent state:

fixed recent window
        ↓
adaptive weights
        ↓
retrieval

This isolates the geometry. The Colab probe is mostly in this category.

Stage 2 — one-step causal replay

Freeze the agent state but replace the retrieval packet:

same state
   ├── normal memories   -> action A
   └── adaptive memories -> action B

This tests whether changed retrieval can mediate changed action.

Stage 3 — closed loop

Then allow the system to evolve:

state_t
   ↓
recent-memory statistics
   ↓
relaxation_t
   ↓
retrieval_t
   ↓
action_t
   ↓
state_t+1
   ↓
new recent-memory statistics
   ↓
...

At that point I would track more than just component relaxation.

A compact log could contain:

Quantity What it separates
relaxation vector controller output
retrieved IDs/text retrieval effect
top-k turnover neighborhood change
next action behavioral mediation
activity dwell time repetition/persistence
switching rate possible oscillation
reference displacement, if relevant directional restoration
lagged state/weight relation closed-loop dynamics

Then a sequence such as fieldwork → smelting → fieldwork becomes much easier to interpret.

If the intended result is anti-repetition, lower excessive dwell time or broader behavior may be enough.

If the intended result is restoration toward a state distribution, then the stronger test is whether an explicit displacement/error quantity decreases over time.

If there is rapid ping-pong behavior, only then would I look at window size, gain, a deadband, or hysteresis.

This staged evaluation also avoids requiring one long agent run to answer every question at once.

The contradiction/consolidation problem looks like a separate lane

I would keep the contradictory-memory issue separate from the adaptive-retrieval controller, because it seems to require a different notion of similarity.

Semantic similarity is good at finding things that say approximately the same thing. A contradiction can require finding things that refer to the same entity/state slot/time but assign incompatible values.

For example:

10:00  the furnace is empty
10:15  the furnace contains iron

is probably just a state transition.

But:

10:15  the furnace is empty
10:15  the furnace contains iron

may be a genuine conflict if both refer to the same furnace and state.

So I would decompose that pipeline as:

candidate discovery
        ↓
relation/state-role classification
        ↓
duplicate
compatible
contradiction
supersedes
historical
transition
context-specific
        ↓
keep / merge / update / remove

The important part is that the candidate-retrieval objective does not have to be the same as the normal memory-retrieval objective.

A practical candidate key could combine some subset of:

semantic neighborhood
entity
state/property slot
valid time
location/context

and only then ask a classifier/LLM whether the relation is contradiction, supersession, coexistence, etc.

This also avoids deleting useful history just because a newer state exists.

A recent paper, A-TMA, frames a related long-term-memory failure as “ghost memory”: current, historical, and transition facts coexist but are not distinguished properly across maintenance, retrieval, and answer-time resolution. It is not the same implementation, but that three-stage separation seems relevant here.

If you later want standardized stress tests rather than custom RPG cases, MemoryAgentBench includes an explicit conflict-resolution track / FactConsolidation data, while LongMemEval includes knowledge updates and temporal reasoning.

I would treat those as optional validation tools, not as requirements for the current experiment.

So overall, the small experiment made me more interested in the retrieval mechanism, not less.

The cleanest interpretation I can support from my side is:

the adaptive relaxation can genuinely open a latent retrieval coordinate and materially alter the neighborhood.

The stronger interpretation:

the chosen recent-state signal specifically produces useful behavioral homeostasis

just contains several additional causal steps that can be separated fairly cheaply.

If I were choosing the smallest path from here, I would use:

query × relaxation 2×2
        ↓
adaptive vs component-permuted weights
        ↓
same-state retrieval-packet replay
        ↓
short closed-loop trace

That keeps the current design intact and turns the interesting qualitative behavior into a much more interpretable chain of evidence.