> ## Documentation Index
> Fetch the complete documentation index at: https://docs.maximem.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Microsoft Agent Framework

> Context and history providers that give Microsoft Agent Framework agents persistent, per-user memory.

Add persistent memory to a Microsoft Agent Framework (MAF) agent through two providers: a context provider that injects semantic memory before each turn and records turns after, and a history provider that handles verbatim conversation persistence.

<Note>
  Requires Python 3.11+.
</Note>

## Overview

This guide shows how to add Synap to a MAF application to build agents that:

* Inject the most relevant memories as a system message at the start of each turn
* Record completed turns back to Synap for future retrieval
* Persist and replay the full verbatim conversation history when full transcript visibility is needed

The Synap MAF integration ships two providers, each of which plugs into MAF's `context_providers` slot and handles one axis of memory.

| Class                  | Role     | Purpose                                                         |
| ---------------------- | -------- | --------------------------------------------------------------- |
| `SynapContextProvider` | Semantic | Injects relevant memories before each turn; records turns after |
| `SynapHistoryProvider` | Verbatim | Persists and reloads the full conversation transcript           |

## Setup

Install the package alongside MAF:

<CodeGroup>
  ```bash pip theme={null}
  pip install maximem-synap-microsoft-agent azure-ai-agents
  ```

  ```bash uv theme={null}
  uv add maximem-synap-microsoft-agent azure-ai-agents
  # pip-compatible (existing venv): uv pip install maximem-synap-microsoft-agent azure-ai-agents
  ```
</CodeGroup>

<Note>
  The pip package is `maximem-synap-microsoft-agent`, but the import drops the `maximem-` prefix and uses underscores: `from synap_microsoft_agent import ...`.
</Note>

