feat: scaffold MemoryService for Agent Episodic Memory (URT migration)#1467
Open
feat: scaffold MemoryService for Agent Episodic Memory (URT migration)#1467
Conversation
44bd0a8 to
239b787
Compare
pateljay43
reviewed
Mar 27, 2026
pateljay43
reviewed
Mar 27, 2026
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
pateljay43
reviewed
Mar 27, 2026
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
pateljay43
reviewed
Mar 27, 2026
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
mjnovice
commented
Mar 30, 2026
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
mjnovice
commented
Mar 30, 2026
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
pateljay43
reviewed
Mar 30, 2026
packages/uipath-platform/src/uipath/platform/memory/_memory_service.py
Outdated
Show resolved
Hide resolved
Add MemoryService client backed by ECS (/ecs_/memory/...) endpoints for Agent Episodic Memory. This enables dynamic few-shot retrieval where agents query past episodes at execution start and inject them as examples into the system prompt. New files: - memory.py: Pydantic models (MemoryField, MemoryItem, MemoryQueryRequest, etc.) - _memory_service.py: MemoryService with create, ingest, query, retrieve, delete, list - __init__.py: Module exports Also registers sdk.memory on the UiPath class. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tract The original scaffold was based on a different/older API spec. This rewrites models and endpoints to match the actual ECS v2 episodicmemories contract: - Paths: /ecs_/v2/episodicmemories (not /ecs_/memory) - Resources identified by GUID key (not name) - Field model uses keyPath[] + value (not fieldName/fieldValue) - Search replaces query, with structured SearchSettings and per-field settings - Ingest now returns EpisodicMemoryIngestResponse with memory ID - Added missing operations: delete_index, patch_memory (status active/inactive) - EpisodicMemoryIndex includes all server fields (memoriesCount, folderKey, etc.) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per PR review feedback: ingestion should go to LLMOps, which extracts
fields from traces/feedback before forwarding to ECS.
Architecture:
- Index CRUD (create/list/get/delete) → ECS /ecs_/v2/episodicmemories
- Ingest → LLMOps /llmops_/api/Agent/memory/{id}/ingest (feedbackId-based)
- Search → LLMOps /llmops_/api/Agent/memory/{id}/search (returns systemPromptInjection)
- Patch/delete items → LLMOps /llmops_/api/Memory/{id}/items/{itemId}
LLMOps search returns systemPromptInjection — the formatted string
ready to inject into the agent's system prompt for few-shot retrieval.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Full lifecycle test: create index → create feedback → ingest via LLMOps → search → verify response shape → delete index. Tests are marked @pytest.mark.e2e and excluded from default runs. Run with: uv run pytest -m e2e -v (requires UIPATH_URL, UIPATH_ACCESS_TOKEN, UIPATH_FOLDER_KEY env vars). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- LLMOps endpoints use llmopstenant_ prefix (not llmops_) through the platform gateway — llmops_ returns 302, llmopstenant_ routes correctly - SearchField.settings is now required (default FieldSettings()) per LLMOps API contract which requires the settings field on each field - Fixed E2E test feedback endpoint to use llmopstenant_ prefix E2E results: 5 passed, 1 skipped (ingest skipped because synthetic trace/span IDs don't exist in LLMOps trace store — needs real agent trace for full lifecycle test) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Adds e2e-uipath-platform job to test-packages.yml - Runs on uipath-platform changes, Python 3.11, ubuntu-latest - Uses ALPHA_TEST_CLIENT_ID/CLIENT_SECRET for auth (same as integration tests) - Reads memory folder from UIPATH_MEMORY_FOLDER secret - E2E results are non-blocking in the test gate (informational) - Test supports both token-based (local) and client credentials (CI) auth Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per PR review: _resolve_folder now matches ContextGroundingService pattern — resolves folder_key from folder_path via FolderService when UIPATH_FOLDER_KEY is not set (serverless/robot environments only have UIPATH_FOLDER_PATH). MemoryService now takes a FolderService dependency, wired through the UiPath class. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove methods not used by any frontend or backend flow:
- get(), delete_index() (neither frontend uses; backend uses v1.1)
- ingest() (IM-internal, requires feedback_id from trace pipeline)
- patch_memory(), delete_memory() (wrong endpoints, IM admin ops)
Remove unused models: FeedbackMemoryStatus, EpisodicMemoryPatchRequest,
MemoryIngestRequest/Response, MemoryItemUpdateRequest/Response.
Add escalation memory methods used by the backend agentic loop:
- escalation_search() -> POST /api/Agent/memory/{id}/escalation/search
- escalation_ingest() -> POST /api/Agent/memory/{id}/escalation/ingest
Add models: EscalationMemoryIngestRequest, EscalationMemorySearchResponse,
EscalationMemoryMatch, CachedRecall (matching backend C# contracts).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename _ECS_BASE to _MEMORY_SPACES_BASE for clarity - Add full docstrings (Args/Returns) to all async methods to match their sync counterparts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cover all 5 public methods: create, list, search, escalation_search, escalation_ingest. Tests verify correct URL construction, request body serialization, folder header propagation, and response deserialization. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
EpisodicMemoryField was for ECS ingest (removed). EpisodicMemoryStatus is not referenced by any service method or model. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace "index" terminology with "memory space" throughout the memory module to match the product language used by frontends and backend (MemorySpaceResponse, MemorySpace, etc.). Renames: - EpisodicMemoryIndex → MemorySpace - EpisodicMemoryListResponse → MemorySpaceListResponse - EpisodicMemoryCreateRequest → MemorySpaceCreateRequest All docstrings updated to use "memory space" instead of "memory index". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1dcb374 to
a0ea814
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
MemoryServicetouipath-platform— the SDK client for Agent Memory Spaces. This enables programmatic access to memory space CRUD, dynamic few-shot search, and escalation memory operations used by the UiPath agentic loop.What's included
MemoryServiceexposed assdk.memoryon theUiPathclasscreate,list,search,escalation_search,escalation_ingestMemorySpace,MemorySpaceCreateRequest,MemorySearchRequest/Response,EscalationMemoryIngestRequest, etc.pytest-httpxHTTP mocking/ecs_/v2/episodicmemories) for CRUD, LLMOps (/llmopstenant_/api/Agent/memory) for search and escalationfolder_pathresolutionSDK Methods → Agents Repo References
create()— POST/ecs_/v2/episodicmemories/createExternal.Clients/Ecs/EcsClient.cs:30CreateMemorySpaceAsync()External.Clients/Ecs/AgentMemoryService.cs:20CreateNamespaceAsync()(wrapper)frontend/src/stores/memoryStore.ts:108useCreateMemorySpace()frontend/src/stores/memoryStore.ts:462useCreateEpisodicMemory()frontend-sw/src/api/hooks/memory.ts:93useCreateMemorySpace()list()— GET/ecs_/v2/episodicmemoriesExternal.Clients/Ecs/EcsClient.cs:186GetEpisodicMemorySpaceAsync()(with $filter)frontend/src/stores/memoryStore.ts:129useFetchMemorySpaces()frontend-sw/src/api/hooks/memory.ts:37useFetchMemorySpaces()search()— POST/llmopstenant_/api/Agent/memory/{id}/searchExternal.Clients/LlmOps/LlmOpsClient.cs:238GetDynamicFewShotExamplesFromTracesAsync()Execution.Shared/MemorySpaces/MemorySpacesExecutor.cs:44QueryDynamicFewShotPromptsWithDetailsAsync()— agentic loopCommon/Clients/ILlmOpsClient.cs:33ILlmOpsClientcontractescalation_search()— POST/llmopstenant_/api/Agent/memory/{id}/escalation/searchExternal.Clients/LlmOps/LlmOpsClient.cs:259SearchEscalationMemoryAsync()Execution.Shared/Tools/EscalationTool/EscalationToolExecutor.cs:642FetchFromMemory()— escalation toolCommon/Clients/ILlmOpsClient.cs:40ILlmOpsClientcontractescalation_ingest()— POST/llmopstenant_/api/Agent/memory/{id}/escalation/ingestExternal.Clients/LlmOps/LlmOpsClient.cs:296IngestEscalationMemoryAsync()Execution.Shared/Tools/EscalationTool/EscalationToolExecutor.cs:518GetEscalationOutcomeAsync()— escalation toolCommon/Clients/ILlmOpsClient.cs:47ILlmOpsClientcontractAPI Contract References
Test plan
pytest-httpxmocking (13 tests)ruff check), format (ruff format), type check (mypy) all pass🤖 Generated with Claude Code