Skip to content

Conversation

mingshl
Copy link
Collaborator

@mingshl mingshl commented Oct 14, 2025

Description

During testing, there is casting exception when multiple writes to scratch pad when return_history is true, because we need to parse input notes from string, process as List, store back as JSON string.

Solution

Modified both ReadFromScratchPadTool and WriteToScratchPadTool to:

  1. Consistent String Storage: Always store SCRATCHPAD_NOTES_KEY as JSON string using StringUtils.toJson(notes)
  2. Flexible Input Handling: Parse existing notes using StringUtils.parseStringArrayToList() to support both legacy List format and new JSON string format
  3. Backward Compatibility: Maintain existing functionality while fixing the type mismatch

Key Changes

ReadFromScratchPadTool: Parse input notes from string, process as List, store back as JSON string
WriteToScratchPadTool: Parse existing notes from string, append new note, store as JSON string
Updated Tests: Fixed all unit tests to expect JSON string format and added specific string conversion test cases

###Verifying after fix:

GET {{host}}/_plugins/_ml/memory/message/xgdl4JkBjTTL2aEw_BNV/traces?next_token=0

{
    "traces": [
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "xwdm4JkBjTTL2aEwAxOf",
            "create_time": "2025-10-14T01:46:46.041004Z",
            "updated_time": "2025-10-14T01:46:46.041004Z",
            "input": "How many indices in my cluster? Before returnning final answer, can you read from scratch pad again?",
            "response": "{\"metrics\":{\"latencyMs\":1558.0},\"output\":{\"message\":{\"content\":[{\"text\":\"Okay, let me first check the scratchpad to see if I have any relevant notes saved.\"},{\"toolUse\":{\"input\":{},\"name\":\"ReadFromScratchPadTool\",\"toolUseId\":\"tooluse_XxixiSqAQDGy6szoGGVWhw\"}}],\"role\":\"assistant\"}},\"stopReason\":\"tool_use\",\"usage\":{\"inputTokens\":1263.0,\"outputTokens\":64.0,\"serverToolUsage\":{},\"totalTokens\":1327.0}}",
            "origin": "LLM",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 1
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "yAdm4JkBjTTL2aEwAxOm",
            "create_time": "2025-10-14T01:46:46.050721Z",
            "updated_time": "2025-10-14T01:46:46.050721Z",
            "input": "{}",
            "response": "Notes from scratchpad:\n- You are a helpful researcher to conduct searches in OpenSearch cluster. Before making the search, please remember to use the listIndexTool to figure out what are the available indices first. When using listIndexTool, remember the index name has to be in an array format. Please write down important notes after tool used.",
            "origin": "ReadFromScratchPadTool",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 2
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "ygdm4JkBjTTL2aEwERNR",
            "create_time": "2025-10-14T01:46:49.542802Z",
            "updated_time": "2025-10-14T01:46:49.542802Z",
            "input": "How many indices in my cluster? Before returnning final answer, can you read from scratch pad again?",
            "response": "{\"metrics\":{\"latencyMs\":3433.0},\"output\":{\"message\":{\"content\":[{\"text\":\"From the scratchpad, it seems I don't have any existing information about the number of indices in the cluster. Let me create a research plan to find that out.\\n\\nResearch Plan:\\n1. Use the ListIndexTool to get a list of all indices in the cluster\\n2. Count the number of indices returned \\n3. Save the index list and count to the scratchpad\"},{\"toolUse\":{\"input\":{\"notes\":\"Research Plan:\\n1. Use ListIndexTool to list all indices \\n2. Count number of indices\\n3. Save index list and count to scratchpad\"},\"name\":\"WriteToScratchPadTool\",\"toolUseId\":\"tooluse_oIdJZSmeS-ef7nIniPEwug\"}}],\"role\":\"assistant\"}},\"stopReason\":\"tool_use\",\"usage\":{\"inputTokens\":1410.0,\"outputTokens\":178.0,\"serverToolUsage\":{},\"totalTokens\":1588.0}}",
            "origin": "LLM",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 3
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "yQdm4JkBjTTL2aEwERNR",
            "create_time": "2025-10-14T01:46:49.544225Z",
            "updated_time": "2025-10-14T01:46:49.544225Z",
            "input": "{\"notes\":\"Research Plan:\\n1. Use ListIndexTool to list all indices \\n2. Count number of indices\\n3. Save index list and count to scratchpad\"}",
            "response": "Scratchpad updated. Full content:\n- You are a helpful researcher to conduct searches in OpenSearch cluster. Before making the search, please remember to use the listIndexTool to figure out what are the available indices first. When using listIndexTool, remember the index name has to be in an array format. Please write down important notes after tool used.\n- Research Plan:\n1. Use ListIndexTool to list all indices \n2. Count number of indices\n3. Save index list and count to scratchpad",
            "origin": "WriteToScratchPadTool",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 4
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "ywdm4JkBjTTL2aEwGBME",
            "create_time": "2025-10-14T01:46:51.262181Z",
            "updated_time": "2025-10-14T01:46:51.262181Z",
            "input": "How many indices in my cluster? Before returnning final answer, can you read from scratch pad again?",
            "response": "{\"metrics\":{\"latencyMs\":1664.0},\"output\":{\"message\":{\"content\":[{\"text\":\"Now to execute the plan:\"},{\"toolUse\":{\"input\":{\"indices\":[]},\"name\":\"ListIndexTool\",\"toolUseId\":\"tooluse_d8GN_G9CSq2MmhNqiMQcyA\"}}],\"role\":\"assistant\"}},\"stopReason\":\"tool_use\",\"usage\":{\"inputTokens\":1711.0,\"outputTokens\":62.0,\"serverToolUsage\":{},\"totalTokens\":1773.0}}",
            "origin": "LLM",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 5
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "zAdm4JkBjTTL2aEwGBMX",
            "create_time": "2025-10-14T01:46:51.283035Z",
            "updated_time": "2025-10-14T01:46:51.283035Z",
            "input": "{\"indices\":[]}",
            "response": "row,health,status,index,uuid,pri(number of primary shards),rep(number of replica shards),docs.count(number of available documents),docs.deleted(number of deleted documents),store.size(store size of primary and replica shards),pri.store.size(store size of primary shards)\n1,green,open,.plugins-ml-memory-message,1V24LDjlT9mFKyUGIEkiNA,1,0,11,1,39.1kb,39.1kb\n2,green,open,.plugins-ml-model-group,_kFKAePKRpKAGTk0ALlJXg,1,0,1,1,12.6kb,12.6kb\n3,green,open,.plugins-ml-memory-meta,RrOMXaEMQgmxo34ydZOt7g,1,0,2,11,66.4kb,66.4kb\n4,green,open,.plugins-ml-config,6f7BWQiaSVS-pKKgalp2oQ,1,0,1,0,3.9kb,3.9kb\n5,green,open,.plugins-ml-model,2I2oNNL4Ro672wn70vFUbw,1,0,1,2,127kb,127kb\n6,green,open,.plugins-ml-agent,5mRk2ZnyQOmZ5IntXflRDQ,1,0,1,0,21.1kb,21.1kb\n7,green,open,.plugins-ml-task,vaqOqWmpRPCtlqdiQJrSUQ,1,0,2,3,36.1kb,36.1kb\n",
            "origin": "ListIndexTool",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 6
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "zQdm4JkBjTTL2aEwJBNQ",
            "create_time": "2025-10-14T01:46:54.413256Z",
            "updated_time": "2025-10-14T01:46:54.413256Z",
            "input": "How many indices in my cluster? Before returnning final answer, can you read from scratch pad again?",
            "response": "{\"metrics\":{\"latencyMs\":3074.0},\"output\":{\"message\":{\"content\":[{\"text\":\"Looking at the output, there are 7 rows which correspond to 7 indices in the cluster.\"},{\"toolUse\":{\"input\":{\"notes\":\"Found 7 indices in the cluster from ListIndexTool:\\n1. .plugins-ml-memory-message  \\n2. .plugins-ml-model-group\\n3. .plugins-ml-memory-meta\\n4. .plugins-ml-config\\n5. .plugins-ml-model\\n6. .plugins-ml-agent  \\n7. .plugins-ml-task\"},\"name\":\"WriteToScratchPadTool\",\"toolUseId\":\"tooluse_rV5zL5FlT1Wblxrarfqksg\"}}],\"role\":\"assistant\"}},\"stopReason\":\"tool_use\",\"usage\":{\"inputTokens\":2208.0,\"outputTokens\":168.0,\"serverToolUsage\":{},\"totalTokens\":2376.0}}",
            "origin": "LLM",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 7
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "zgdm4JkBjTTL2aEwJBNR",
            "create_time": "2025-10-14T01:46:54.416241Z",
            "updated_time": "2025-10-14T01:46:54.416241Z",
            "input": "{\"notes\":\"Found 7 indices in the cluster from ListIndexTool:\\n1. .plugins-ml-memory-message  \\n2. .plugins-ml-model-group\\n3. .plugins-ml-memory-meta\\n4. .plugins-ml-config\\n5. .plugins-ml-model\\n6. .plugins-ml-agent  \\n7. .plugins-ml-task\"}",
            "response": "Scratchpad updated. Full content:\n- You are a helpful researcher to conduct searches in OpenSearch cluster. Before making the search, please remember to use the listIndexTool to figure out what are the available indices first. When using listIndexTool, remember the index name has to be in an array format. Please write down important notes after tool used.\n- Research Plan:\n1. Use ListIndexTool to list all indices \n2. Count number of indices\n3. Save index list and count to scratchpad\n- Found 7 indices in the cluster from ListIndexTool:\n1. .plugins-ml-memory-message  \n2. .plugins-ml-model-group\n3. .plugins-ml-memory-meta\n4. .plugins-ml-config\n5. .plugins-ml-model\n6. .plugins-ml-agent  \n7. .plugins-ml-task",
            "origin": "WriteToScratchPadTool",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 8
        },
        {
            "memory_id": "xQdl4JkBjTTL2aEw-xOp",
            "message_id": "zwdm4JkBjTTL2aEwLRMy",
            "create_time": "2025-10-14T01:46:56.688262Z",
            "updated_time": "2025-10-14T01:46:56.688262Z",
            "input": "How many indices in my cluster? Before returnning final answer, can you read from scratch pad again?",
            "response": "To summarize, based on the information gathered from the ListIndexTool, there are 7 indices in my OpenSearch cluster. I have compiled the list of index names and the count in my persistent scratchpad for future reference.",
            "origin": "LLM",
            "parent_message_id": "xgdl4JkBjTTL2aEw_BNV",
            "trace_number": 9
        }
    ]
}

