Advanced Voice Memory Surface
Use memoair-voice directly when you need manual lane control, custom prompt injection, custom server/router code, or an LLM-decided search_memory tool. Most voice agents should use the framework packages instead.
memoair-livekit (drop-in MemoAirLiveKitAgent). It auto-injects context before every LLM turn. Pipecat, Vapi, and Retell adapter packages land in v0.4; until then this page (and the canonical examples/livekit/voice_agents/memoair_voice_custom_agent.py example) is the supported path for those frameworks and any other custom integration.Install
pip install "memoair-voice>=0.3.1"Raw client
MemoAirVoiceClient wraps the internal runtime pool. Constructed once at boot with the account-scoped API key plus the project and agent IDs; the pool spawns one voice-runtime per (project_id, user.id) as calls arrive, downloading the runtime binary on first use.
import osimport asynciofrom memoair_voice import MemoAirVoiceClient async def main() -> None: client = MemoAirVoiceClient( api_key=os.environ["MEMOAIR_API_KEY"], project_id=os.environ["MEMOAIR_PROJECT_ID"], agent_id=os.environ["MEMOAIR_AGENT_ID"], ) try: result = await client.search_memory( "what timezone does the user prefer?", user={"id": "user_42", "name": "Demo User"}, lanes=["profile", "working", "permanent", "org"], timeout_ms=250, ) print(result.contextText) await client.save_response( user_text="What time is standup?", assistant_text="10:30 IST.", user={"id": "user_42", "name": "Demo User"}, metadata={"framework": "custom"}, ) finally: await client.aclose() asyncio.run(main())Build an org index from code
Most teams upload org knowledge in the dashboard. Use code when you need CI-driven or app-driven indexing.
client = MemoAirVoiceClient( api_key=os.environ["MEMOAIR_API_KEY"], project_id=os.environ["MEMOAIR_PROJECT_ID"], agent_id=os.environ["MEMOAIR_AGENT_ID"],)try: # create_index is a cloud-only call — no runtime, no user_id needed. result = await client.create_index( "product-knowledge", documents=[ {"id": "returns", "text": "Returns are allowed within 30 days."}, {"id": "shipping", "text": "Express shipping takes 1-2 days."}, ], ) # IndexBuildResult(index_name="product-knowledge", chunk_count=2, version=…) print(result)finally: await client.aclose()LLM tool escape hatch
The framework packages auto-search every turn. If you explicitly want the model to decide when to search, expose the raw tool.
# search_memory_tool() lives on the low-level MemoAirVoiceMemory client,# which the high-level MemoAirVoiceClient wraps. Construct it directly when# you need the LLM-decided tool surface for a specific (project, user).from memoair_voice import MemoAirVoiceMemory async with MemoAirVoiceMemory( api_key=os.environ["MEMOAIR_API_KEY"], project_id=os.environ["MEMOAIR_PROJECT_ID"], user_id="user_42",) as memory: tool = memory.search_memory_tool(search_memory_timeout_ms=250) # Register with your framework's tool surface. # Example: OpenAI-style schema for a custom agent runtime. openai_tool = tool.schema() async def handle_tool_call(query: str) -> str: return await tool(query, intent="answer_current_user")When to use this page
- You are building a framework adapter that MemoAir does not ship yet.
- You need lane-level control for experiments or evaluation harnesses.
- You want LLM-decided retrieval instead of deterministic auto-inject.
- You are debugging raw runtime responses and traces.
Framework defaults
If none of the above applies and you're on LiveKit, use memoair-livekit for the drop-in MemoAirLiveKitAgent. For Pipecat / Vapi / Retell — and any other non-LiveKit framework — use MemoAirVoiceClient with the custom-agent pattern at examples/livekit/voice_agents/memoair_voice_custom_agent.py; first-class adapter packages for those three are scheduled for v0.4. See Pipecat, Vapi, and Retell for the framework-specific wiring.
Full method signatures and options for the surfaces shown on this page: Python SDK Reference.