Control inversion cutover#1770
Draft
javier-aliaga wants to merge 9 commits into
Draft
Conversation
… Workflows Add quarkus-agentic-dapr, a Quarkus extension that runs LangChain4j declarative agents as Dapr Workflows (control inversion). Each agent's ReAct loop runs as a workflow; the only non-deterministic steps — the model call and each tool call — are the agent-llm/agent-tool activities, so all agent state lives in workflow history. Crash recovery (per-call replay), horizontal scale (replica-agnostic activities), and observability follow. - runtime: ReActAgentWorkflow + durable-sequence/parallel/loop/conditional composites that call their children directly; AgentMethodMeta recursive node model with full-state-map propagation for nested composites; @output combiner and structured record returns; @ActivationCondition all-matching conditional routing; ToolRegistry + AgentToolClassRegistry; DaprWorkflowRuntimeRecorder. - deployment: annotation scanning + a drop-in entry point that replaces each agent interface's AiServices-built bean with a durable-workflow proxy (native proxy registered); unchanged user @agent interfaces. - build: module wiring, CI workflows, spotbugs exclusions.
Add quarkus-langchain4j-dapr: a LangChain4j ChatModel backed by the Dapr Conversation API, so the LLM provider is selected by Dapr component YAML (no Java changes to swap providers). Forwards tool specifications and tool_calls, and surfaces request/response for observability.
Persist LangChain4j's AgenticScope (the shared multi-agent state) and chat memory to a Dapr state store — the LangChain4j equivalent of a LangGraph checkpointer — so agentic state survives restarts and is shareable across replicas. - DaprAgenticScopeStore + AgenticScopeStoreInitializer (registers with LangChain4j's AgenticScopePersister at startup). - KeyValueChatMemoryStore over the Dapr state API.
Add quarkus-agentic-dapr-agents-registry: registers each agent's metadata in a Dapr state store at startup (name, type, description, tools), so LangChain4j agents are discoverable by the broader dapr-agents ecosystem. Composite agents are registered with their LangChain4j orchestration type.
Add runnable examples — leaf, sequence, parallel (+@output), loop, conditional, nested composites, and tool-calling agents — exercised by @QuarkusTest integration tests against Dapr dev services. README documents the control-inversion architecture, the agent-type → workflow mapping, and per-call crash recovery.
…amily Unify all module artifactIds under quarkus-langchain4j-dapr-* and nest the agentic extension's runtime+deployment under a parent module, matching the LLM extension's layout: - quarkus-agentic-dapr (+ -deployment) -> quarkus-langchain4j-dapr-agentic (nested) - quarkus-langchain4j-dapr -> quarkus-langchain4j-dapr-llm - quarkus-agentic-dapr-agents-registry -> quarkus-langchain4j-dapr-registry - examples artifact -> quarkus-langchain4j-dapr-examples Also updates the deployment processor's runtime-index artifactId, the extension descriptors, README, and example javadoc to match.
Replace AgentToolActivity's hand-rolled JSON-argument binding with LangChain4j's DefaultToolExecutor — the same binder AiServices uses — gaining @p support and faithful binding of nested/complex types. An unknown (hallucinated) tool, or a binding/execution failure, now returns the error text as the tool result so the ReAct loop can self-correct, instead of crashing the workflow. Removes the now-dead ToolRegistry.invokeTool.
Replace the flat {{var}} string replace with LangChain4j's PromptTemplate — the
same engine quarkus-langchain4j AiServices uses — supporting {{it}}, property
navigation and strict missing-variable checking. Rendering stays a pure function
of the captured call state; wall-clock template variables (current_date/time)
are unsupported because they would break workflow-replay determinism.
…onents Structured output: for a non-String agent return type, append ServiceOutputParser output-format instructions at the proxy entry and parse the result with ServiceOutputParser — the same path AiServices uses — instead of a raw Jackson readValue. Chat memory: detect a @memoryid parameter reflectively at the proxy; load the prior conversation at the entry (captured into the workflow input, so it stays replay-stable) and persist the turn via a new idempotent memory-save activity (replace-with-windowed-history, safe under at-least-once delivery). Backed by the existing KeyValueChatMemoryStore. Agents without @memoryid stay stateless per call, exactly as AiServices is with no chat memory configured.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1770 +/- ##
=========================================
Coverage 76.86% 76.86%
Complexity 2298 2298
=========================================
Files 243 243
Lines 7141 7141
Branches 745 745
=========================================
Hits 5489 5489
Misses 1287 1287
Partials 365 365 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Please explain the changes you've made
Issue reference
We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.
Please reference the issue this PR will close: #[issue number]
Checklist
Please make sure you've completed the relevant tasks for this PR, out of the following list: