Skip to content

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

Merged
glharper merged 6 commits into
mainfrom
glharper/8742-foundry-memory-support
Jul 2, 2026
Merged

feat(agents): provision Foundry memory stores during deploy#8852
glharper merged 6 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.

Comment thread cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Outdated
@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.

Comment thread cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Outdated

@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.

@glharper

glharper commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

/check-enforcer override

glharper and others added 2 commits July 2, 2026 12:12
… route status through progress

- Detect and warn when a declared memory store definition diverges from an existing live store, so azure.yaml changes are not silently ignored (azd does not update existing stores).

- Validate all declared stores before any network call to avoid half-provisioning on a typo.

- Route created/already-exists status through the progress reporter for consistent deploy output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
….com/Azure/azure-dev into glharper/8742-foundry-memory-support

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

@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 of 119db86: drift detection, upfront validation, and progress routing all look correct.

  • validateMemoryStores extraction ensures fail-fast before any network call
  • memoryStoreDefinitionDrift only flags fields the user explicitly declared (no false positives from service defaults)
  • boolPtrDiffers nil-handling is correct: nil declared = no drift, nil live with set declared = drift
  • Test coverage is thorough (drift scenarios, bool pointer edge cases, upfront validation ordering)
  • writeMemoryStoreDriftWarning on stderr with actionable remediation text is the right output channel for a warning

No remaining concerns.

@glharper glharper merged commit eef3f78 into main Jul 2, 2026
26 checks passed

@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 Foundry memory store provisioning to the hosted-agent deploy path: a new data-plane client (FoundryMemoryStoreClient), a memoryStores config/schema block, and provisionMemoryStores wired into Deploy before the agent is created. The shape is right. The client faithfully mirrors the existing FoundryToolboxClient (same pipeline, same https://ai.azure.com/.default scope), validation runs up front before any network call, errors are classified through exterrors, and provisioning is idempotent with a clear warning when a declared definition diverges from a store that already exists.

One thing worth resolving before merge: the drift detection in memoryStoreDefinitionDrift assumes the GET on an existing store returns the full definition. If the preview API does not echo it, the warning fires on every redeploy of a correctly configured store. That is a UX regression rather than a correctness bug, so it does not block, but I would confirm the service contract before this ships. See the inline note.

One non-blocking edge case to keep in mind: because Deploy runs per service in parallel, two services declaring the same store name could both GET 404 and then race on create, and the second POST would surface as an error. Fine to leave for now given this is preview and an unusual config, but worth a follow-up if it comes up.

Nothing here blocks. Address the drift-on-GET question (or confirm the contract), and the rest is good to merge.

func memoryStoreDefinitionDrift(declared, live azure.MemoryStoreDefinition) []string {
var drift []string

if declared.ChatModel != live.ChatModel {

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 comparison assumes the GET on an existing store returns the full definition (chat_model, embedding_model, and any options) that we send on create. If the 2025-11-15-preview service omits or only partially populates definition on GET, then live.ChatModel comes back empty and this reports drift on every redeploy of a correctly configured store, so the user sees the "changes were NOT applied" warning even when nothing changed. Have we confirmed against the live service that GET echoes the definition? If it does not, I would gate the warning on the live definition actually being populated rather than comparing declared values against zero values.

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