Skip to content

feat(memory): use List Observations API for memory_mode="once" - #98

Open
bsahajsinghani wants to merge 1 commit into
twilio:mainfrom
bsahajsinghani:bhoomi/once-mode-list-api
Open

feat(memory): use List Observations API for memory_mode="once"#98
bsahajsinghani wants to merge 1 commit into
twilio:mainfrom
bsahajsinghani:bhoomi/once-mode-list-api

Conversation

@bsahajsinghani

@bsahajsinghani bsahajsinghani commented Aug 4, 2026

Copy link
Copy Markdown

Summary

  • memory_mode="once" now fetches all observations via the List Observations API (GET /Profiles/{id}/Observations) instead of the Recall API
  • memory_mode="always" is unchanged — continues to use the Recall API with per-turn semantic search
  • Observation count is configurable via TWILIO_MEMORY_OBSERVATIONS_LIMIT env var (default 20, max 500)

Why

The Recall API runs a semantic vector search on every call. For "once" mode — where the intent is to fetch everything upfront and cache it — this is the wrong tool:

  • Adds ~750ms semantic search overhead at call start
  • Returns results ranked by relevance, not all observations
  • Breaks LLM prefix caching since the memory block can vary between calls

The List Observations API fetches a flat list of all observations with no semantic search, making the cached memory block static and predictable across turns — enabling prefix caching on voice calls.

API reference: https://www.twilio.com/docs/api/memory/v1/observations/list-profile-observations

Changes

  • src/tac/context/memory.py — adds list_observations() method on MemoryClient
  • src/tac/core/tac.py — adds list_observations() on TAC class with profile resolution
  • src/tac/channels/base.py"once" mode calls tac.list_observations() instead of tac.retrieve_memory()

Test plan

  • make test passes (692 tests)
  • make type-check passes (no new errors)
  • Set memory_mode="once" and verify List API is called once at call start and cached
  • Set memory_mode="always" and verify Recall API is still used per turn

memory_mode="once" now fetches all observations via the List Observations
API (GET /Profiles/{id}/Observations) instead of the Recall API. This
avoids semantic search overhead (~750ms) on every call start and enables
LLM prefix caching since the memory block is static across turns.

memory_mode="always" is unchanged — it continues to use the Recall API
with the user's per-turn query for semantic relevance.

Observation count is configurable via TWILIO_MEMORY_OBSERVATIONS_LIMIT
env var (default 20, max 500). Example: TWILIO_MEMORY_OBSERVATIONS_LIMIT=500

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread src/tac/context/memory.py
async def list_observations(
self,
profile_id: str,
limit: int = 500,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need the max number here? any latency implications with this number setting this high?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants