Table of Contents

Personalized Memory API Reference

This document is the API contract for FoundationaLLM personalized agent memory. It is intended for developers implementing the Memory MCP server and for anyone calling CoreAPI memory endpoints directly.

Audience: Memory MCP server developers, CoreAPI integrators
Controller: src/dotnet/CoreAPI/Controllers/MemoryController.cs
Models: src/dotnet/Common/Models/Memory/
Design plan: personalized-agent-memory-plan.md


Overview

Personalized memory stores durable markdown facts about a user (and optionally per agent). Memory is:

  • Owned by the authenticated user's UPN
  • Stored by FoundationaLLM (Cosmos / FoundationaLLM.Context resource provider, memories resource type)
  • Exposed only through CoreAPI convenience endpoints
  • Consumed by agents through an out-of-process Memory MCP server that forwards to CoreAPI

The Memory MCP server must not access Cosmos or enforce ownership itself. It validates MCP request shape, authenticates to CoreAPI, forwards identity, and maps MCP tools to the HTTP API below.

Agent (FoundationaLLMMCPClientTool)
        │  MCP tools: get_memory / append_memory / clear_memory
        │  HTTP headers include X-USER-IDENTITY = resolved user identity JSON
        ▼
Memory MCP server  (separate repo)
        │  HTTP to CoreAPI
        ▼
CoreAPI  /instances/{instanceId}/memory/*
        │
        ▼
FoundationaLLM.Context resource provider → Cosmos `Memories`

Base URL

https://{core-api-url}/instances/{instanceId}/memory
Variable Description Where to find
{core-api-url} Core API base URL App Config: FoundationaLLM:APIs:CoreAPI:APIUrl
{instanceId} FoundationaLLM instance GUID App Config: FoundationaLLM:Instance:Id

Authentication and identity

Memory endpoints accept the same dual auth model as other CoreAPI controllers:

Scheme How to send Notes
Microsoft Entra ID (JWT) Authorization: Bearer <token> Policy: Microsoft Entra ID standard
Agent access token Platform agent-access-token auth scheme Policy: FoundationaLLM agent access token

User identity for Memory MCP

When the agent invokes the Memory MCP server through FoundationaLLMMCPClientTool, the Management Portal tool configuration should include:

Header key Source Value
X-USER-IDENTITY New Value (or system context token) context://user_identity

At runtime the MCP client resolves context://user_identity to the signed-in user's identity JSON and sends it as X-USER-IDENTITY.

The Memory MCP server should:

  1. Accept X-USER-IDENTITY from the inbound MCP/HTTP request.
  2. Authenticate to CoreAPI with its configured service credential (Entra / managed identity / other deployment-approved pattern).
  3. Propagate the user identity into the CoreAPI call using the platform's trusted service-to-service identity pattern for the deployment.

Full on-behalf-of (OBO) token exchange across Orchestration → LangChain → MCP → CoreAPI is a later workstream. Until then, use the controlled trusted-forwarding pattern described in the memory plan.

Ownership is enforced in CoreAPI / the Memory resource provider against UnifiedUserIdentity.UPN. The MCP server must not invent or substitute a different user UPN.


Scopes

Scope Meaning Stored? agent_object_id / agentObjectId
user Cross-agent memory for the user Yes Not used
agent Memory for one agent + user Yes Required
combined User + current-agent memory assembled at read time No (read-only composition) Required for meaningful agent portion

Agent object IDs are FoundationaLLM resource paths, for example:

/instances/{instanceId}/providers/FoundationaLLM.Agent/agents/{agentName}

Endpoint summary

Method Path Purpose
GET /instances/{instanceId}/memory Read memory markdown JSON
POST /instances/{instanceId}/memory/append Append markdown to user or agent memory
POST /instances/{instanceId}/memory/clear Clear user or agent memory (confirm=true)
GET /instances/{instanceId}/memory/export Export raw markdown (text/markdown)
POST /instances/{instanceId}/memory/import Import markdown (append or replace)

Shared response model

Most JSON endpoints return MemoryResponse:

{
  "scope": "user",
  "upn": "user@contoso.com",
  "user_name": "user@contoso.com",
  "name": "Example User",
  "agent_object_id": null,
  "agent_name": null,
  "content_markdown": "# User memory\n\n- Prefers concise answers\n",
  "created_on": "2026-07-19T12:00:00+00:00",
  "updated_on": "2026-07-19T12:05:00+00:00"
}
Field Type Description
scope string user, agent, or combined
upn string Owning user principal name
user_name string? Username (often email)
name string? Display name
agent_object_id string? Set for agent-scoped documents
agent_name string? Agent display/name when known
content_markdown string Memory body (empty string when none)
created_on datetime? Profile created time
updated_on datetime? Profile last update time

Empty memory: GET returns 200 OK with content_markdown empty (or containing only content created by prior test/setup). Missing profiles are treated as empty, not 404.


GET /memory — read memory

GET /instances/{instanceId}/memory?scope={scope}&agentObjectId={agentObjectId}
Authorization: Bearer {token}
Accept: application/json

Query parameters

Name Required Description
scope No (default combined) user, agent, or combined
agentObjectId Required when scope is agent or when agent portion of combined is needed Agent resource object ID

ASP.NET query binding uses camelCase agentObjectId. JSON request bodies use snake_case agent_object_id.

Examples

User memory

curl -sS -X GET \
  "$CORE_API/instances/$INSTANCE_ID/memory?scope=user" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Agent memory

curl -sS -X GET \
  "$CORE_API/instances/$INSTANCE_ID/memory?scope=agent&agentObjectId=$AGENT_OBJECT_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

Combined memory

curl -sS -X GET \
  "$CORE_API/instances/$INSTANCE_ID/memory?scope=combined&agentObjectId=$AGENT_OBJECT_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"

combined concatenates non-empty user and agent markdown with blank lines between them. Response scope is combined.


POST /memory/append — append memory

POST /instances/{instanceId}/memory/append
Authorization: Bearer {token}
Content-Type: application/json

Request body (AppendMemoryRequest)

Field Type Required Description
scope string Yes user or agent (combined is invalid)
agent_object_id string Required for agent Agent object ID
agent_name string No Optional; CoreAPI can resolve from the agent resource
content_markdown string Yes Markdown to append (must be non-whitespace)
reason string No Provenance note included in the append heading
operation_id string No Associated completion/operation id
session_id string No Associated conversation/session id

Example

curl -sS -X POST \
  "$CORE_API/instances/$INSTANCE_ID/memory/append" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "user",
    "content_markdown": "- Prefers concise answers.",
    "reason": "User stated preference"
  }'

Behavior

  • Appends to the existing markdown document for the scope.
  • CoreAPI wraps the append with an automatic heading / provenance block (timestamp; optional reason).
  • Returns updated MemoryResponse.

POST /memory/clear — clear memory

POST /instances/{instanceId}/memory/clear
Authorization: Bearer {token}
Content-Type: application/json

Request body (ClearMemoryRequest)

Field Type Required Description
scope string Yes user or agent
agent_object_id string Required for agent Agent object ID
confirm boolean Yes Must be true or the API returns 400

Example

curl -sS -X POST \
  "$CORE_API/instances/$INSTANCE_ID/memory/clear" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "agent",
    "agent_object_id": "/instances/00000000-0000-0000-0000-000000000000/providers/FoundationaLLM.Agent/agents/benefits-assistant",
    "confirm": true
  }'

Behavior

  • Sets content_markdown to empty while retaining the memory profile metadata.
  • confirm: false (or omitted/false) → 400 Bad Request.

GET /memory/export — export markdown

GET /instances/{instanceId}/memory/export?scope={scope}&agentObjectId={agentObjectId}
Authorization: Bearer {token}
Accept: text/markdown
Name Required Description
scope Yes user, agent, or combined
agentObjectId Required for agent / agent portion of combined Agent object ID

Response: 200 OK with Content-Type: text/markdown and the markdown body (not wrapped in JSON).

curl -sS -X GET \
  "$CORE_API/instances/$INSTANCE_ID/memory/export?scope=user" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: text/markdown"

POST /memory/import — import markdown

POST /instances/{instanceId}/memory/import
Authorization: Bearer {token}
Content-Type: application/json

Request body (ImportMemoryRequest)

Field Type Required Description
scope string Yes user or agent
agent_object_id string Required for agent Agent object ID
content_markdown string Yes Markdown to import
mode string No (default append) append or replace

Example

curl -sS -X POST \
  "$CORE_API/instances/$INSTANCE_ID/memory/import" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "user",
    "mode": "replace",
    "content_markdown": "# User memory\n\n- Imported preference\n"
  }'

Behavior

mode Result
append Appends imported content under an import heading
replace Replaces the entire content_markdown with the provided body
anything else 400 Bad Request

Import/export are CoreAPI (and future Agent Portal) features. The agent-facing Memory MCP tools in v1 are get / append / clear only; MCP servers may optionally expose import later but are not required to.


Validation and error responses

Condition HTTP status
Missing agent_object_id / agentObjectId for scope=agent 400
clear with confirm not true 400
Invalid scope 400
Invalid import mode 400
Empty content_markdown on append/import 400 / argument exception
Caller cannot access the agent resource Agent RP error (typically 403/404)
Unauthenticated / unauthorized 401 / 403

Successful reads of empty memory return 200, not 404.


Memory MCP tool mapping

Implement these MCP tools in the Memory MCP server. Do not create separate tools for user vs agent memory — use a scope argument.

get_memory

MCP argument Type Required Default Maps to CoreAPI
scope string (user | agent | combined) Yes Often combined in tool config GET .../memory?scope=

CoreAPI call:

GET /instances/{instanceId}/memory?scope={scope}&agentObjectId={currentAgentObjectId}

Return to the agent: markdown text (from content_markdown, or the export body if you prefer).

append_memory

MCP argument Type Required Maps to CoreAPI
scope string (user | agent) Yes AppendMemoryRequest.scope
memory string (markdown) Yes AppendMemoryRequest.content_markdown
reason string No AppendMemoryRequest.reason

CoreAPI call:

POST /instances/{instanceId}/memory/append
Content-Type: application/json

{
  "scope": "{scope}",
  "agent_object_id": "{currentAgentObjectId}",   // when scope=agent
  "content_markdown": "{memory}",
  "reason": "{reason}"
}

clear_memory

MCP argument Type Required Default Maps to CoreAPI
scope string (user | agent) Yes — ClearMemoryRequest.scope
confirm boolean Yes false in tool config ClearMemoryRequest.confirm

CoreAPI call:

POST /instances/{instanceId}/memory/clear
Content-Type: application/json

{
  "scope": "{scope}",
  "agent_object_id": "{currentAgentObjectId}",   // when scope=agent
  "confirm": true
}

Only call CoreAPI when confirm is true. Otherwise return a clear MCP-level validation error to the agent.

Supplying agent_object_id

Agent-facing MCP tool schemas expose scope (and content/confirm), not agent_object_id, to the LLM. For scope=agent or scope=combined, the Memory MCP server must supply the current agent object ID when calling CoreAPI.

Recommended approaches (pick one and document it in the MCP server repo):

  1. Server configuration — bind each MCP deployment/route to a known agent object ID, or
  2. Invocation context — accept agent object ID from a trusted inbound header / metadata established by the platform when the tool is invoked, or
  3. Explicit MCP argument — optionally accept agent_object_id for advanced clients (not required for the default FoundationaLLM Tools Experience wrappers).

Never invent an agent object ID from the user prompt.


MCP server responsibilities (checklist)

Do

  • [ ] Expose MCP tools get_memory, append_memory, clear_memory
  • [ ] Validate MCP argument shapes before calling CoreAPI
  • [ ] Call CoreAPI paths documented above
  • [ ] Forward / honor X-USER-IDENTITY for the signed-in user
  • [ ] Authenticate to CoreAPI with the deployment's service credential
  • [ ] Return markdown (or structured tool results containing markdown) to the agent
  • [ ] Require confirm=true before calling clear

Do not

  • [ ] Store memory in the MCP server
  • [ ] Access Cosmos DB directly
  • [ ] Implement vector search or semantic deduplication
  • [ ] Implement ChatGPT/Claude/Gemini-specific import parsers
  • [ ] Bypass UPN ownership (always use the authenticated / forwarded user identity)

Management Portal configuration (FoundationaLLM side)

In Management Portal Tools Experience, configure three MCP Client tools against the Memory MCP server URL:

  1. Add header: Key X-USER-IDENTITY, Source New Value, Value context://user_identity
  2. Leave Intelligent Execute unchecked
  3. Use List Tools → select the memory tool → Configure
  4. Save the tool, then save the agent

See verification plan: V018-management-portal-memory-mcp-config.md
MCP client header docs: mcp-client.md


Functional verification

CoreAPI behavior is covered by:

Run V017 against a deployed or local CoreAPI with Entra auth before integrating the MCP server end-to-end.


Document Purpose
personalized-agent-memory-plan.md Full design, storage model, phases
Core API reference (SDKs) General CoreAPI auth and patterns
mcp-client.md context:// header tokens
Agent access tokens Alternate CoreAPI auth