Skip to content

CAMEL-23952: Support executeToolsConcurrently for langchain4j-agent - #25228

Open
atiaomar1978-hub wants to merge 4 commits into
apache:mainfrom
atiaomar1978-hub:CAMEL-23952-execute-tools-concurrently
Open

CAMEL-23952: Support executeToolsConcurrently for langchain4j-agent#25228
atiaomar1978-hub wants to merge 4 commits into
apache:mainfrom
atiaomar1978-hub:CAMEL-23952-execute-tools-concurrently

Conversation

@atiaomar1978-hub

@atiaomar1978-hub atiaomar1978-hub commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

AI-generated on behalf of atiaomar1978-hub

  • Exposes AgentConfiguration.withExecuteToolsConcurrently() and withExecuteToolsConcurrently(Executor), wired into AbstractAgent.configureBuilder() for LangChain4j AiServices.
  • When concurrent execution is enabled without an explicit executor, LangChain4jAgentProducer registers a Camel-managed thread pool via ExecutorServiceManager (on a duplicated configuration so registry beans are not mutated) and shuts it down on component stop.
  • Builds on exchange-isolated Camel route tool execution (CAMEL-23944) so parallel tool calls are safe.
  • Documents concurrent tool mode in the langchain4j-agent component guide.

Review follow-up (Bugbot / Grok)

  • Fixed: Managed executor is no longer written into shared #agentConfiguration registry beans; producer uses AgentConfiguration.duplicate() for the build-time copy.
  • Added: Context stop/restart test for managed executor path; duplicate() unit test.

Test plan

  • AgentConfigurationTest (executeToolsConcurrently + duplicate)
  • LangChain4jAgentExecuteToolsConcurrentlyTest (parallel overlap, registry not mutated, restart)
  • mvn test -pl components/camel-ai/camel-langchain4j-agent -am -Dtest=LangChain4jAgentExecuteToolsConcurrentlyTest,AgentConfigurationTest

@atiaomar1978-hub

Copy link
Copy Markdown
Contributor Author

AI-generated comment on behalf of atiaomar1978-hub

Follow-up commit 16b9389254f addresses Bugbot/Grok review:

  • Registry safety: LangChain4jAgentProducer now builds agents from AgentConfiguration.duplicate() so the managed concurrent-tool executor is attached only to the producer-owned copy, not shared #agentConfiguration beans.
  • Tests: Added duplicate() coverage and a context stop/restart regression for the managed-executor path.

Re-ran LangChain4jAgentExecuteToolsConcurrentlyTest + AgentConfigurationTest — green.

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@atiaomar1978-hub

Copy link
Copy Markdown
Contributor Author

AI-generated comment on behalf of atiaomar1978-hub

Pushed a0102839 to fix the failing sourcecheck job (run 30468300277).

The build regenerated catalog docs from langchain4j-agent-component.adoc, but the committed copy under catalog/camel-catalog/src/generated/resources/.../langchain4j-agent-component.adoc was missing the new Concurrent tool execution section. That file is now synced with the component docs so git status stays clean after the build.

Please re-run or wait for CI on the latest commit.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-ai/camel-langchain4j-agent-api
  • components/camel-ai/camel-langchain4j-agent

🔬 Scalpel shadow comparison — Scalpel: 11 tested, 28 compile-only — current: 10 all tested

Maveniverse Scalpel detected 39 affected modules (current approach: 10).

