Skip to content

Control inversion cutover#1770

Draft
javier-aliaga wants to merge 9 commits into
dapr:masterfrom
javier-aliaga:control-inversion-cutover
Draft

Control inversion cutover#1770
javier-aliaga wants to merge 9 commits into
dapr:masterfrom
javier-aliaga:control-inversion-cutover

Conversation

@javier-aliaga

Copy link
Copy Markdown
Contributor

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:

  • Code compiles correctly
  • Created/updated tests
  • Extended the documentation

… 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

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.86%. Comparing base (2d06cb4) to head (c1eb379).
⚠️ Report is 2 commits behind head on master.

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.
📢 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.

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.

1 participant