Configure your API key. Generate one from the [Synap Dashboard](https://synap.maximem.ai).

```bash .env theme={null}
SYNAP_API_KEY=synap_your_key_here
AZURE_AI_ENDPOINT=your-endpoint
```

Initialize the SDK once at application startup:

```python theme={null}
from maximem_synap import MaximemSynapSDK

sdk = MaximemSynapSDK()
await sdk.initialize()
```

See [SDK Initialization](/sdk/initialization) for the full lifecycle and configuration options.

## Basic integration

The smallest useful integration wires `SynapContextProvider` into a MAF agent. Each turn now starts with the most relevant Synap memories injected as a system message, and ends with the completed turn ingested back into Synap:

```python theme={null}
# pip install maximem-synap-microsoft-agent azure-ai-agents
import os
from maximem_synap import MaximemSynapSDK
from azure.ai.agents import AgentsClient
from synap_microsoft_agent import SynapContextProvider

sdk = MaximemSynapSDK()
await sdk.initialize()

client = AgentsClient(endpoint=os.environ["AZURE_AI_ENDPOINT"])

agent = client.as_agent(
    context_providers=[
        SynapContextProvider(
            sdk=sdk,
            user_id="alice",
            customer_id="acme",   # optional, required for B2B instances
            max_context_results=6,
        ),
    ],
)

response = await agent.run("What were the outcomes from my last meeting?")
```

The provider handles both the read (context injection) and the write (turn ingestion). **Reads degrade gracefully** on Synap outages: empty context is injected, the error is logged, and the agent still answers. **Writes surface failures explicitly** so silent data loss is impossible.

For verbatim transcript persistence on top of semantic memory, layer in `SynapHistoryProvider`; see below.

***

## Core concepts

### Context provider

`SynapContextProvider` runs on MAF's `before_turn` and `after_turn` hooks:

1. **Before each turn**: fetches relevant memories for the incoming message and appends them as a `system` context message.
2. **After each turn**: ingests the full user/assistant exchange back into Synap.

```python theme={null}
from synap_microsoft_agent import SynapContextProvider

ctx = SynapContextProvider(
    sdk=sdk,
    user_id="alice",
    customer_id="acme",
    max_context_results=6,
)
```

This is the standard provider for most agents: it gives the model awareness of long-term context without requiring you to manage the transcript.

### History provider

`SynapHistoryProvider` handles the verbatim conversation transcript. Use it when the model needs to see the full prior message history (not just semantic snippets):

```python theme={null}
import uuid
from synap_microsoft_agent import SynapHistoryProvider

# conversation_id (and every other id) must be a valid UUID.
hist = SynapHistoryProvider(
    sdk=sdk,
    user_id="alice",
    conversation_id=str(uuid.uuid4()),
)
```

The provider exposes two methods that MAF calls automatically:

| Method                      | Behavior                                                              |
| --------------------------- | --------------------------------------------------------------------- |
| `load(thread_id)`           | Fetches prior messages from Synap and restores them to the MAF thread |
| `save(thread_id, messages)` | Writes new messages to Synap after each turn                          |

`SynapHistoryProvider` is orthogonal to `SynapContextProvider`: one stores semantic memory, the other stores the literal transcript. Most production agents use both.

***

## Complete example: agent with both memory axes

The pattern below combines the two providers so the agent gets both semantic context and full transcript replay:

```python theme={null}
import os
import uuid
from azure.ai.agents import AgentsClient
from synap_microsoft_agent import SynapContextProvider, SynapHistoryProvider


def build_agent(sdk, client: AgentsClient, user_id: str, conversation_id: str, customer_id: str | None = None):
    return client.as_agent(
        context_providers=[
            SynapContextProvider(
                sdk=sdk,
                user_id=user_id,
                customer_id=customer_id,
                max_context_results=6,
            ),
            SynapHistoryProvider(
                sdk=sdk,
                user_id=user_id,
                conversation_id=conversation_id,
            ),
        ],
    )


# Usage
client = AgentsClient(endpoint=os.environ["AZURE_AI_ENDPOINT"])
agent = build_agent(sdk, client, user_id="alice", conversation_id=str(uuid.uuid4()), customer_id="acme")

response = await agent.run("What did we agree on for the Q2 roadmap?")
# Context provider injects semantic memory; history provider gives the model the full conversation transcript.
```

Three things to notice in this pattern:

1. **The two providers serve different needs.** Semantic memory tells the agent *what's relevant*; verbatim history tells it *what was said*.
2. **`conversation_id` only matters to the history provider.** The context provider pulls user-level memories regardless of thread.
3. **Failure semantics split.** Reads (context fetch, history load) degrade gracefully; writes (turn ingest, history save) raise on failure so silent data loss is impossible.

***

## Advanced patterns

### Multi-tenant scoping

Both providers accept the standard scoping triple: `user_id` (required), optional `customer_id`, optional `conversation_id`. `customer_id` is required on B2B Synap instances and ignored on single-tenant ones. See [Memory Scopes](/concepts/memory-scopes).

```python theme={null}
ctx = SynapContextProvider(sdk=sdk, user_id="alice", customer_id="acme")
```

For multi-tenant services, build providers per request rather than caching them globally; each agent should have its scope baked in.

### Choosing between context-only and history-only

Some agents don't need both:

* **Context only**: concise agents that benefit from semantic recall but where full transcripts would blow the context budget.
* **History only**: short-lived agents (single session) that need verbatim replay but no long-term memory pool.
* **Both**: production agents that maintain ongoing relationships with users across many sessions.

### Failure semantics

The integration follows the Synap-wide contract:

* **`SynapContextProvider` reads degrade gracefully**: empty context is injected and the error logged.
* **`SynapContextProvider` writes surface failures**: turn ingestion raises `SynapIntegrationError` so callers know persistence failed.
* **`SynapHistoryProvider.load` degrades gracefully**: returns an empty message list and logs the error.
* **`SynapHistoryProvider.save` surfaces failures**: raises `SynapIntegrationError`.

This is by design: read failures shouldn't break a user-facing turn, but silent write failures would corrupt the memory pool.

***

## Going further

* [Patterns overview](/patterns/overview): reusable memory patterns across frameworks.
* [Cookbook overview](/cookbook/overview): end-to-end worked examples.

***

## Next steps

<CardGroup cols={2}>
  <Card title="Semantic Kernel" icon="microsoft" href="/integrations/semantic-kernel">
    Kernel plugin for Microsoft Semantic Kernel.
  </Card>

  <Card title="NeMo Agent Toolkit" icon="microchip" href="/integrations/nemo-agent-toolkit">
    `MemoryEditor` for NVIDIA NeMo workflows.
  </Card>

  <Card title="Context Fetch" icon="search" href="/sdk/context-fetch">
    The retrieval API behind `SynapContextProvider`: modes, scopes, and response shapes.
  </Card>

  <Card title="Memory Scopes" icon="layer-group" href="/concepts/memory-scopes">
    How `user_id`, `customer_id`, and `conversation_id` interact across reads.
  </Card>
</CardGroup>
