AlphaAvatar v0.6.4: a self-hostable realtime multimodal assistant runtime with shared perception and ENV memory

Hi everyone :waving_hand:

A few weeks ago, I shared an early introduction to AlphaAvatar, an open-source and self-hostable realtime full-multimodal personal AI assistant runtime.

The discussion around that post was very helpful. One particularly useful point was that AlphaAvatar may be more valuable when positioned less as another avatar frontend, and more as a reusable runtime layer for persistent realtime multimodal agents.

That is increasingly how I see the project as well.

AlphaAvatar does not try to own every ASR, TTS, RTC, model, or avatar renderer. Instead, it aims to provide the stateful runtime connecting them:

  • realtime multimodal perception

  • session and interaction state

  • persistent Memory and Persona

  • identity continuity

  • tools, MCP, RAG, and DeepResearch

  • status and workflow feedback

  • avatar and channel outputs

  • self-hosted storage and provider control

Since the previous post, the project has gone through several architecture-focused releases, culminating in v0.6.4.

Updated architecture

The new architecture is organized around six main areas:

1. AlphaAvatar Core

avatar-core contains transport-independent multimodal primitives:

  • EnvObservation

  • EnvAnnotation

  • MediaPayload

  • raw and annotated payload views

  • generic video frame buffers

  • typed perception streams

  • shared timelines

  • consumer-specific observation windows

The goal is to let Memory, Persona, Vision, and future runtime modules consume the same multimodal observation model without depending directly on LiveKit or another RTC backend.

2. AlphaAvatar RTC

avatar-rtc acts as the adapter boundary between external realtime communication systems and AlphaAvatar Core.

LiveKit remains the default RTC integration today, but LiveKit-specific frame and track types are converted at the adapter boundary instead of leaking into the core runtime.

The main design principle is:

RTC is an adapter, not business logic.

Future native WebRTC, aiortc, or other realtime backends should be able to publish the same core observations.

3. AlphaAvatar Agent

avatar-agents owns orchestration and session execution.

The runtime is now separated into parallel components:

  • SessionRuntime

  • ContextRuntime

  • PerceptionRuntime

  • IO Runtime

  • Agent Runtime

  • AvatarEngine as the high-level orchestrator

This moves more responsibilities out of AvatarEngine and gives plugins clearer runtime dependencies and lifecycle boundaries.

4. AlphaAvatar Plugins

Cross-cutting assistant capabilities are implemented as plugins:

  • Memory

  • Persona

  • Status

  • Character

  • Interaction Router

  • future Reflection, Planning, and Behavior plugins

Plugins consume runtime context and perception streams instead of independently subscribing to RTC tracks or rebuilding their own session state.

5. Tools Plugins

Tool and knowledge capabilities remain independently replaceable:

  • MCP

  • RAG

  • DeepResearch

  • future sandbox and external workspace integrations

These tools are also connected to Memory and Status so that long-running actions can remain visible and useful across future sessions.

6. Channels

The same assistant runtime can be exposed through:

  • the realtime web application

  • WhatsApp

  • avatar interfaces

  • future Discord, Slack, mobile, and external application integrations

The channel should change how the assistant is accessed, not recreate the assistant itself.

Shared realtime perception

One of the main changes in v0.6.4 is the introduction of a shared perception path:

RTC / Device Input
        ↓
EnvObservation + MediaPayload
        ↓
PerceptionRuntime
  ├── Typed Streams
  ├── Shared Timeline
  └── Window Builder
        ↓
Persona / Vision / Memory / Future Routers

Previously, different modules could subscribe to the LiveKit video track independently.

Now, an RTC adapter publishes the media once. Multiple runtime consumers can process it using their own cursors, sampling policies, buffers, and temporal windows.

For example:

  • Persona can perform face detection and identity matching.

  • Vision can select recent frames for the current LLM turn.

  • Memory can consume a longer observation window.

  • Future routers can use motion, presence, screen, or speaker events.

These consumers do not have to block one another or use the same sampling rate.

Online ENV Memory

v0.6.4 also introduces the first version of online ENV Memory.

Traditional assistant memory usually begins with conversation text:

user message
    ↓
memory extraction
    ↓
long-term memory

ENV Memory extends this to continuously observed multimodal context:

live visual observations
        ↓
ordered perception window
        ↓
multimodal ENV extraction
        ↓
structured environment memory
        ↓
future visual-history retrieval

Examples of ENV memories include:

  • a person remaining at a desk during a session

  • a cup being placed on a table

  • a plant repeatedly appearing near the user

  • a screen showing a coding workflow

  • a person entering or leaving the visible environment

  • an object changing position across observation windows

The goal is not to store every frame or generate endless image captions.

Instead, AlphaAvatar samples observations, aligns annotations, extracts concise episodic memories, and stores only useful structured results.

Raw video frames remain runtime-only and are not written directly into the vector database or Markdown memory storage.

Annotations as alternate payload views

Persona can now attach face annotations to shared observations.

An observation may contain multiple representations:

  • raw video frame

  • raw JPEG

  • annotated video frame

  • annotated JPEG

  • future derived representations

Memory can prefer an annotated JPEG when extracting ENV context, while Vision can resolve the most recent annotated frame when building model context.

The raw representation remains unchanged.

This allows different modules to enrich the same observation without copying or overwriting the original media.

Graph-aware multimodal memory

The previous v0.6.3 release introduced graph-aware Memory foundations:

  • multi-object memory ownership

  • graph node mentions

  • session-scoped local entity keys

  • alias-ready graph lookup

  • LanceDB graph-node indexing

  • graph-aware semantic retrieval

ENV Memory now plugs into the same system.

A visual memory may be connected to concrete observed entities such as:

  • a visible person

  • a face track

  • a screen

  • a document

  • a plant

  • a vehicle

  • a physical object

  • a distinguishable room

The memory text remains the source of truth, while graph nodes act as sparse retrieval anchors.

Provider-independent extraction

Another recent change is the task-based Provider Layer.

Memory, Persona, embeddings, and multimodal extraction tasks can be configured independently.

For example:

  • one model may extract conversation memory

  • another multimodal model may process ENV observations

  • a local embedding model may index memories

  • another provider may handle the realtime assistant response

The personal data and storage layer can remain self-hosted even when optional external inference providers are used.

Why keep this outside the model?

It is possible that more orchestration will eventually become model-native.

Models may increasingly handle:

  • context compression

  • tool planning

  • multimodal state tracking

  • memory selection

  • user modeling

However, I still think an explicit user-owned runtime remains valuable for:

  • privacy boundaries

  • persistent personal storage

  • model and provider swapping

  • observability

  • replay and evaluation

  • identity management

  • tool permissions

  • debugging

  • user-editable Memory and Persona

  • cross-channel continuity

The model can become more capable without requiring personal state, tools, and system behavior to disappear into an opaque kernel.

Current limitations

AlphaAvatar is still developer-first and under active development.

Current limitations include:

  • LiveKit is still the primary RTC implementation.

  • ENV Memory currently focuses mainly on sampled visual observations.

  • Visual-history retrieval is still relatively basic.

  • Multi-user visual and speaker routing requires more work.

  • Reflection, Planning, Behavior, and Interaction Router are not complete.

  • User-facing Memory and Persona inspection controls are still being developed.

Next steps

The next major directions include:

  • audio and screen-based ENV Memory

  • richer object-, event-, identity-, and time-aware retrieval

  • cross-window event consolidation

  • multi-user face and speaker alignment

  • alternative RTC adapters

  • interaction routing and proactive behavior

  • Reflection and Planning

  • replay and evaluation tooling

  • user-controlled Memory and Persona editing

Questions for the community

I would be interested in feedback on a few design questions:

  1. Which assistant capabilities should remain explicit runtime components, and which should eventually become model-native?

  2. What is the right evaluation framework for long-running ENV Memory?

  3. Should multimodal memory primarily store textual episodes, structured events, graph relations, selected media artifacts, or a combination?

  4. What runtime interface would make AlphaAvatar useful to other voice-agent, digital-human, AI companion, or AI VTuber projects?

Links

Thanks to everyone who provided feedback on the original post. The architecture is still evolving, and contributions, criticism, comparisons with related projects, and implementation discussions are very welcome.

Hi. I also took a quick look at the latest code on my side:


I think the shared-perception refactor is a useful step toward the runtime-layer positioning you described. In particular, publishing media once into a transport-independent observation model, then letting Persona, Vision, Memory, and future routers consume it through their own cursors and windows, seems like a much cleaner foundation than allowing each plugin to rebuild its own RTC-specific perception path.

My short answers to the four questions would be:

Question My current answer
What should remain explicit in the runtime? Keep externally consequential commitments explicit: identity ownership, durable-memory commits, permissions, retention/deletion, provider egress, cancellation, delivered output, and audit information. Models can propose interpretations, associations, summaries, plans, and memory candidates.
How should long-running ENV Memory be evaluated? Treat it as a lifecycle: write, maintain, retrieve, use, and operate. A final QA score alone would hide whether the failure happened during perception, memory creation, updating, retrieval, or downstream use.
What should multimodal memory store? Probably a combination, but with narrow responsibilities: an observation receipt, a lossy episodic record, structured claim/state candidates, sparse graph/vector projections, and optionally selected media with explicit retention rules.
What interface would help other projects? Keep a small AlphaAvatar-native perception/session contract, separate the in-process plugin API from the out-of-process wire protocol, and expose adapters to adjacent standards rather than making one external protocol define the internal architecture.

The common thread is what I would call the commitment boundary:

observation
    ↓
model interpretation / memory candidate
    ↓
runtime policy decision
    ↓
durable memory / accepted state / delivered output / external action

Models can become much better at perception, compression, association, planning, and memory selection without requiring the final commitment step to disappear into the model. The runtime is where those commitments can remain user-owned, inspectable, correctable, provider-independent, and enforceable.

A default route that seems relatively low-risk

Rather than selecting a large memory framework or external protocol first, I would probably proceed in this order:

  1. Preserve the current shared-perception separation.
  2. Define a few small contracts around it:
    • observation and stream/QoS semantics;
    • memory and current-state semantics;
    • authority and commit semantics;
    • trace and provenance semantics.
  3. Create a small fixed set of synthetic and recorded scenario traces.
  4. Compare text-only, structured-only, and hybrid memory representations on exactly those traces.
  5. Stabilize the internal semantics before exposing multiple external adapters.
  6. Before serious persistent multi-user or write-capable tool deployment, add enough structured trace information to reconstruct how an observation affected memory and later behavior.

That route does not require deciding the final memory architecture immediately. It creates a way to compare later alternatives without changing the question each time.

The first things I would make explicit are:

  • stable IDs and correlation from observation to later response/action;
  • stream-specific retention, loss, resume, and late-arrival behavior;
  • the distinction between an observation, an episode, a derived claim, historical state, and accepted current state;
  • a lightweight provenance receipt even when raw media is not retained;
  • user/tenant/channel/tool authority as one cross-cutting policy boundary.
1. Runtime components versus model-native capabilities

A distinction that may scale better than a fixed list of modules is:

Can this output remain probabilistic and replaceable, or must the system be able to enforce, explain, undo, or audit it?

Reasonable model-native candidates

These can remain model-dependent proposals, provided their downstream use is controlled:

  • visual/audio classification;
  • captioning and event segmentation;
  • candidate entity association;
  • candidate memory extraction;
  • summarization and context compression;
  • retrieval ranking;
  • planning and routing suggestions;
  • proactive-assistance suggestions;
  • suggested expression, gesture, or response style.

The runtime does not necessarily need to understand how a model reached those suggestions. It does need to know what happened after receiving them.

Capabilities that seem safer as explicit runtime commitments

  • which user, participant, workspace, or channel owns data;
  • whether data may be sent to a particular inference provider;
  • whether a candidate becomes durable Memory or Persona;
  • whether an older claim is corrected, superseded, disputed, or merely historical;
  • retention, export, correction, and deletion;
  • read-only versus write/destructive tool authority;
  • whether explicit approval is required;
  • whether a generated response was displayed, spoken, interrupted, canceled, or never delivered;
  • retry and idempotency behavior for external actions;
  • trace redaction and audit access;
  • cross-channel visibility rules.

A useful rule of thumb may be:

Question If yes, prefer an explicit runtime decision
Can this affect another person or an external system? Yes
Must the user be able to inspect, correct, or delete it? Yes
Must it survive a model/provider replacement? Yes
Could repeating it cause duplicate external effects? Yes
Does it decide who owns or may see information? Yes
Would an incident require reconstructing the decision? Yes

This is also why I would keep the runtime/model boundary separate from the plugin boundary. A Memory plugin can use models internally, while the durable commit and deletion contract remains explicit. Similarly, a tool-routing model can propose a call while the authority check remains outside it.

The MCP security guidance is relevant as an adjacent example, not as a complete AlphaAvatar design: protocol support does not remove the implementation’s responsibility for authorization, scope minimization, session/user binding, credential handling, and consent.

2. Evaluating long-running ENV Memory

I would avoid treating ENV Memory as one end-to-end QA number. A high final score can hide poor writing compensated by a strong model, while a low score can come from retrieval or action selection even when the stored memory was correct.

The recent WorldMemArena work uses a useful architecture-independent decomposition:

  1. Write — did the system retain the evidence that would later matter?
  2. Maintain — did it consolidate repetitions, preserve history, and update stale state correctly?
  3. Retrieve — did it surface the right evidence at decision time?
  4. Use — did the agent actually use the retrieved evidence correctly?

For a realtime runtime I would add a fifth category:

  1. Operate — did it remain timely, bounded, isolated, and observable over a long-running stream?

Possible metrics by stage

Stage Example checks
Write event coverage, false-memory rate, duplicate rate, identity-binding accuracy, evidence sufficiency
Maintain stale-state rate, contradiction handling, correction propagation, cross-window consolidation, history preservation
Retrieve evidence recall/precision, temporal relevance, identity relevance, modality selection, distractor resistance
Use task success, answer grounding, calibrated abstention, correct tool/action choice, harmful use of stale memory
Operate ingestion lag, annotation lag, memory-write latency, query latency, consumer lag, dropped records, storage growth, provider-egress volume

