Python: samples: add Synap long-term memory plugin sample#14008
Python: samples: add Synap long-term memory plugin sample#14008visy-ani wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 91%
✓ Correctness
This is a clean, well-structured sample that correctly uses the Semantic Kernel APIs (Kernel, ChatHistory, FunctionChoiceBehavior.Auto, get_chat_message_content). The only minor correctness concern is that
get_chat_message_contentreturnsChatMessageContent | None(chat_completion_client_base.py:178), and the sample passesresponsedirectly tohistory.add_message()on line 66 without a None guard. IfresponsewereNone,add_messagewould raise aTypeErrorbecause it checksisinstance(message, ChatMessageContent)then"role" not in message(chat_history.py:205-208), andindoesn't work onNoneType. In practice, theNonereturn path is markedpragma: no coverwith a comment saying 'this should not happen' (chat_completion_client_base.py:193-194), and some other samples (e.g., crew_ai_plugin.py:93-94) also skip this check. So this is non-blocking but worth noting.
✓ Security Reliability
This is a straightforward sample file demonstrating a third-party Synap memory plugin. No security or reliability issues were found. The sample follows existing conventions: API keys are sourced from environment variables (no hardcoded secrets), demo-only identifiers are clearly labeled, and the code structure mirrors other memory samples in the directory. The one minor deviation from repo convention is using bare
os.environ[]for the Synap API key (other samples delegate env-var resolution to SDK constructors via Pydantic settings), but this is dictated by the third-party SDK's interface and is not a security or reliability concern.
✓ Test Coverage
This PR adds a new concept sample for Synap long-term memory. Regarding test coverage: the repository convention is that most concept samples—especially those requiring external service credentials—are not tested in
test_concepts.py. Of the existing memory samples, onlysimple_memory.pyis tested;complex_memory.pyandmemory_with_pandas.pyare not (they also depend on external services). Sincesynap_memory.pyrequires bothSYNAP_API_KEYandOPENAI_API_KEYplus third-party packages (maximem_synap,synap_semantic_kernel), skipping integration tests is consistent with existing patterns. However, the sample is not listed in the concepts README.md, which every other memory sample is.
✗ Design Approach
The sample’s overall shape is fine, but it currently does not demonstrate the cross-session memory behavior described in the PR. The second turn reuses the same
ChatHistory, so the model can answer from short-term conversation state even if the Synap plugin never stores or retrieves anything.
Flagged Issues
- The sample keeps the user's fact in the same ChatHistory across both turns (lines 60-72), so the recall question can be answered from short-term chat context alone—without exercising Synap's persistent memory path at all. This means the sample does not actually demonstrate the cross-session memory feature it introduces.
Automated review by visy-ani's agents
| chat_history=history, settings=settings, kernel=kernel | ||
| ) | ||
| print(f"Assistant: {response}") | ||
| history.add_message(response) |
There was a problem hiding this comment.
Nitpick: get_chat_message_content returns ChatMessageContent | None. If response is None, add_message will raise TypeError. The None path is effectively dead code today (marked pragma: no cover) and other samples also skip this guard, so this is non-blocking—but adding a guard would be more defensive.
| history.add_message(response) | |
| if response: | |
| history.add_message(response) |
| history.add_user_message("What do you know about my dietary restrictions?") | ||
| response = await chat_service.get_chat_message_content( | ||
| chat_history=history, settings=settings, kernel=kernel | ||
| ) | ||
| print(f"Assistant: {response}") | ||
|
|
There was a problem hiding this comment.
The PR describes persistent cross-session memory, but history still contains the user's original fact from the first turn. The model can answer from short-term chat history even if synap-store_memory/synap-search_memory are never invoked. Re-create the ChatHistory before the recall turn to actually exercise the long-term memory path.
| history.add_user_message("What do you know about my dietary restrictions?") | |
| response = await chat_service.get_chat_message_content( | |
| chat_history=history, settings=settings, kernel=kernel | |
| ) | |
| print(f"Assistant: {response}") | |
| # Turn 2: recall from a fresh session so Synap, not short-term chat history, supplies the fact | |
| history = ChatHistory() | |
| history.add_system_message( | |
| "You are a helpful assistant with long-term memory. " | |
| "Use synap-search_memory to recall facts about the user. " | |
| "Use synap-store_memory to save important new facts." | |
| ) | |
| history.add_user_message("What do you know about my dietary restrictions?") | |
| response = await chat_service.get_chat_message_content( | |
| chat_history=history, settings=settings, kernel=kernel | |
| ) | |
| print(f"Assistant: {response}") |
There was a problem hiding this comment.
Pull request overview
Adds a Python concept sample demonstrating Synap-backed long-term memory for Semantic Kernel chat completion with automatic function calling.
Changes:
- Adds setup documentation for installing Synap dependencies and configuring API keys.
- Initializes Synap SDK, registers
SynapPlugin, and enablesFunctionChoiceBehavior.Auto(). - Demonstrates a two-turn store/recall memory flow.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| # Turn 1: teach | ||
| history.add_user_message( | ||
| "I'm a software engineer who's allergic to peanuts. Remember this." |
| kernel = Kernel() | ||
| kernel.add_service(OpenAIChatCompletion(ai_model_id="gpt-4o-mini")) | ||
| kernel.add_plugin( | ||
| SynapPlugin(sdk=sdk, user_id="demo-user-001", customer_id="demo-customer"), |
| @@ -0,0 +1,77 @@ | |||
| # Copyright (c) Microsoft. All rights reserved. | |||
|
|
|||
| """Sample: long-term memory via the Synap plugin. | |||
|
Hi @moonbox3 and @westey-m 👋 — would love a review when you have a moment! This adds Why this fits All real CI checks are green (CLA, Agent, Prepare, review, add_label, title prefix). The "Cleanup artifacts" failure is the standard post-job cleanup. Thanks! |
Summary
Adds
python/samples/concepts/memory/synap_memory.py— a sample showing how to give a Semantic Kernel agent persistent, cross-session memory via Synap.The sample registers
SynapPlugin(fromsynap-semantic-kernel) which exposes two kernel functions:synap-search_memory— semantic search over the user's stored memoriessynap-store_memory— persist explicit factsWith
FunctionChoiceBehavior.Auto(), the chat completion service can call these functions on demand to remember and recall facts about the user.PyPI: https://pypi.org/project/synap-semantic-kernel/
Open source: https://github.com/maximem-ai/maximem_synap_sdk/tree/main/packages/integrations/synap-semantic-kernel
Contribution Checklist