feat: Add new toolset for OpenSearch Agentic Memory API#138
feat: Add new toolset for OpenSearch Agentic Memory API#138oujezdsky wants to merge 31 commits intoopensearch-project:mainfrom
Conversation
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
…uster_name param Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
…Tool Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
…moryTool Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
|
Hello, This PR is ready for review again. 5 new commits that address issues:
Thank you for the review and apologies for the inconvenience. |
|
Hi @oujezdsky thanks for the PR! Few high level thoughts before I review the PR:
|
|
Hello @rithin-pullela-aws, Regarding the Readme and Userguide—no problem, I’ll add the new tools there as well. thanks |
…Tool Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
|
This PR has been updated to address all comments and is now ready for re-review.
|
nathaliellenaa
left a comment
There was a problem hiding this comment.
Thanks for raising this PR @oujezdsky! Added some comments
CHANGELOG.md
Outdated
|
|
||
| ### Fixed | ||
| - Fix AWS auth issues for cat based tools, pin OpenSearchPy to 2.18.0 ([#135](https://github.com/opensearch-project/opensearch-mcp-server-py/pull/135)) | ||
| - Add new toolset for the OpenSearch Agentic Memory API: `CreateAgenticMemoryContainerTool`, `CreateAgenticMemorySessionTool`, `AddAgenticMemoriesTool`, `GetAgenticMemoryTool`, `UpdateAgenticMemoryTool`, `DeleteAgenticMemoryByIDTool`, `DeleteAgenticMemoryByQueryTool`, and `SearchAgenticMemoryTool`. ([#113](https://github.com/opensearch-project/opensearch-mcp-server-py/pull/138)) |
There was a problem hiding this comment.
| - Add new toolset for the OpenSearch Agentic Memory API: `CreateAgenticMemoryContainerTool`, `CreateAgenticMemorySessionTool`, `AddAgenticMemoriesTool`, `GetAgenticMemoryTool`, `UpdateAgenticMemoryTool`, `DeleteAgenticMemoryByIDTool`, `DeleteAgenticMemoryByQueryTool`, and `SearchAgenticMemoryTool`. ([#113](https://github.com/opensearch-project/opensearch-mcp-server-py/pull/138)) | |
| - Add new toolset for the OpenSearch Agentic Memory API: `CreateAgenticMemoryContainerTool`, `CreateAgenticMemorySessionTool`, `AddAgenticMemoriesTool`, `GetAgenticMemoryTool`, `UpdateAgenticMemoryTool`, `DeleteAgenticMemoryByIDTool`, `DeleteAgenticMemoryByQueryTool`, and `SearchAgenticMemoryTool`. ([#138](https://github.com/opensearch-project/opensearch-mcp-server-py/pull/138)) |
README.md
Outdated
| - `messages` (conditional): A list of messages. Required when `payload_type` is `conversational`. *(Body Parameter)* | ||
| - `structured_data` (conditional): Structured data content. Required when `payload_type` is `data`. *(Body Parameter)* | ||
| - `binary_data` (optional): Binary data content encoded as a Base64 string for binary payloads. *(Body Parameter)* | ||
| - `payload_type` (required): The type of payload. Valid values are `conversational` or `data`. See [See Payload types](https://docs.opensearch.org/latest/ml-commons-plugin/agentic-memory/#payload-types). *(Body Parameter)* |
There was a problem hiding this comment.
| - `payload_type` (required): The type of payload. Valid values are `conversational` or `data`. See [See Payload types](https://docs.opensearch.org/latest/ml-commons-plugin/agentic-memory/#payload-types). *(Body Parameter)* | |
| - `payload_type` (required): The type of payload. Valid values are `conversational` or `data`. See [Payload types](https://docs.opensearch.org/latest/ml-commons-plugin/agentic-memory/#payload-types). *(Body Parameter)* |
README.md
Outdated
| - `namespace` (optional): The [namespace](https://docs.opensearch.org/latest/ml-commons-plugin/agentic-memory/#namespaces) context for organizing memories (for example, `user_id`, `session_id`, or `agent_id`). If `session_id` is not specified in the namespace field and `disable_session`: `false` (default is `true`), a new session with a new session ID is created. *(Body Parameter)* | ||
| - `metadata` (optional): Additional metadata for the memory (for example, `status`, `branch`, or custom fields). *(Body Parameter)* | ||
| - `tags` (optional): Tags for categorizing memories. *(Body Parameter)* | ||
| - `infer` (optional): Whether to use an LLM to extract key information (default: `false`). When `true`, the LLM extracts key information from the original text and stores it as a memory. [See Inference mode](https://docs.opensearch.org/latest/ml-commons-plugin/agentic-memory/#inference-mode). *(Body Parameter)* |
There was a problem hiding this comment.
| - `infer` (optional): Whether to use an LLM to extract key information (default: `false`). When `true`, the LLM extracts key information from the original text and stores it as a memory. [See Inference mode](https://docs.opensearch.org/latest/ml-commons-plugin/agentic-memory/#inference-mode). *(Body Parameter)* | |
| - `infer` (optional): Whether to use an LLM to extract key information (default: `false`). When `true`, the LLM extracts key information from the original text and stores it as a memory. See [Inference mode](https://docs.opensearch.org/latest/ml-commons-plugin/agentic-memory/#inference-mode). *(Body Parameter)* |
src/opensearch/helper.py
Outdated
| """Create a new agentic memory session in the specified memory container. | ||
|
|
||
| Args: | ||
| args: CreateSessionArgs containing memory_container_id and optional session_id, summary, metadata, namespace |
There was a problem hiding this comment.
Nit:
| args: CreateSessionArgs containing memory_container_id and optional session_id, summary, metadata, namespace | |
| args: CreateAgenticMemorySessionArgs containing memory_container_id and optional session_id, summary, metadata, namespace |
src/tools/agentic_memory/actions.py
Outdated
| return [{'type': 'text', 'text': f'Error updating memory: {str(error_to_report)}'}] | ||
|
|
||
|
|
||
| async def delete_agentic_memoryby_ID_tool( |
There was a problem hiding this comment.
Function name be should be delete_agentic_memory_by_id_tool to make it consistent with other function names
src/tools/agentic_memory/actions.py
Outdated
| if container_id: | ||
| message = f'Successfully created memory container. ID: {container_id}. Response: {json.dumps(result)}' | ||
| else: | ||
| message = ( | ||
| f'Memory container created, but no ID was returned. Response: {json.dumps(result)}' | ||
| ) |
There was a problem hiding this comment.
Should we keep a consistent message formatting? We can follow the format in create_agentic_memory_session_tool, for example
message = (
f'Successfully created memory container. ID: {container_id}. Response: {json.dumps(result)}'
if container_id
else f'Memory container created, but no ID was returned. Response: {json.dumps(result)}'
)
src/tools/agentic_memory/params.py
Outdated
| @model_validator(mode='after') | ||
| def validate_embedding_configuration(self) -> 'AgenticMemoryConfigurationArgs': | ||
| """Validate embedding model configuration.""" | ||
| if self.embedding_model_type == 'TEXT_EMBEDDING' and self.embedding_dimension is None: |
There was a problem hiding this comment.
Can we do if self.embedding_model_type == EmbeddingModelType.text_embedding?
src/tools/tools.py
Outdated
| 'function': create_agentic_memory_session_tool, | ||
| 'args_model': CreateAgenticMemorySessionArgs, | ||
| 'min_version': '3.3.0', # Agentic memory APIs requires OpenSearch 3.3+ | ||
| 'http_methods': 'UPDATE', |
There was a problem hiding this comment.
The http_methods should be the actual REST API method being called, so in this case it should be POST. The same should be applied for the other agentic memory tools
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
…tency Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
|
@nathaliellenaa Thanks for the feedback! I've addressed all the comments. |
|
Thanks for the PR! Overall the changes look good to me from a tools perspective. One question is that when using these MCP tools with an agent, e.g. Claude desktop or Q/Kiro CLI, is it able to recognize that it needs to create a container before it can use the other Agentic Memory tools? Or would the user need to guide it through prompt to create container then add/get/update/delete memory? |
|
Thanks for the feedback! Regarding the MCP tools themselves, it relies on the tool definitions (schemas). For example, since But I could extend the description in For example, like this: (snippet from |
…ory-tools Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
I think we should keep container creation separate from the MCP tools for these reasons:
This way, agents don't need to pass it with every call. |
+1 on we should keep memory container creation separate as otherwise agent will create a new container each time and won't be able to access previous session's memory. Though for ease-of-use purpose we should consider if we can provide an easy way to create the container either via a script or via optional MCP tools. Having to manually setup embedding models, LLM connectors, strategies, index settings manually could be overwhelming for new users of Agentic Memory.
Yes container ID can be provided via tool customization, maybe we can also allow it to be configured via env vars. I think memory tools should also be disabled by default (so that agents don't try to invoke them without a container ready), and users who do want to use memory can specify flag to enable and provide memory container ID. |
Yeah +1 on this. We can take that as a follow up item.
Agree with disabling by default. To make this seamless, we could auto-enable based on configuration: This way:
Users just set |
I agree on separating the memory container creation from the MCP tools as the configuration can be complex and it's error prone for agents to handle at runtime. To make the initial setup easier, we could support pre-built container templates (e.g., default, minimal, advanced). This way, new users who aren't familiar with Agentic Memory can simply run
+1 on this. I think we can introduce a dedicated flag for the agentic memory feature. When users enable this flag, all agentic memory-related tools will be automatically enabled, and they can provide the memory_container_id at server startup. For example |
|
@oujezdsky if possible can we target to make the suggested changes and merge this PR asap? Thanks a lot for working on this. |
|
Hi everyone, thanks for the detailed feedback. @dhrubo-os I'll be able to work on it this weekend. There's a chance I'll be able to do it sooner, but the weekend is the most certain. |
…ory-tools Signed-off-by: Jiri Oujezdsky <oujezdsky2@gmail.com>
|
@dhrubo-os Quick question regarding YAML config. I checked how If so, are you OK with me extending the config format to support defaults, e.g.: tools:
ListIndexTool:
display_name: "My_Custom_Index_Lister"
description: "This is a custom description for the tool that lists indices. It's much more descriptive now!"
args:
index: "Custom description for the 'index' argument in ListIndexTool."
AddAgenticMemoriesTool:
args:
memory_container_id:
default: "your-container-id"so the server can prefill I would implement it in such a way that it does not affect the existing functionality around parsing |
Sorry for the late reply. Sure go ahead. I prefer that too. |
|
Okay |
LEt's target to merge this PR by this month if possible. Also how did we test if the tools are correctly picking up or not? Specially adding memory and search memory? |
I tested all CRUD + search operatios. Everything was OK. |
Description
This pull request introduces a set of 7 new tools to support the OpenSearch Agentic Memory API (released in 3.3). This allows agents using the MCP server to create, manage, and interact with agentic memories.
Key changes include:
CreateAgenticMemoryContainerTool,CreateAgenticMemorySessionTool,AddAgenticMemoriesTool,GetAgenticMemoryTool,UpdateAgenticMemoryArgsTool,DeleteAgenticMemoryByIDTool,DeleteAgenticMemoryByQueryTool, andSearchAgenticMemoryTool.asynchelper functions insrc/opensearch/helper.py.HelperOperationErrorto provide better, contextualized error logging.pytest.mark.parametrizefor all happy paths andpytest.raisesfor Pydantic validation.Issues Resolved
Closes #113
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.