⚠️ Modules only in Scalpel (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 11 modules (3 direct + 8 downstream), skip tests for 28 (generated code, meta-modules)

Modules Scalpel would test (11)
  • camel-catalog
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-langchain4j-agent
  • camel-langchain4j-agent-api
  • camel-launcher-container
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
Modules with tests skipped (28)
  • apache-camel
  • camel-allcomponents
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • components/camel-ai/camel-langchain4j-agent: 16 test(s) disabled on GitHub Actions
All tested modules (39 modules)
  • Camel :: AI :: LangChain4j :: Agent
  • Camel :: AI :: LangChain4j :: Agent :: API
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Catalog :: CSimple Maven Plugin (deprecated)
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Lucene (deprecated)
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@gnodet gnodet left a comment

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.

Well-structured PR. The core design is sound: duplicate() protects shared registry beans from mutation, Camel's ExecutorServiceManager manages the thread pool lifecycle correctly (doInit create, doStop shutdown), and the concurrency test genuinely validates parallel tool overlap using a CountDownLatch barrier + AtomicInteger high-water-mark. CI is green. No correctness issues — only convention cleanups below.

Findings

1. [Convention] Test methods use public and JUnit assertions instead of AssertJAgentConfigurationTest.java

The two new test methods (testDuplicateCopiesExecuteToolsConcurrentlySettings, testExecuteToolsConcurrently) use public visibility and JUnit assertions (assertTrue, assertSame, assertEquals, assertNull). Per project conventions: new test methods should be package-private and use AssertJ where it improves readability. Example migration:

@Test
void testExecuteToolsConcurrently() {
    AgentConfiguration config = new AgentConfiguration();
    assertThat(config.getExecuteToolsConcurrently()).isNull();
    assertThat(config.getExecuteToolsExecutor()).isNull();

    AgentConfiguration enabled = config.withExecuteToolsConcurrently();
    assertThat(enabled).isSameAs(config);
    assertThat(config.getExecuteToolsConcurrently()).isTrue();
    // ...
}

2. [Convention] FQCNs in test codeLangChain4jAgentExecuteToolsConcurrentlyTest.java

Two method signatures use fully-qualified class names instead of imports:

  • bindToRegistry(org.apache.camel.spi.Registry registry) → import Registry
  • recordConcurrentEntry(String label, org.apache.camel.Exchange exchange) → import Exchange

3. [Nit] assertSame on autoboxed int is fragileAgentConfigurationTest.java

assertSame(original.getMaxToolCallingRoundTrips(), copy.getMaxToolCallingRoundTrips());

getMaxToolCallingRoundTrips() returns int, so both sides are autoboxed. For value 3 this works due to Integer caching (-128 to 127), but for values > 127 it would fail. The preceding assertEquals already validates the value — this line can be removed or changed to assertEquals/assertThat(...).isEqualTo(...).

4. [Suggestion] Tests leak Executors.newSingleThreadExecutor() instancesAgentConfigurationTest.java

Both new test methods create single-thread executors without shutdown, leaking non-daemon threads. Minor — won't cause test failures — but wrapping in try/finally with executor.shutdownNow() would be cleaner.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of Guillaume Nodet

Omar Atie and others added 4 commits July 30, 2026 09:22
Wire LangChain4j parallel tool execution through AgentConfiguration,
resolve a Camel-managed executor when none is supplied, and add tests
plus component documentation.

Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid mutating registry-held configuration when attaching the
Camel-managed concurrent tool pool; add duplicate() and a context
restart regression test.

Co-authored-by: Cursor <cursoragent@cursor.com>
Regenerate catalog copy of component adoc so sourcecheck passes after
executeToolsConcurrently documentation was added.

Co-authored-by: Cursor <cursoragent@cursor.com>
Migrate new AgentConfigurationTest methods to AssertJ, shut down test
executors, remove fragile assertSame on autoboxed int, and replace FQCNs
with imports in LangChain4jAgentExecuteToolsConcurrentlyTest.

Co-authored-by: Cursor <cursoragent@cursor.com>
@atiaomar1978-hub
atiaomar1978-hub force-pushed the CAMEL-23952-execute-tools-concurrently branch from a010283 to 3a5d72c Compare July 30, 2026 16:27
@atiaomar1978-hub

Copy link
Copy Markdown
Contributor Author

AI-generated comment on behalf of atiaomar1978-hub

Addressed @gnodet review in 3a5d72cc81c (rebased onto current main):

  1. AgentConfigurationTest — new concurrent-tool tests now use AssertJ, package-private visibility, and shut down test executors in finally; removed fragile assertSame on autoboxed int.
  2. LangChain4jAgentExecuteToolsConcurrentlyTest — replaced FQCNs with Registry and Exchange imports.
  3. Added assertj-core test dependency to camel-langchain4j-agent-api for the migrated assertions.

Re-ran AgentConfigurationTest (28 tests) + LangChain4jAgentExecuteToolsConcurrentlyTest (3 tests) — all green.

Ready for re-review.

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.

2 participants