* Add agent-framework-azure-cosmos-memory context provider (draft) Introduces CosmosMemoryContextProvider, a ContextProvider that wraps the azure-cosmos-agent-memory toolkit to give agents long-term, Cosmos DB-backed memory (fact/procedural recall + user summaries). Includes package scaffolding, unit tests (mocked client), live Azure integration tests (marked), samples, README, and AGENTS.md. Draft: uv.lock is intentionally left unchanged. This package depends on azure-cosmos-agent-memory (requires Python >=3.11), which is unsatisfiable against the workspace's current >=3.10 floor, so adding it to the shared lock requires a workspace decision (raise floor to 3.11 or exclude from workspace). Test coverage to be expanded. * ci: exclude azure-cosmos-memory from uv workspace resolution The package depends on azure-cosmos-agent-memory which requires Python >=3.11 and a prompty pre-release (>=2.0.0a9). Both are unsatisfiable against the workspace's >=3.10 floor and pre-release policy, causing uv sync to fail in every Python CI job. Exclude the package from the shared workspace so it is resolved and tested as a standalone package. * ci: fix code-quality failures for azure-cosmos-memory - Strip trailing whitespace from package files (pre-commit trailing-whitespace hook) - Exclude the package README from markdown-code-lint: the package is excluded from the uv workspace, so its README snippets import a module that is not installed in the workspace env and Pyright cannot resolve it * Exclude azure-cosmos-memory README from markdown-code-lint task * Address PR review comments on cosmos-memory context provider - Wire credential into Cosmos and AI Foundry clients; let toolkit own DefaultAzureCredential when none supplied (remove dead import). - Honor auto_extract=False by zeroing extraction/summary cadence thresholds. - Skip whitespace-only conversation turns and store stripped content. - Show confidence 0.0 and coerce confidence to float in _format_memories. - Register both 'integration' and 'azure' pytest markers accurately. - Fix duplicated install block in README. - Update and extend unit tests for new credential wiring and fixes. * Include azure-cosmos-memory in the uv workspace Follow the github_copilot pattern for a package with a Python 3.11-only dependency: lower requires-python to >=3.10 and gate azure-cosmos-agent-memory behind a python_version >= '3.11' marker. Add a direct, gated prompty pre-release dependency so the workspace's if-necessary-or-explicit prerelease policy permits the toolkit's transitive prompty requirement. Guard the test modules with pytest.importorskip so the 3.10 CI leg skips cleanly. Remove the workspace exclude and the markdown-code-lint exclude, and regenerate uv.lock. * Address review feedback on cosmos-memory provider Rename provider parameters to match Agent Framework conventions: foundry_endpoint (was ai_foundry_endpoint) and embedding_model/chat_model (were *_deployment_name). Move DEFAULT_* to module-level constants, type memory_types as a Literal, use DEFAULT_CONTEXT_PROMPT as the default value, and add ProcessorConfig/CosmosMemorySettings TypedDicts. Resolve connection settings via agent_framework load_settings with required-field validation, replacing the manual getenv/raise blocks. Scope user_id/thread_id to the provider state and drop the unpreventable first-turn warning. Rewrite the samples around Agent (not raw SessionContext), provider-scoped state, and session-id threading; use PEP 723 inline dependencies instead of a samples dependency group; use a plain input() loop; remove the dead custom processor stub. Update README/AGENTS for the renamed parameters and env vars. Add a samples ruff per-file-ignores entry now that the package is linted in CI. * Add emulator-backed vector search integration test Bump azure-cosmos-agent-memory to >=0.2.0b2 (adds the embeddings/chat client injection seam) and add tests/test_emulator.py: an integration (not azure) suite that exercises real Cosmos vector search with a quantizedFlat index against a local Cosmos DB emulator, using deterministic in-memory fakes for embeddings and chat so no Azure AI Foundry account or LLM is required. To run on a stock emulator the fixture strips the toolkit's full-text index (the provider only does pure vector search) and requests provisioned autoscale throughput instead of serverless. The suite skips cleanly when no emulator is reachable. * Fix CI typing and package checks for azure-cosmos-memory The package recently joined the uv workspace, so its source and tests are now covered by the Test Typing Checks and Package Checks gates for the first time. tests: rename stale constructor kwargs to the current provider API (foundry_endpoint/embedding_model/chat_model); use a typed _STUB_AGENT for the unused agent param so pyright/pyrefly/ty/zuban all accept it; make processor_config values ints; assert non-None memory_client in the emulator tests. source: relax reportUnknown*/reportOptional* for this package only (the toolkit ships no py.typed; mirrors the hosting-telegram precedent); decouple the conditional toolkit import from the annotation type; use settings.get(); fix memory_types list invariance; drop a redundant None guard; read role via getattr. * Apply pyupgrade: single-arg AsyncGenerator in test_integration * Make Cosmos memory extraction drain transparently on provider exit The provider now drains in-flight background memory extraction in __aexit__, so applications no longer need to call flush() in their own control flow; the client's close() would otherwise cancel pending extraction tasks. flush() is hardened against clients that expose no usable background-task registry. sample: interactive_chat reads input via asyncio.to_thread so the event loop stays free and background extraction runs during the session; removes the manual flush now that the provider drains on exit. tests: add explicit transparent-extraction integration tests (emulator: after_run schedules extraction and __aexit__ drains it; live Azure: a fact is extracted and recalled in a later session with no manual flush). Emulator tests reuse a single fixed database to avoid exhausting the emulator's partition budget across runs. * Add custom extraction-prompt seam and sample to cosmos-memory provider Adds a prompts_dir option to CosmosMemoryContextProvider that points the Agent Memory Toolkit pipeline at a caller-supplied directory of Prompty templates, so callers can override extract_memories.prompty to control what the extraction LLM produces. The toolkit exposes no public prompts-directory seam, so the provider contains the one internal touch (swapping the pipeline's template loader after the store connects); applies to both provider-built and supplied clients. sample: interactive_chat_custom_extraction.py - the interactive chat wired with a custom coding-assistant extraction rubric. It derives a complete prompts directory at runtime (copies the bundled templates and augments extract_memories.prompty) so it stays schema-compatible with the installed toolkit. tests: unit tests assert the provider redirects the pipeline loader only when prompts_dir is set; an emulator integration test proves end to end that a unique marker in a custom extract_memories.prompty reaches the extraction LLM call. * docs: document prompts_dir custom-extraction seam in cosmos-memory README Replaces the stale, non-functional CustomMemoryProcessor snippet with the working prompts_dir approach, lists the new interactive_chat_custom_extraction.py sample, and corrects the interactive-sample feature list. * Address review: rename _new_session, drop defensive toolkit import guard Sample (comment): rename _new_thread to _new_session in both interactive samples (a new session is the new thread). Provider (comment): replace the _memory_toolkit_available flag + __init__ ImportError guard with a plain guarded import that re-raises a clear ImportError, matching the github_copilot package's pattern for its 3.11-only SDK. Kept requires-python >=3.10 (bumping this one workspace member to 3.11 would force the entire uv workspace lock floor to 3.11). Tests now run importorskip before importing the package, mirroring github_copilot. * Pass cadence via cadence_thresholds instead of mutating os.environ * Mark package alpha and drop private naming in samples * Require Python 3.11 and inject user summary as untrusted context * CI: exclude azure-cosmos-memory from uv sync on Python 3.10 * Re-trigger CI (flaky external link check) * Require chat/embedding models instead of silent defaults * Fix pyright: narrow resolved chat/embedding models to str --------- Co-authored-by: Theo van Kraay <thvankra@microsoft.com>
18 KiB
Get Started with Microsoft Agent Framework Azure Cosmos DB Memory
Please install this package via pip:
pip install agent-framework-azure-cosmos-memory --pre
Azure Cosmos DB Memory Context Provider
The Azure Cosmos DB Memory integration provides CosmosMemoryContextProvider for long-term semantic memory storage using the Azure Cosmos DB Agent Memory Toolkit.
This context provider enables:
- Semantic memory retrieval - Facts, procedural knowledge, and episodic memories
- Automatic memory extraction - Conversation turns are processed to extract structured knowledge
- User profile consolidation - Cross-thread user profiles with preferences and facts
- Memory reconciliation - Deduplication and contradiction resolution
Basic Usage Example
from azure.identity.aio import DefaultAzureCredential
from agent_framework.foundry import FoundryChatClient
from agent_framework_azure_cosmos_memory import CosmosMemoryContextProvider
# A single AI Foundry endpoint powers both memory and the chat agent
foundry_endpoint = "https://<project>.services.ai.azure.com"
# Create the memory provider
memory_provider = CosmosMemoryContextProvider(
cosmos_endpoint="https://<account>.documents.azure.com:443/",
cosmos_database="ai_memory",
foundry_endpoint=foundry_endpoint,
credential=DefaultAzureCredential(),
)
# Create an agent with memory - reuses the same AI Foundry endpoint
agent = FoundryChatClient(
project_endpoint=foundry_endpoint,
model="gpt-4o-mini",
credential=DefaultAzureCredential(),
).as_agent(
instructions="You are a helpful assistant with long-term memory.",
context_providers=[memory_provider]
)
# Use the agent - memories are automatically stored and retrieved
session = agent.create_session()
await agent.run("I love hiking and prefer vegetarian food.", session=session)
await agent.run("What do you know about my preferences?", session=session)
Authentication Options
The provider supports the same authentication modes as other Azure integrations:
- Managed identity / RBAC (recommended): Pass
DefaultAzureCredential() - Connection string: Set environment variables
- Environment variables:
COSMOS_ENDPOINT,COSMOS_DATABASE,FOUNDRY_ENDPOINT
Development Setup
To avoid dependency conflicts with your system Python, it's recommended to use a virtual environment:
Option 1: Using venv (Built-in, Cross-Platform)
Bash/Linux/macOS:
# Navigate to the package directory
cd python/packages/azure-cosmos-memory
# Create virtual environment
python3 -m venv .venv
# Activate virtual environment
source .venv/bin/activate
# Install package in development mode with all dependencies
pip install -e ".[dev]"
# OPTIONAL: sample dependencies (needed for the samples). The samples also declare these
# inline via PEP 723, so you can instead run them with `uv run samples/<name>.py`.
pip install agent-framework-foundry python-dotenv
# Verify installation
python -c "from agent_framework_azure_cosmos_memory import CosmosMemoryContextProvider; print('✓ Package installed')"
PowerShell:
# Navigate to the package directory
cd python\packages\azure-cosmos-memory
# Create virtual environment
python -m venv .venv
# Activate virtual environment
.\.venv\Scripts\Activate.ps1
# If you get execution policy errors, run first:
# Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Install package in development mode with all dependencies
pip install -e ".[dev]"
# OPTIONAL: sample dependencies (needed for the samples). The samples also declare these
# inline via PEP 723, so you can instead run them with `uv run samples/<name>.py`.
pip install agent-framework-foundry python-dotenv
# Verify installation
python -c "from agent_framework_azure_cosmos_memory import CosmosMemoryContextProvider; print('✓ Package installed')"
To deactivate the virtual environment:
deactivate # Works on all platforms
Option 2: Using uv (Fast Alternative)
If you have uv installed:
# Sync all dependencies including dev dependencies
uv sync --prerelease=allow
# Run samples with uv (it manages the environment for you)
uv run python samples/interactive_chat.py
How to Run the Samples
Important: Before running samples, complete the Development Setup above to create a virtual environment and install the package.
This package includes three samples demonstrating different usage patterns:
1. Basic Usage (samples/basic_usage.py) - API Demonstration
This sample shows the raw ContextProvider API by manually calling before_run() and after_run(). It demonstrates:
- How the provider searches for memories
- How memories are injected into context
- How conversations are stored
- Not a real agent - just shows the API mechanics
Run it:
Ensure your virtual environment is activated, then:
# Bash/Linux/macOS
export COSMOS_ENDPOINT="https://<your-account>.documents.azure.com:443/"
export FOUNDRY_ENDPOINT="https://<your-project>.services.ai.azure.com"
python samples/basic_usage.py
# PowerShell
$env:COSMOS_ENDPOINT="https://<your-account>.documents.azure.com:443/"
$env:FOUNDRY_ENDPOINT="https://<your-project>.services.ai.azure.com"
python samples/basic_usage.py
2. Interactive Chat (samples/interactive_chat.py) - Real Agent Integration
This sample shows real-world usage with Agent Framework. It demonstrates:
- ✅ Full Agent Framework integration - actual chatbot you can interact with
- ✅ Multi-turn conversations - see memories persist across sessions
- ✅ User/thread scoping - test memory isolation
- ✅ Interactive CLI - chat with the agent, switch users, start new threads
Prerequisites:
-
Complete Development Setup - Create a venv and install the package with test dependencies:
pip install -e ".[dev]"The samples declare their own dependencies via PEP 723 inline metadata, so you can also just run them with
uv run samples/interactive_chat.py. To install the sample dependencies manually into your venv:pip install agent-framework-foundry python-dotenv -
Azure Resources - You'll need:
- An Azure Cosmos DB account with a database (e.g.,
ai_memory) - An Azure AI Foundry project with embedding and chat deployments
- The following deployments configured in AI Foundry:
text-embedding-3-large(or your preferred embedding model)gpt-4o-mini(or your preferred chat model)
- An Azure Cosmos DB account with a database (e.g.,
-
Configure environment variables - Set these in your activated virtual environment.
Note: A single
FOUNDRY_ENDPOINTpowers everything:- The memory provider uses it internally for embeddings + memory extraction.
- The chat agent you talk to uses it via
FoundryChatClient.
Authentication is via
DefaultAzureCredential(i.e.az login), so no API key is required.Bash/Linux/macOS:
# Cosmos DB export COSMOS_ENDPOINT="https://<your-account>.documents.azure.com:443/" export COSMOS_DATABASE="ai_memory" # AI Foundry - used by BOTH the memory provider and the chat agent export FOUNDRY_ENDPOINT="https://<your-project>.services.ai.azure.com" export EMBEDDING_MODEL="text-embedding-3-large" export CHAT_MODEL="gpt-4o-mini"PowerShell:
# Cosmos DB $env:COSMOS_ENDPOINT="https://<your-account>.documents.azure.com:443/" $env:COSMOS_DATABASE="ai_memory" # AI Foundry - used by BOTH the memory provider and the chat agent $env:FOUNDRY_ENDPOINT="https://<your-project>.services.ai.azure.com" $env:EMBEDDING_MODEL="text-embedding-3-large" $env:CHAT_MODEL="gpt-4o-mini" -
Ensure Azure authentication - The samples use
DefaultAzureCredential, which tries:- Environment variables (service principal)
- Managed identity (if running in Azure)
- Azure CLI (
az login) - Interactive browser login (fallback)
For local development, the easiest option is:
az login -
Run the sample (ensure your virtual environment is activated):
Bash/Linux/macOS:
# Make sure venv is activated (you should see (.venv) in your prompt) python samples/interactive_chat.pyPowerShell:
# Make sure venv is activated (you should see (.venv) in your prompt) python samples/interactive_chat.py
Interactive sample features:
- Chat naturally and tell the assistant your preferences
- Use
/newto start a new thread (memories persist across threads) - Use
/user <id>to switch users (test memory isolation) - Use
/quitto exit
The interactive sample demonstrates:
- Real agent with memory integration
- Multi-turn conversations with memory persisting across threads
- Multi-user and multi-thread memory scoping
3. Interactive Chat with Custom Extraction (samples/interactive_chat_custom_extraction.py)
The same interactive chat as above, but wired with a custom memory-extraction prompt so you can control what the pipeline extracts. It uses a coding-assistant rubric that classifies architectural and technical decisions as durable facts. See Custom Memory Extraction Rubric below for how the prompts_dir seam works.
Run it the same way as the interactive chat (same prerequisites and environment variables):
python samples/interactive_chat_custom_extraction.py
Custom Memory Extraction Rubric
You can control both how often memories are extracted and what gets extracted.
Control extraction cadence (processor_config)
processor_config sets how many turns pass between each pipeline step. The provider forwards these
to the toolkit client via its cadence_thresholds argument (no global environment mutation); keys you
omit fall back to the toolkit's environment/defaults. This applies only when the provider builds the
client, so pass processor_config together with the connection arguments rather than a pre-built
memory_client:
memory_provider = CosmosMemoryContextProvider(
cosmos_endpoint=...,
foundry_endpoint=...,
processor_config={
"FACT_EXTRACTION_EVERY_N": 1, # Extract after every turn
"DEDUP_EVERY_N": 3, # Deduplicate every 3 extractions
"USER_SUMMARY_EVERY_N": 5, # Update user profile every 5 turns
"THREAD_SUMMARY_EVERY_N": 10, # Summarize thread every 10 turns
},
)
Customize the extraction prompt (prompts_dir)
To change what the LLM extracts and how it classifies memories, supply your own Prompty templates via prompts_dir. When set, the toolkit's extraction and summarization steps read their templates (including extract_memories.prompty) from that directory instead of the bundled defaults:
memory_provider = CosmosMemoryContextProvider(
cosmos_endpoint=...,
foundry_endpoint=...,
prompts_dir="./my_prompts",
)
The directory must contain the complete template set, since the loader resolves each template by name with no fallback to the bundled copies. The simplest way to customize just the extraction rubric is to copy the toolkit's bundled templates and edit extract_memories.prompty (keeping its inputs and JSON output schema intact). See samples/interactive_chat_custom_extraction.py for a working example that builds this directory at runtime, so the custom prompt stays compatible with the installed toolkit's schema.
Configuration
memory_provider = CosmosMemoryContextProvider(
source_id="cosmos_memory", # Provider identifier
cosmos_endpoint="https://...", # Cosmos DB endpoint
cosmos_database="ai_memory", # Database name
foundry_endpoint="https://...", # AI Foundry endpoint
credential=DefaultAzureCredential(), # Azure credential
# Memory retrieval options
top_k=5, # Number of memories to retrieve
min_confidence=0.7, # Minimum confidence score (0.0-1.0)
memory_types=["fact", "procedural"], # Types to retrieve
# Processing options
auto_extract=True, # Auto-extract memories after runs
processor_config={ # Optional processor settings
"FACT_EXTRACTION_EVERY_N": 1, # Extract facts every N turns
"DEDUP_EVERY_N": 5, # Deduplicate every N extractions
}
)
Memory Types
The provider retrieves four types of memories:
| Type | Description | Default TTL |
|---|---|---|
| fact | Declarative knowledge ("user prefers dark mode") | None |
| procedural | Behavioral rules ("always confirm before deleting") | None |
| episodic | Past experiences with context and outcomes | 90 days |
| unclassified | Memories that couldn't be confidently classified | None |
Each memory has a confidence score (0.0-1.0). Use min_confidence to filter low-quality extractions.
Processing Pipeline
The memory toolkit automatically:
- Stores conversation turns - Raw messages saved to Cosmos DB
- Extracts memories - LLM extracts facts, rules, and experiences
- Generates summaries - Thread and user-level summaries
- Reconciles duplicates - Merges similar memories and resolves contradictions
Processing can run:
- In-process (default) - Zero infrastructure, suitable for prototypes and low TPS
- Azure Functions - Scalable processing via Cosmos DB change feed
Working with Multiple Providers
Combine with other context providers for comprehensive memory:
from agent_framework import InMemoryHistoryProvider
from agent_framework_azure_cosmos import CosmosHistoryProvider
from agent_framework_azure_cosmos_memory import CosmosMemoryContextProvider
agent = client.as_agent(
context_providers=[
# Short-term: recent conversation
InMemoryHistoryProvider("recent"),
# Mid-term: persistent conversation history
CosmosHistoryProvider(
endpoint=cosmos_endpoint,
credential=credential,
database_name="agent-framework",
container_name="chat-history",
),
# Long-term: semantic memory with facts and profiles
CosmosMemoryContextProvider(
cosmos_endpoint=cosmos_endpoint,
foundry_endpoint=foundry_endpoint,
credential=credential,
),
]
)
User and Thread Scoping
Memories are scoped by user_id and thread_id:
session = agent.create_session()
# Set user_id and thread_id in the provider-scoped state (keyed by the provider's source_id)
scoped = session.state.setdefault("cosmos_memory", {})
scoped["user_id"] = "user-123"
scoped["thread_id"] = "thread-456"
await agent.run("Remember that I'm allergic to peanuts.", session=session)
If not provided, the provider uses session.session_id as both user and thread identifiers.
Advanced: Custom Processing
For fine-grained control over memory processing:
from azure.cosmos.agent_memory.aio import AsyncCosmosMemoryClient
# Create a custom memory client. To disable automatic extraction, zero the cadence thresholds
# on the client you build - the provider cannot reconfigure a client you pass in, so supplying
# a memory_client together with auto_extract=False or processor_config raises ValueError.
memory_client = AsyncCosmosMemoryClient(
cosmos_endpoint=cosmos_endpoint,
cosmos_database="ai_memory",
ai_foundry_endpoint=ai_foundry_endpoint,
use_default_credential=True,
cadence_thresholds={
"FACT_EXTRACTION_EVERY_N": 0,
"THREAD_SUMMARY_EVERY_N": 0,
"USER_SUMMARY_EVERY_N": 0,
},
)
# Pass to the provider
memory_provider = CosmosMemoryContextProvider(
memory_client=memory_client,
)
# Manually trigger processing when needed
await memory_client.process_now(user_id="user-123", thread_id="thread-456")
To let the provider disable extraction for you, omit
memory_clientand passauto_extract=Falsewith the connection arguments instead - the provider then builds the client with the extraction and summary steps zeroed.
Environment Variables
All configuration can be provided via environment variables:
Using a .env file (cross-platform, recommended):
COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
COSMOS_DATABASE=ai_memory
FOUNDRY_ENDPOINT=https://<project>.services.ai.azure.com
EMBEDDING_MODEL=text-embedding-3-large
CHAT_MODEL=gpt-4o-mini
# Optional: Processing configuration
FACT_EXTRACTION_EVERY_N=1
DEDUP_EVERY_N=5
THREAD_SUMMARY_EVERY_N=10
USER_SUMMARY_EVERY_N=20
Or set in your shell session:
Bash/Linux/macOS:
export COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
export COSMOS_DATABASE=ai_memory
export FOUNDRY_ENDPOINT=https://<project>.services.ai.azure.com
PowerShell:
$env:COSMOS_ENDPOINT="https://<account>.documents.azure.com:443/"
$env:COSMOS_DATABASE="ai_memory"
$env:FOUNDRY_ENDPOINT="https://<project>.services.ai.azure.com"
See Also
- Azure Cosmos DB Agent Memory Toolkit
- Agent Framework Context Providers
- agent-framework-azure-cosmos - For basic history and checkpoint storage