The write stage is especially difficult because the future query is not known yet. An extraction can produce a very readable episode while discarding the visual detail that a future question needs. Therefore I would test evidence sufficiency, not only summary quality.

A compact scenario suite

A small deterministic suite may be more useful initially than integrating a large benchmark:

Stable scene

A red cup remains on the desk for twenty observation windows.

Checks:

  • does it create one useful episode rather than twenty near-duplicates?
  • can it still answer that the cup remained present?
  • does consolidation preserve the time range?

Short, important event

A key is placed beside the laptop for two seconds and then removed.

Checks:

  • can sampling miss it?
  • if captured, does it survive consolidation?
  • can the system distinguish past presence from current presence?

State evolution

red cup on desk
→ red cup removed
→ blue cup appears
→ red cup returns

Checks:

  • current state;
  • event history;
  • change description;
  • uncertainty about whether the returning cup is the same physical object.

Multiple people

Two people interact with the same object.
One leaves.
The other later moves the object.
One face becomes temporarily occluded.

Checks:

  • action-to-person binding;
  • safe use of unknown;
  • correction after identity resolution;
  • whether another person’s episode leaks into the primary user’s long-term state.

M3-Agent is one of the closer public projects because it builds episodic and semantic memory from continuous visual/audio input and uses an entity-centric multimodal graph. Its public issue tracker also contains a report where two people were apparently consolidated into one character (issue #18). That does not imply the same cause exists here, but it is a useful failure shape for a synthetic identity test.

Correction

The system records that an object belongs to Alice.
The user later says it was borrowed from Bob.

Checks:

  • whether the original episode remains as history;
  • whether the ownership claim is corrected;
  • whether graph/vector projections are updated;
  • whether later retrieval still presents the old claim as current.

Delayed processing

Observation arrives.
Annotation is delayed beyond the normal window.
A consumer temporarily falls behind retention.
The session reconnects.

Checks:

  • late-annotation policy;
  • gap visibility;
  • duplicate processing;
  • resume behavior;
  • whether memory is written twice.

Controls that help avoid over-interpreting results

For the same scenarios, compare:

  • no long-term memory;
  • text episode only;
  • structured event/state only;
  • selected media only;
  • text plus structured state;
  • text plus selected media;
  • timestamp-shuffled memory;
  • identity-label-swapped memory;
  • an irrelevant image substituted for the retrieved image;
  • retrieved memory withheld from the final answering model.

The timestamp and identity controls test whether the system is using temporal/entity structure rather than semantic similarity alone.

The irrelevant-image and text-only controls test whether a “multimodal memory” result is really using visual evidence or merely a generated caption. MemEye is useful here because it explicitly considers visual necessity and shortcut resistance. TeleEgo is another relevant reference for streaming, memory persistence, and long-running egocentric inputs.

I would treat these recent benchmarks as sources of evaluation vocabulary and test design, not as settled standards or direct drop-in leaderboards for AlphaAvatar.

3. Text episodes, structured events, graphs, and selected media

I do not think these need to compete for the role of a single canonical format. They can be projections with different responsibilities.

A possible layering is:

Observation receipt
    ↓
Lossy episodic record
    ↓
Structured claim/event candidates
    ↓
Policy-accepted current-state projection
    ↓
Graph/vector retrieval projections

Optional selected media can remain beside this chain when later reinspection is valuable and retention is permitted.

1. Observation receipt

This does not have to contain the original video frame.

It can be a small immutable record such as:

observation_id: obs_...
observed_at: ...
source_id: camera_...
participant_ids: [...]
modality: video
annotation_ids: [...]
extractor:
  provider: ...
  model: ...
  prompt_schema_version: ...
privacy_class: ...
media_retained: false

Its purpose is to answer:

  • what input existed;
  • when and where it was observed;
  • which processing activity derived the memory;
  • which identity/annotation information was available at that time.

The W3C PROV data model provides useful general vocabulary here—entities, activities, agents, use, generation, and derivation. I would borrow the conceptual model rather than implement the whole ontology.

2. Episodic record

This is a readable, intentionally lossy description of an event or interval:

At approximately 10:02, a red cup was placed on the desk.

It is useful for:

  • human inspection;
  • semantic retrieval;
  • narrative continuity;
  • debugging;
  • low-cost model context.

It should not be expected to preserve every visual detail.

3. Structured claim or event candidate

This captures machine-actionable semantics without automatically declaring them permanently true:

candidate_id: claim_...
subject: object_track_7
predicate: located_on
object: desk_2
valid_from: ...
valid_until: null
status: candidate
supported_by:
  - obs_...

Other useful statuses might include:

candidate
accepted
disputed
superseded
rejected
unknown

The important distinction is not necessarily a scalar confidence value. It is why the runtime currently considers a claim usable.

For example:

  • directly observed;
  • model-classified;
  • inferred from multiple episodes;
  • explicitly stated by the user;
  • confirmed by the user;
  • contradicted by newer evidence.

4. Current-state projection

Current state should not need to erase historical episodes.

For example:

Historical episode:
    A red cup was present on the desk from 10:02 to 10:14.

Current-state projection:
    No cup is currently confirmed on the desk.

Open uncertainty:
    The later red cup may or may not be the same physical object.

This avoids making either of these mistakes:

  • returning an old observation as the current state;
  • deleting useful history merely because the state changed.

A full bitemporal database or event-sourcing architecture may be excessive initially. A smaller schema may be enough:

observed_at
recorded_at
valid_from
valid_until
supersedes
corrected_by
supported_by
contradicted_by

5. Graph and vector projections

Graph nodes and embeddings are useful indices, but they do not have to become the epistemic authority.

A graph can answer:

  • which episodes mention this person or object;
  • which room or screen was involved;
  • which claims conflict;
  • how identities or aliases are connected;
  • what changed over time.

A vector index can answer:

  • which memories are semantically relevant to this query?

Both can point back to the episodic/claim records. Rebuilding either projection should not require inventing facts that no longer have a traceable source.

6. Selected media

Retaining every frame conflicts with the project’s stated goal and creates obvious privacy/storage problems. However, retaining no reinspection path can make certain failures impossible to distinguish.

A middle route is selective media retention governed by policy:

  • explicit user opt-in;
  • bounded TTL;
  • an event was marked important;
  • the extraction was uncertain;
  • identity binding requires later review;
  • the user explicitly bookmarks the event;
  • a debugging/test mode is active.

Otherwise, an observation receipt can remain without raw media.

Interpreting “memory text remains the source of truth”

That phrase can mean at least two slightly different things:

  1. text is the human-readable canonical record, while graphs are sparse indices;
  2. the natural-language text is the final epistemic authority.

The first interpretation seems quite practical. For the second, it may help to retain a small amount of structured status/provenance beside the text, so an observation, an inference, and an accepted current-state claim do not become indistinguishable after storage.

This would preserve the useful text-first design without requiring the text itself to carry every update, identity, temporal, and trust semantic.

4. A reusable runtime interface

I would separate two audiences because they need different contracts.

A. In-process plugin contract

For AlphaAvatar plugins in the same Python process, the useful interface may include:

  • typed observations and annotations;
  • typed memory candidates and policy decisions;
  • lifecycle hooks;
  • async cancellation;
  • consumer registration and cleanup;
  • cursor/resume semantics;
  • capability discovery;
  • structured errors;
  • health and lag metrics.

This layer can remain Python-native and efficient.

B. Out-of-process wire contract

For other voice agents, VTubers, digital humans, channel bridges, or remote services, a small versioned event contract would be easier to adopt than internal classes.

A possible envelope:

{
  "schema_version": "alphaavatar.runtime.v1",
  "event_id": "...",
  "event_type": "perception.observation.created",
  "source": "...",
  "occurred_at": "...",
  "session_id": "...",
  "participant_id": "...",
  "turn_id": "...",
  "correlation_id": "...",
  "causation_id": "...",
  "privacy_class": "...",
  "payload": {}
}

Not every event needs every ID, but consistent identity and causation fields make replay, deduplication, and cross-process debugging much easier.

I would consider documenting at least these event families:

session.*
participant.*
perception.observation.*
perception.annotation.*
interaction.turn.*
generation.*
delivery.*
tool.*
memory.candidate.*
memory.commit.*
memory.correction.*
state.*
policy.*

Stream-specific QoS/loss semantics

A reusable contract also needs to say whether each stream is lossy.

Stream/event Reasonable default
Raw/recent video frames Bounded, drop older frames to stay current
Intermediate ASR hypotheses Replace/coalesce
Final user transcript Preserve or explicitly report loss
Presence/motion hints Bounded and possibly coalesced
Identity annotations Bounded lateness with explicit orphan policy
Tool lifecycle Preserve and correlate
Durable-memory commit Idempotent and auditable
Destructive external action Idempotent or protected by an operation key
UI/avatar animation hints Usually lossy
User correction/deletion Preserve and confirm application

The mature idea worth borrowing from systems such as ROS 2 QoS and GStreamer queues is not their implementation stack. It is the explicit vocabulary:

  • history depth;
  • lifespan/max age;
  • reliability;
  • maximum records/bytes/time;
  • block versus drop;
  • drop-oldest versus drop-newest;
  • deadline;
  • consumer lag;
  • late-arrival policy.

Adjacent standards

I would not make any one of these the AlphaAvatar internal model, but each can cover a boundary:

  • CloudEvents for a small interoperable event envelope;
  • AsyncAPI to document message-driven channels, operations, and schemas;
  • AG-UI for frontend-facing run, message, tool, activity, and state events;
  • MCP for tools and resources;
  • OpenTelemetry for traces, metrics, and logs.

In other words:

AlphaAvatar-native perception/session semantics
    ├── AG-UI adapter for agent ↔ frontend interaction
    ├── MCP adapter for tools/resources
    ├── CloudEvents-like envelope for external events
    ├── AsyncAPI document for the wire contract
    └── OpenTelemetry export for observability

AG-UI is particularly useful as a comparison because it separates lifecycle, text, tool-call, activity, and state events, but its primary boundary is agent-to-frontend. It does not define continuous perception, annotation lateness, identity fusion, or durable ENV Memory commit semantics, so those should probably remain AlphaAvatar-native.

Channel continuity also needs channel policy

I agree with the principle that a channel should not recreate the assistant. However, continuity does not necessarily mean identical authority everywhere.

For example, the same assistant may have different rules for:

  • which memories are retrievable in a personal voice session versus a shared avatar screen;
  • whether a channel may display private ENV observations;
  • which tools are read-only or write-capable;
  • whether proactive output is appropriate;
  • whether speech, UI, or message delivery counts as the authoritative delivered response.

That could be represented as a channel policy attached to the same runtime state, rather than separate assistant instances.

A small synthetic check against the current runtime contract

For one narrow check, I ran a CPU-only synthetic probe against commit:

1cc2c6fc84650bbda114a82b33e5f5c2af834167

What I observed:

  • the perception streams were already bounded, so the concern is not an unlimited queue;
  • when a consumer crossed the retention boundary, it received the retained tail, but the public read result did not indicate how much earlier data had been missed;
  • unmatched annotations, including annotations targeting an already-evicted observation, remained pending in the tested timeline path;
  • a runtime-only observation without a persisted path produced an empty to_evidence_dict() result.

These are not claims of production failures. They were isolated synthetic contract checks, and upper layers may impose additional constraints.

The useful interface questions they suggest are:

  • how does a consumer learn that it crossed the retention boundary?
  • is there a first_available_seq, gap count, or equivalent metric/event?
  • what are the TTL, maximum size, and discard reason for orphan/late annotations?
  • when raw media is intentionally not persisted, where is the non-media provenance receipt stored?
  • when a consumer reconnects, does it resume, replay the retained window, or start at the newest item?

The roadmap already mentions retention, backpressure, payload pruning, and consumer-lag policy, so this looks more like an opportunity to make those semantics visible in the public contract than a different architectural direction.

5. Trust, security, and minimum replayability

As Memory, identity, proactive behavior, and MCP tools converge, I think security will be easier to reason about as one cross-cutting trust model rather than separate plugin TODOs.

A compact policy matrix might cover:

Boundary Example decision
Capture Is camera/screen/audio observation enabled in this context?
Identity Which user/participant/tenant may this observation belong to?
Provider egress May the payload or derived data leave the self-hosted boundary?
Memory commit May this candidate become durable Memory or Persona?
Retrieval In which session/channel may the memory be surfaced?
Tool authority Is the operation read-only, write-capable, destructive, or approval-gated?
Retention How long may raw, derived, and trace data remain?
Correction/deletion Which derived claims and projections must be recomputed?
Audit Who may inspect traces and what must be redacted?

This is not a claim that AlphaAvatar currently has a particular vulnerability. It is a way to connect privacy controls, multi-user isolation, memory editing, provider selection, tool permissions, and replay under one decision model.

Replay versus reconstructability

A full replay UI can probably wait while the project is developer-first.

Before persistent multi-user deployment, long-lived personal memory, proactive operation, or write-capable tools, I would want minimum reconstructability:

observation
→ annotation/extraction
→ memory candidate
→ commit/reject
→ update/correction
→ retrieval
→ generation
→ delivered/canceled output
→ external action

That does not require storing every prompt, frame, transcript, or private payload indefinitely.

The minimum record can be:

  • stable IDs and timestamps;
  • event type and result;
  • policy decision and reason code;
  • model/provider/schema version;
  • references to redacted or separately retained artifacts;
  • cancellation/interruption/drop reason;
  • operation/idempotency key;
  • retention and privacy classification.

This provides causality without requiring a surveillance log.

LiveKit observability is a useful adjacent example because it can correlate transcripts, traces, logs, metrics, and recordings in a session timeline, while also allowing collection categories such as audio, transcripts, traces, and logs to be enabled or disabled separately. AlphaAvatar can remain fully self-hosted and still borrow the separation between correlation and raw-data retention.

Generated versus delivered output

For realtime assistants, I would also preserve the distinction between:

generated
queued for TTS/UI
partially delivered
fully delivered
interrupted
canceled
superseded

This matters for memory and auditing. A generated sentence that was interrupted before the user heard it should not automatically be treated as shared conversational history or as a fact the assistant successfully communicated.

The same principle applies to external actions:

proposed
authorized
started
completed
failed
canceled
compensated

This becomes more important when model planning and proactive behavior become more capable.

A possible near-term milestone

If I had to reduce the above to one practical milestone, I would choose:

A small versioned “runtime trace contract” plus a fixed scenario suite that can exercise multiple memory representations.

For each scenario, preserve a trace such as:

observation IDs
annotation IDs
candidate memory
commit/reject decision
historical episode
current-state projection
retrieved evidence
final response/action
timing and drop information

Then the project can compare:

  • different perception providers;
  • different ENV extraction models;
  • text-only versus structured versus hybrid memory;
  • graph implementations;
  • RTC adapters;
  • local versus external inference;
  • future model-native memory selection.

The comparison remains meaningful because the observation, expected state transitions, and downstream task are fixed.

This also gives other projects something concrete to integrate against: not only a list of Python classes, but a set of events, lifecycle expectations, and conformance scenarios.

Related work I found useful as a map

These are comparisons and sources of vocabulary rather than direct prescriptions:

  • M3-Agent paper and repository: continuous visual/audio input, episodic and semantic memory, and entity-centric multimodal graphs.
  • WorldMemArena: stage-level evaluation of memory writing, maintenance, retrieval, and use in evolving environments.
  • TeleEgo: long-running egocentric streams, realtime behavior, and memory persistence.
  • MemEye: testing whether visual evidence is actually necessary instead of allowing caption-based shortcuts.
  • W3C PROV: stable vocabulary for entities, activities, agents, and derivation.
  • CloudEvents: a small common event envelope.
  • AsyncAPI: machine-readable documentation for message-driven APIs.
  • AG-UI event model: frontend-facing lifecycle, message, tool, activity, and state events.
  • MCP security best practices: authorization and trust-boundary considerations for external tools.
  • LiveKit observability: an adjacent example of correlating realtime-agent traces while separating data-collection categories.

Overall, I think v0.6.4 makes the perception substrate much clearer. The next useful layer may be to make the runtime’s commitments equally explicit: when an observation becomes a durable memory, when memory becomes accepted current state, when identity becomes authoritative, when generated output becomes delivered interaction history, and when a model proposal is allowed to affect an external system.

Hi John — thank you for the extremely detailed review, and especially for taking the time to inspect the implementation and run a synthetic probe against the current code.

The “commitment boundary” is a very useful framing. It describes the direction I want more precisely: models may propose interpretations, associations, memory candidates, plans, and proactive actions, while the runtime remains responsible for deciding what becomes durable, authoritative, visible, or externally consequential.

I also agree with your clarification around “memory text remains the source of truth.” My original intention was that readable memory should remain canonical relative to graph and vector projections, rather than treating unstructured text as sufficient for every temporal, provenance, correction, and authority semantic. A small structured layer alongside the readable episode seems like the right direction.

The synthetic probe also surfaced several concrete contract gaps that I think are valid:

  • consumers should be explicitly informed when they cross the retained observation boundary;

  • late or orphaned annotations need bounded retention and visible discard semantics;

  • runtime-only observations should still produce a lightweight provenance receipt even when raw media is not persisted;

  • reconnect and cursor-resume behavior should be part of the public contract rather than an implicit implementation detail.

My current thinking is to approach this incrementally.

First, I will harden the existing perception contract around gaps, retention, annotation lateness, provenance, and resume behavior. After that, I plan to introduce a minimal candidate → policy decision → durable commit path for ENV Memory, with stable IDs and enough trace metadata to reconstruct how an observation affected later memory and behavior.

I also like the idea of using the event schema as an internal runtime trace contract first, then deriving an out-of-process protocol only after the internal semantics have stabilized. That should avoid committing too early to CloudEvents, AG-UI, or another external envelope while still keeping future adapters possible.

A small deterministic scenario suite also seems like a good immediate evaluation foundation, particularly for repeated scenes, short events, evolving state, delayed annotations, identity ambiguity, and later user corrections.

Thank you again — this gives me a much clearer path from the shared-perception substrate in v0.6.4 toward an inspectable and enforceable runtime contract. I would be very interested in your feedback again when the first trace schema and scenario tests are available.

Hi Knack — this is a really interesting framing, especially the point that a perception or memory system which only reacts to arriving facts is structurally blind to expected events that fail to occur.

I think this connects to AlphaAvatar in two important ways.

First, ENV Memory should probably not only record presence and explicit state changes. Over time, it may also learn recurring temporal patterns and create an absence or deviation candidate when an established pattern stops occurring. As you pointed out, the broken pattern may contain much more information than another routine observation.

I would still want that absence to remain a probabilistic candidate rather than immediately becoming a fact, because a missing observation could also be caused by sampling, occlusion, camera position, sensor downtime, or the user simply changing context.

Second, your “Knack is a cat person” example is exactly why provenance and claim status matter. These should remain distinguishable:

  • “Knack said that his cat’s name is Tuffy.”

  • “The system inferred that Knack may be a cat person.”

A user statement, a direct observation, and a system inference should not silently collapse into the same type of memory or authority level.

This is also close to a longer-term direction I am considering for AlphaAvatar: a temporal expectation layer that learns recurring behavioral or environmental patterns, generates absence or deviation candidates, and passes them through a proactive-interaction policy before deciding whether the assistant should mention them. These inferred deviations would remain separate from directly observed or user-confirmed memory.

Surprisal seems useful as one signal in that process, although I suspect it would need to be combined with confidence, recurrence, user relevance, and practical salience rather than becoming the sole importance score.

Thanks for sharing this. I would be interested to learn more about how you estimate the underlying probabilities for sparse person-model dimensions, and how you distinguish genuine silence from missing or incomplete observation.

BTW, we also have an AlphaAvatar Discord community, and you would be very welcome to join. I would especially value your feedback as the runtime trace contract and deterministic scenario tests take shape. Contributions are of course welcome too, but even continued architectural discussion would be extremely helpful.

BTW, we also have an AlphaAvatar Discord community if you would like to continue the discussion there. The temporal-expectation, silence, and proactive-interaction directions seem especially relevant, and I would be very interested in comparing approaches or experimenting together.

Hi Knack — thank you, this is extremely helpful.

“Absence is only information if you can prove you were looking” is probably the clearest formulation of the problem I have seen. It also reveals that absence detection cannot be implemented only at the Memory or proactive-policy layer. The perception/runtime layer must first be able to provide an observation-coverage receipt: what source was active, what time window was covered, whether sampling was continuous enough, and whether the result was genuinely empty rather than simply unavailable.

That suggests a useful distinction for AlphaAvatar:

  • positive observation: the runtime observed something;

  • negative observation: the runtime actively checked a sufficiently covered window and did not observe the expected event;

  • missing observation: the runtime cannot make a claim because coverage was incomplete or unavailable.

Only the second case should be allowed to produce an absence candidate.

Your point about probability estimates is also reassuring. I agree that a bounded, monotonic, auditable ranking signal is more useful in practice than pretending to have a well-calibrated probability over sparse person-model dimensions. Capping surprisal and reducing its influence when the underlying dimension has little evidence both seem like sensible safeguards.

The separation between surprisal, salience, and provenance is especially valuable. They answer different questions:

  • surprisal: how much did this update the model?

  • salience: how retrievable should it be?

  • provenance: where did it come from, and how much authority does it have?

Collapsing those into a single importance score would make policy decisions difficult to inspect.

I also strongly agree that surprisal should rank candidates, never decide outcomes. Whether something becomes durable memory, updates a current-state projection, triggers reflection, or causes proactive interaction should remain a runtime policy decision.

The reflection loop failure you described is particularly relevant to AlphaAvatar’s future architecture. I will need to make the distinction between primary evidence and derived content explicit:

  • observations, user statements, and raw tool results are evidence;

  • summaries, reflections, inferred claims, and absence candidates are derived artifacts.

Derived artifacts may reference evidence and produce new claims, but they must not increase the evidence count that triggers further reflection. Otherwise the system can quietly become self-referential without producing an obvious runtime error.

The Shannon/Knack example also makes provenance more concrete than a generic confidence score. A user-stated claim, a self-description, and a reflection-generated inference must not compete in the same slot with equal authority. Source role and authority should participate directly in conflict resolution, and a self- or reflection-derived claim should never silently overwrite an explicit user statement.

This discussion is helping clarify several future boundaries for AlphaAvatar:

  • observation coverage before absence inference;

  • evidence versus derived artifacts;

  • surprisal as ranking rather than policy;

  • source-aware claim authority;

  • class-specific retention and decay;

  • reflection triggers that count only primary evidence.

And yes, keeping this discussion public makes sense. The examples and failure cases are likely useful to other people working on persistent assistants as well.

Thank you again for sharing the lessons from your own implementation. They are exactly the kind of subtle failures that are much easier to prevent architecturally than to diagnose later.