Check List

  • New functionality includes testing.
  • New functionality has been documented.
  • API changes companion pull request created.
  • Commits are signed per the DCO using --signoff.
  • Public documentation issue/PR created.

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.

Copy link

codecov bot commented Oct 14, 2025

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.13%. Comparing base (709ba4b) to head (079e462).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...search/ml/engine/tools/ReadFromScratchPadTool.java 75.00% 0 Missing and 1 partial ⚠️
...nsearch/ml/engine/tools/WriteToScratchPadTool.java 75.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #4310      +/-   ##
============================================
- Coverage     80.14%   80.13%   -0.01%     
+ Complexity    10175    10171       -4     
============================================
  Files           854      854              
  Lines         44231    44219      -12     
  Branches       5117     5113       -4     
============================================
- Hits          35450    35437      -13     
- Misses         6631     6633       +2     
+ Partials       2150     2149       -1     
Flag Coverage Δ
ml-commons 80.13% <75.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mingshl mingshl temporarily deployed to ml-commons-cicd-env October 14, 2025 02:58 — with GitHub Actions Inactive
@mingshl mingshl temporarily deployed to ml-commons-cicd-env October 14, 2025 02:58 — with GitHub Actions Inactive
@mingshl mingshl merged commit 9b11665 into opensearch-project:main Oct 14, 2025
13 of 14 checks passed
opensearch-trigger-bot bot pushed a commit that referenced this pull request Oct 14, 2025
Signed-off-by: Mingshi Liu <[email protected]>
(cherry picked from commit 9b11665)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants