Skip to content

Conversation

dhrubo-os
Copy link
Collaborator

Description

[adding agentCore memory integration in agent execution]

Related Issues

Resolves #[Issue number to be closed when this PR is merged]

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.

@b4sjoo
Copy link
Collaborator

b4sjoo commented Sep 1, 2025

Can we remove those emojis in response messages? @dhrubo-os

Copy link

codecov bot commented Sep 3, 2025

Codecov Report

❌ Patch coverage is 56.32084% with 501 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.19%. Comparing base (f75ae1a) to head (a7ac7bf).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
...edrockagentcore/BedrockAgentCoreClientWrapper.java 10.92% 161 Missing and 2 partials ⚠️
...emory/bedrockagentcore/BedrockAgentCoreMemory.java 24.00% 108 Missing and 6 partials ⚠️
...thms/agent/MLPlanExecuteAndReflectAgentRunner.java 56.41% 84 Missing and 18 partials ⚠️
.../ml/engine/algorithms/agent/MLChatAgentRunner.java 85.11% 29 Missing and 10 partials ⚠️
...ckagentcore/BedrockAgentCoreCredentialManager.java 0.00% 31 Missing ⚠️
...mory/bedrockagentcore/BedrockAgentCoreAdapter.java 64.17% 9 Missing and 15 partials ⚠️
...ch/ml/engine/algorithms/agent/MLAgentExecutor.java 87.71% 12 Missing and 9 partials ⚠️
...ch/ml/common/input/execute/agent/AgentMLInput.java 22.22% 5 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #4149      +/-   ##
============================================
- Coverage     81.81%   81.19%   -0.62%     
- Complexity     8847     8970     +123     
============================================
  Files           761      766       +5     
  Lines         38099    39021     +922     
  Branches       4250     4378     +128     
============================================
+ Hits          31170    31683     +513     
- Misses         5109     5473     +364     
- Partials       1820     1865      +45     
Flag Coverage Δ
ml-commons 81.19% <56.32%> (-0.62%) ⬇️

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.

@dhrubo-os dhrubo-os temporarily deployed to ml-commons-cicd-env September 3, 2025 02:07 — with GitHub Actions Inactive
@dhrubo-os dhrubo-os temporarily deployed to ml-commons-cicd-env September 3, 2025 02:07 — with GitHub Actions Inactive
Signed-off-by: Dhrubo Saha <[email protected]>
Copy link
Collaborator

@pyek-bot pyek-bot left a comment

Choose a reason for hiding this comment

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

Thanks for the changes @dhrubo-os ! This is a considerable PR.

A couple things would help to make the review easier:

  1. A class diagram of the Adapter pattern for the BedrockAgentCoreMemory
  2. Parallels between existing memory components like memory, message, interaction with AgentCore.
  3. Memory management between the planner/executor. Currently, they are separate memories. Wondering if we are merging them with agentCore.

I've reviewed most of the PR and left quite a few refactor/nitpick type of comments. Feel free to address them later. However, a few comments are about the functionality and the expected result. Please do take a look at them!

Map<String, String> parameters = StringUtils.getParameterMap(parser.map());
inputDataset = new RemoteInferenceInputDataSet(parameters);
break;
case "memory":
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use constants (leaving nitpicks so we can track them, they can be addressed later)

Comment on lines +103 to +105
Map<String, String> inputParameters = gson
.fromJson(input, TypeToken.getParameterized(Map.class, String.class, String.class).getType());
extractedParameters.putAll(inputParameters);
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we use this please:

Map<String, Object> parsedInputParameters = gson.fromJson(input, TypeToken.getParameterized(Map.class, String.class, Object.class).getType());
extractedParameters.putAll(StringUtils.getParameterMap(parsedInputParameters));

Ref: https://github.com/opensearch-project/ml-commons/pull/4138/files#diff-28a59745543ec384ed12c99d11a3d4f9909aa4032449587135b9bdcf313c6293

Copy link
Collaborator

Choose a reason for hiding this comment

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

let's keep this method as in the above PR if possible, thanks

extractedParameters.putAll(inputParameters);

// Check if input is a JSON object or array
String trimmedInput = input.trim();
Copy link
Collaborator

Choose a reason for hiding this comment

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

is there a reason for these changes? i would avoid parameter parsing changes unless 100% required for memory related changes

Comment on lines +150 to +155
input.setMemory(memoryMap);

assertNotNull("Memory should not be null after setting", input.getMemory());
assertEquals("bedrock_agentcore_memory", input.getMemory().get("type"));
assertEquals("test-arn", input.getMemory().get("memory_arn"));
assertEquals("us-east-1", input.getMemory().get("region"));
Copy link
Collaborator

Choose a reason for hiding this comment

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

this test is only testing the setter, not sure how useful that is

AgentMLInput agentMLInput = (AgentMLInput) input;

// DEBUG: Log agentMLInput memory field immediately after cast
log.info("DEBUG: AgentMLInput memory field immediately after cast: {}", agentMLInput.getMemory());
Copy link
Collaborator

Choose a reason for hiding this comment

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

can this be removed? info log

Comment on lines +566 to +586
if (executorMemoryId != null) {
reactParams.put("executor_memory_id", executorMemoryId);
allParams.put("executor_memory_id", executorMemoryId); // Track executor memory ID
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

for reactParams we should use key memory_id so that we don't need custom logic in chat agent for when it is being used as executor, chat agent should not know this information as it is an individual agent, just the caller is not human

reactParams.put("memory_session_token", allParams.get("memory_session_token"));

// CRITICAL FIX: Pass executor memory ID to executor agents
if (executorMemoryId != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

also this param seems specific to agentcore, maybe consider rename

}

// CRITICAL FIX: Use executor memory ID for executor agent calls to maintain shared conversation context
if (executorMemoryId != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

same check as above, is this intentional?


// CRITICAL FIX: Use executor memory ID for executor agent calls to maintain shared conversation context
if (executorMemoryId != null) {
reactParams.put("session_id", executorMemoryId);
Copy link
Collaborator

Choose a reason for hiding this comment

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

both keys: session_id and executor_memory_id has the same value

// Last resort: generate new session_id only if none exists
String sessionId = "bedrock-session-" + System.currentTimeMillis();
reactParams.put("session_id", sessionId);
allParams.put("session_id", sessionId);
Copy link
Collaborator

Choose a reason for hiding this comment

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

any reason for not adding session_id to allParams in the above if conditions

Comment on lines +703 to +715
if (memory instanceof ConversationIndexMemory) {
saveTraceData(
(ConversationIndexMemory) memory,
memory.getType(),
stepToExecute,
results.get(STEP_RESULT_FIELD),
conversationId,
false,
parentInteractionId,
traceNumber,
"PlanExecuteReflect Agent"
);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

are we not storing traceData for agentCore?

log.info("Skipping interaction save for memory type: {}", memory.getClass().getSimpleName());
List<ModelTensors> finalModelTensors = createModelTensors(
memory.getConversationId(),
reactAgentMemoryId,
Copy link
Collaborator

Choose a reason for hiding this comment

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

reactAgentMemoryId is passed twice, this should be the memory_id of the conversation itself, unsure how agentcore is handling planner/executor memories, is this intentional?

Comment on lines +986 to +989
if (finalResult != null && !finalResult.isEmpty()) {
// Only add response tensor for non-ConversationIndexMemory cases
// ConversationIndexMemory handles this in the calling method
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

this condition does nothing

} else {
log
.warn(
"⚠️ NO RECORDS FOUND: sessionId={}, memoryId={} - This may indicate session mismatch or no events saved yet",
Copy link
Collaborator

@b4sjoo b4sjoo Sep 3, 2025

Choose a reason for hiding this comment

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

Could you please remove those emojis in logs to make it look more product ready?

public void getMessages(ActionListener<List<Interaction>> listener) {
log
.info(
"🔍 RETRIEVE FOR COMPATIBILITY START: memorySessionId={}, agentId={}, memoryId={}",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here

bedrockClient.listMemoryRecords(getMemoryId(), this.sessionId, this.agentId, ActionListener.wrap(records -> {
log
.info(
"📥 COMPATIBILITY RESPONSE: Found {} records for sessionId={}, memoryId={}",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here

for (BedrockAgentCoreMemoryRecord record : records) {
log
.info(
"📋 CONVERTING RECORD: type={}, content='{}', sessionId={}",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here


@Override
public void getMessages(String id, ActionListener<BedrockAgentCoreMemoryRecord> listener) {
log.info("RETRIEVE REQUEST START: requestedSessionId={}, memorySessionId={}, memoryId={}", id, this.sessionId, getMemoryId());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems log too detailed, considering downgrade it to DEBUG

@dhrubo-os dhrubo-os temporarily deployed to ml-commons-cicd-env September 3, 2025 22:42 — with GitHub Actions Inactive
@dhrubo-os dhrubo-os temporarily deployed to ml-commons-cicd-env September 3, 2025 22:42 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants