Skip to content

feat(aws): agentcore harness adapter#7287

Draft
tshepomaredi wants to merge 5 commits into
mainfrom
tshepo-agentcore-harness-adapter
Draft

feat(aws): agentcore harness adapter#7287
tshepomaredi wants to merge 5 commits into
mainfrom
tshepo-agentcore-harness-adapter

Conversation

@tshepomaredi

Copy link
Copy Markdown
Contributor

Description

This PR adds AWS Bedrock AgentCore Harness integration to the agentic-ai framework, enabling BPMN ad-hoc subprocesses to use AWS-managed AI agents (AgentCore Harness) with full visibility of custom in-line tool calls as BPMN element activations.

Key features

  • Introduces AgentCoreHarnessAdapter implementing AiFrameworkAdapter for Harness API integration
  • Adds "AgentCore Managed Agent" element template for Camunda Modeler
  • Inner BPMN elements become inline_function tools, giving Camunda control over tool execution
  • Built-in Harness tools (shell, browser, code interpreter) can be used alongside custom BPMN tools
  • Supports allowedTools configuration to scope which tools the agent can use

Related issues

closes #

Checklist

  • Backport labels are added if these code changes should be backported. No backport label is added to the latest
    release, as this branch will be rebased onto main before the next release. Example backport labels:
    • backport stable/8.8: for changes that should be included in the next 8.8.x release.
    • or backport release-8.8.7: for changes that should be included in the specific release 8.8.7, and this
      release has already been created. The release branch will be merged back into stable/8.8 later, so the change
      will be included in future 8.8.x releases as well.
  • Tests/Integration tests for the changes have been added if applicable.
  • If the change requires a documentation update, it has been added to the appropriate section in the documentation.

Add initial implementation of AgentCoreHarnessAdapter that implements
AiFrameworkAdapter interface for AWS Bedrock AgentCore Harness integration.

Components:
- AgentCoreHarnessAiFrameworkChatResponse: Response record with session ID
- HarnessMessageConverter: Converts Camunda messages to/from Harness format
- HarnessToolConverter: Converts ToolDefinition to HarnessTool (inline_function)
- AgentCoreHarnessAdapter: Main adapter calling InvokeHarness API

The adapter uses inline_function tools so Harness returns tool calls back
to Camunda for BPMN element activation, preserving visibility and control.
- Add AgentCoreHarnessJobWorker and AgentCoreHarnessRequest for ad-hoc subprocess
- Add element template for 'AgentCore Managed Agent' in modeler
- Wire up Spring bean configuration in AgenticAiConnectorsAutoConfiguration
- Handle stopReason from Harness response (tool_use vs end_turn)
- Filter tool calls to only activate BPMN elements for inline_function tools
- Built-in tools (shell, browser) are executed by Harness internally
- Add allowedTools support to scope which tools Harness can use
- Add INFO logging for debugging Harness invocations
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

}

/** Accumulates data from streaming Harness response events. */
private class HarnessResponseData {
textBuilder.append(text);
}

void startToolUse(HarnessContentBlock.Builder toolUseBuilder) {
- Add HarnessToolConverterTest (7 tests)
- Add HarnessMessageConverterTest (12 tests)
- Cover tool definition conversion, message conversion, and error handling
@tshepomaredi tshepomaredi marked this pull request as ready for review May 20, 2026 09:56
@tshepomaredi tshepomaredi requested review from a team as code owners May 20, 2026 09:56
@tshepomaredi tshepomaredi self-assigned this May 20, 2026
@@ -0,0 +1,247 @@
{
"$schema": "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json",
"name": "AgentCore Managed Agent",

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.

❓ should we name it Amazon Bedrock AgentCore Managed Agent?

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.

we should also highlight it as an Alpha Feature while the AgentCore Harness itself is still in Preview.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

"name": "AgentCore Managed Agent",
"id": "io.camunda.connectors.agenticai.agentcore.harness.v1",
"description": "Drive an AWS Bedrock AgentCore Harness through a re-entrant tool-call loop, exposing the AHSP inner elements as inline_function tools.",
"keywords": ["AI", "AI Agent", "AWS", "AgentCore", "Harness", "Bedrock"],

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.

Suggested change
"keywords": ["AI", "AI Agent", "AWS", "AgentCore", "Harness", "Bedrock"],
"keywords": ["AI", "AI Agent", "Amazon", "AWS", "AgentCore", "Harness", "Bedrock"],

🔧 we should add Amazon as a keyword

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

"value": "bpmn:AdHocSubProcess"
},
"engines": {
"camunda": "^8.9"

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.

Suggested change
"camunda": "^8.9"
"camunda": "^8.10"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

LOGGER.trace("Activating tool {}: {}", toolCall.metadata().name(), toolCall);
} else {
LOGGER.debug("Activating tool {}", toolCall.metadata().name());
LOGGER.info("Activating tool {}", toolCall.metadata().name());

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.

❓ do we need that log on the info level?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reverted to debug. The info level was added during development for debugging

AgentCoreHarnessJobWorker.USER_PROMPT_VARIABLE,
AgentCoreHarnessJobWorker.MAX_ITERATIONS_VARIABLE
})
public class AgentCoreHarnessJobWorker implements AgentConnectorFunction {

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.

🔧 we should actually start to call it AgentCoreHarnessSubProcess to begin getting rid of the JobWorker suffix.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

✅ . Renamed to AgentCoreHarnessSubProcess and updated constants from JOB_WORKER_NAME/TYPE to CONNECTOR_NAME/TYPE

agentContext,
toolCallResults,
null, // provider is not used for Harness
new JobWorkerAgentRequestData(

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.

💭 I think this shows that we need to adjust the JobWorkerExecutionContext to maybe have a different type of AgentRequest that it can carry, as currently you are glueing here a lot of data to a completely different execution model.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

True, this is a workaround to reuse the existing JobWorkerAgentRequestHandler. A cleaner approach would be to introduce a more generic AgentExecutionContext, or something that doesn't assume the Langchain provider model. I'd suggest we track this as a follow-up refactor to keep this PR focused on the Harness integration. WDYT?

@NotBlank String harnessArn, String region, List<String> allowedTools) {

/** Extract region from ARN if not explicitly provided. */
public String effectiveRegion() {

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.

💭 Nice feature, but currently i think the region is an explicity and mandatory config param, which we should also enforce in such a case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The region inference from ARN was added for convenience since the ARN always contains the region (arn:aws:bedrock-agentcore:REGION:ACCOUNT:harness/NAME). But I can make it mandatory for consistency with other AWS connectors.

updatedAgentContext, assistantMessage, sessionId);
}

private String getOrCreateSessionId(AgentContext agentContext) {

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.

❓ Is the session subject to timeouts? Can we restore sessions or is it eternal until we close it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Per AWS documentation, the runtimeSessionId is used for conversation continuity within a Harness invocation session. The session is managed by Harness and persists across multiple InvokeHarness calls with the same session ID. I'll add a comment documenting this behavior. Regarding timeouts, this depends on the Harness config AWS, the session ID itself doesn't expire but the underlying Harness session may have idle timeouts configured.

return responseData;
}

private AssistantMessage buildAssistantMessage(

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.

🔧 Likely this should also move to the HarnessMessageConverter somehow

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. The challenge is that buildAssistantMessage needs access to inlineToolNames (the set of BPMN element names) to filter tool calls, which is context the converter doesn't currently have. I can either:

  1. Pass inlineToolNames as a parameter to the converter
  2. Keep filtering in the adapter and move only the message building to the converter

WDYT?

* @param toolUseBlock the Harness tool use block
* @return Camunda ToolCall
*/
public ToolCall toToolCall(HarnessToolUseBlock toolUseBlock) {

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.

❓ Where is this method being used? I can't see it being used here besides the test class.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You're right it was created anticipating we'd need to convert HarnessToolUseBlock from the response but we don't need it so I'll remove it.

AwsBasicCredentials.create(staticAuth.accessKey(), staticAuth.secretKey());
builder.credentialsProvider(StaticCredentialsProvider.create(credentials));
}
case AwsAuthentication.AwsDefaultCredentialsChainAuthentication ignored ->
builder.credentialsProvider(StaticCredentialsProvider.create(credentials));
}
case AwsAuthentication.AwsDefaultCredentialsChainAuthentication ignored ->
builder.credentialsProvider(DefaultCredentialsProvider.create());
}
case AwsAuthentication.AwsDefaultCredentialsChainAuthentication ignored ->
builder.credentialsProvider(DefaultCredentialsProvider.create());
case AwsAuthentication.AwsApiKeyAuthentication ignored ->
- Rename template to 'Amazon Bedrock AgentCore Managed Agent (Alpha)'
- Add [Alpha] prefix to description and 'Amazon' keyword
- Update engine version to ^8.10
- Revert log level from INFO to DEBUG
- Rename AgentCoreHarnessJobWorker to AgentCoreHarnessSubProcess
- Add session timeout documentation comment
- Remove unused toToolCall method from HarnessMessageConverter
@tshepomaredi tshepomaredi force-pushed the tshepo-agentcore-harness-adapter branch from 228f99f to aba3ff4 Compare May 29, 2026 11:17
@nikonovd nikonovd removed the request for review from mathias-vandaele June 1, 2026 12:12
@maff maff marked this pull request as draft June 2, 2026 09:19
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.

6 participants