Skip to content

feat(agents): provision Foundry memory stores during deploy#8852

Open
glharper wants to merge 4 commits into
mainfrom
glharper/8742-foundry-memory-support
Open

feat(agents): provision Foundry memory stores during deploy#8852
glharper wants to merge 4 commits into
mainfrom
glharper/8742-foundry-memory-support

Conversation

@glharper

Copy link
Copy Markdown
Member

Summary

Adds support for Foundry memory in the azure.ai.agents extension by provisioning Foundry memory stores as part of the hosted-agent deploy flow, mirroring the reference provision_memory_store.py sample.

Users declare one or more memory stores under the agent service config in azure.yaml, and azd creates them (idempotent create-if-not-exists) in the Foundry project before deploying the agent. Memory stores back the agent's memory_search tool, letting agents retain context across sessions.

Fixes #8742

What changed

  • FoundryMemoryStoreClient (internal/pkg/azure/foundry_memory_store_client.go): new data-plane client with CreateMemoryStore, GetMemoryStore, and an idempotent EnsureMemoryStore (create-if-missing, leave existing stores unchanged). Targets POST/GET {projectEndpoint}/memory_stores with API version 2025-11-15-preview, matching the official REST contract. Follows the existing FoundryToolboxClient pattern.
  • Config (internal/project/config.go): new memoryStores section on the agent service-target config (name, description, chatModel, embeddingModel, and optional extraction/retention options).
  • Deploy wiring (internal/project/service_target_agent.go): provisionMemoryStores is invoked from Deploy after config/env load and before the agent is created. Validates required fields and reports per-store progress and created/already-exists status.
  • Schema (schemas/azure.ai.agent.json): memoryStores array + MemoryStore definition.
  • Errors (internal/exterrors/codes.go): CodeInvalidMemoryStore, OpCreateMemoryStore.
  • Tests for the client (request shape, name escaping, ensure get/create/propagate paths), config round-trip, and provisioning validation. CHANGELOG entry.

Example azure.yaml config

services:
  my-agent:
    config:
      memoryStores:
        - name: support_memory
          description: Memory for the support agent
          chatModel: gpt-5.2              # model deployment name in the project
          embeddingModel: text-embedding-3-small
          options:
            userProfileEnabled: true
            chatSummaryEnabled: false
            userProfileDetails: "Avoid sensitive data such as age, financials, precise location, and credentials"

Design notes / assumptions

  • chatModel / embeddingModel reference model deployment names that must already exist in the Foundry project (consistent with the sample and REST docs).
  • Provisioning is idempotent: existing stores are left as-is, so deploy is safe to re-run.
  • Integration surface is the azure.ai.agent service-target config. The unified Foundry resource shape (PR feat: carry Foundry agent and resource definitions in azure.yaml #8779) currently lives on a feature branch rather than main; this PR targets main using the existing service-target config, consistent with how toolboxes/connections/deployments are declared.

Testing

  • go build ./...
  • go test ./... (full extension suite passes)
  • gofmt -s, golangci-lint run (0 issues), cspell (0 issues) on changed files

Add support for declaring Foundry memory stores in the agent service config and provisioning them (create-if-not-exists) during `azd deploy`, mirroring the reference provision_memory_store.py sample.

- New FoundryMemoryStoreClient (Create/Get/Ensure) targeting the memory_stores data-plane API (api-version 2025-11-15-preview).

- New `memoryStores` section in the agent service-target config and JSON schema.

- provisionMemoryStores wired into the agent Deploy flow before agent creation.

Fixes #8742

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 29, 2026 15:58
@github-actions

Copy link
Copy Markdown

📋 Prioritization Note

Thanks for the contribution! The linked issue isn't in the current milestone yet.
Thank you for logging this issue; our team is reviewing it. If you need urgent prioritization, tag @RickWinter and @kristenwomack to let us know.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Foundry memory support to the azure.ai.agents extension by allowing users to declare memoryStores in azure.yaml, and provisioning those stores (create-if-not-exists) as part of the hosted-agent deploy flow.

Changes:

  • Adds memoryStores to the agent service-target config and JSON schema, including optional retention/extraction options.
  • Introduces a new Foundry data-plane client to GET/POST memory store resources and an idempotent EnsureMemoryStore.
  • Wires provisioning into Deploy and adds unit tests + a changelog entry.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
cli/azd/extensions/azure.ai.agents/schemas/azure.ai.agent.json Adds memoryStores schema and MemoryStore definition for azure.yaml validation.
cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Calls memory-store provisioning during deploy; adds mapping helper for options.
cli/azd/extensions/azure.ai.agents/internal/project/memory_store_provision_test.go Adds tests for provisioning no-op, validation, and options mapping.
cli/azd/extensions/azure.ai.agents/internal/project/config.go Extends service target config structs with MemoryStore and MemoryStoreOptions.
cli/azd/extensions/azure.ai.agents/internal/project/config_test.go Adds marshal/unmarshal round-trip coverage for MemoryStores.
cli/azd/extensions/azure.ai.agents/internal/pkg/azure/foundry_memory_store_client.go Introduces the Foundry Memory Store data-plane client (create/get/ensure).
cli/azd/extensions/azure.ai.agents/internal/pkg/azure/foundry_memory_store_client_test.go Adds request-shape, escaping, and ensure(create-if-missing) tests for the client.
cli/azd/extensions/azure.ai.agents/internal/exterrors/codes.go Adds error code and op name for memory store provisioning.
cli/azd/extensions/azure.ai.agents/CHANGELOG.md Documents the new memoryStores deploy-time provisioning behavior.

@github-actions github-actions Bot added the ext-agents azure.ai.agents extension label Jun 29, 2026

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One error code inconsistency to fix. The rest of the implementation follows existing patterns cleanly (client structure mirrors the toolsets client, idempotent ensure pattern is solid, tests cover the key branches).

The Copilot bot flagged IncludeBody: true as a concern, but that's the existing convention in oundry_toolsets_client.go, so it's fine here.

… options, neutral provision op name

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incremental review after 1f1975d: the error code is now aligned with the existing CodeMissingAiProjectEndpoint convention, the mapMemoryStoreOptions nil-or-empty guard prevents sending an empty options object to the service, and the op name OpProvisionMemoryStore better reflects the GET-then-POST semantics of EnsureMemoryStore. All fields in memoryStoreOptionsEmpty match the MemoryStoreOptions struct, and the new test case validates the empty-struct path. No remaining concerns.

…-memory-support

# Conflicts:
#	cli/azd/extensions/azure.ai.agents/CHANGELOG.md
@huimiu

huimiu commented Jul 1, 2026

Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

…-memory-support

# Conflicts:
#	cli/azd/extensions/azure.ai.agents/CHANGELOG.md

Co-authored-by: huimiu <107838226+huimiu@users.noreply.github.com>

Copilot AI commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Done. Merged origin/main into the branch. The only conflict was in CHANGELOG.md — the ## Unreleased section in this PR overlapped with the new ## 1.0.0-beta.2 (2026-07-01) header on main. Resolved by keeping only the #8742 memory-store entry under ## Unreleased (the other items from the pre-merge unreleased section were already captured in the 1.0.0-beta.1 release on main) and letting main's 1.0.0-beta.2 section follow below it.

Copilot finished work on behalf of huimiu July 1, 2026 10:26

@RickWinter RickWinter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds a data-plane client for Foundry memory stores and wires idempotent create-if-missing provisioning into the hosted-agent deploy, gated on declared memoryStores in azure.yaml. The shape is right: it mirrors the existing Foundry client pattern, keys off FOUNDRY_PROJECT_ENDPOINT like the rest of the file, only creates on a real 404, and propagates auth/5xx/network errors instead of masking them. Client and provisioning-validation test coverage is solid. The one thing worth resolving before merge is drift: once a store exists, editing its chatModel, embeddingModel, or options in azure.yaml has no effect and no warning, and the gray "leaving as-is" line lands exactly where a user expects their change to apply. Documenting that as intended and, ideally, warning when the declared definition diverges from the live store would prevent a confusing silent no-op. The rest are optional: validating all stores before the first network call avoids half-provisioning on a typo, and routing the created/exists lines through the progress reporter keeps deploy output consistent. Nothing here blocks; the idempotent design is sound and safe to re-run.

if created {
fmt.Println(output.WithSuccessFormat("Created memory store %q", store.Name))
} else {
fmt.Println(output.WithGrayFormat("Memory store %q already exists; leaving as-is", store.Name))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because EnsureMemoryStore returns the existing store untouched on a GET hit, a user who edits chatModel, embeddingModel, or any options for an already-created store and redeploys gets no update and no warning, and this line even prints "leaving as-is" in gray right where they would expect their new config to take effect. That is a reasonable default for idempotency, but the silent divergence between azure.yaml and the live store is easy to trip over. Could we at least surface it, for example compare the declared definition against what the GET returned and warn when they differ, so the user knows a change in azure.yaml was ignored? If updating in place is out of scope for this PR, a louder message here would go a long way.


client := azure.NewFoundryMemoryStoreClient(projectEndpoint, p.credential)

for _, store := range config.MemoryStores {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: validation runs inside the same loop that issues the create calls, so if the second store is missing chatModel we have already created the first one before we error out. Re-running is safe thanks to the idempotent ensure, so this is not harmful, just a little surprising on a config typo. Would it be worth validating every store's required fields up front, before the loop that talks to the service, so a bad entry fails fast without half-provisioning?

}

if created {
fmt.Println(output.WithSuccessFormat("Created memory store %q", store.Name))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the created/exists results go straight to stdout via fmt.Println while the surrounding deploy flow reports through the progress reporter. Depending on how progress renders (a spinner), interleaving a raw Println mid-loop can look ragged. Routing these through progress(...) too would keep the output consistent with the rest of Deploy.

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All prior feedback addressed. The implementation follows existing patterns cleanly, test coverage is solid, and the merge conflicts from main were resolved without issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext-agents azure.ai.agents extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Foundry memory support

6 participants