-
Notifications
You must be signed in to change notification settings - Fork 227
Quarkus + Langchain4j Dapr Workflows extension + Agent registry #1693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
9943d89
eee2076
5478a02
ffb8a17
ad054ec
32b5bb9
8fa3e89
91384b7
0777814
c216390
6fdb204
3bf62ab
57dc653
dd66032
0fa83c4
9aa082c
6a70c99
07f3e24
3138679
9cd675d
6391fdd
90f79e1
42a8831
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| name: Quarkus Agentic Build | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - master | ||
| - release-quarkus-* | ||
| paths: | ||
| - 'quarkus/**' | ||
| tags: | ||
| - quarkus-v* | ||
|
|
||
| pull_request: | ||
| branches: | ||
| - master | ||
| - release-quarkus-* | ||
| paths: | ||
| - 'quarkus/**' | ||
|
|
||
| jobs: | ||
| build: | ||
| name: "Build & Test" | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 30 | ||
| env: | ||
| JDK_VER: 17 | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
| - name: Set up OpenJDK ${{ env.JDK_VER }} | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| distribution: 'temurin' | ||
| java-version: ${{ env.JDK_VER }} | ||
| - name: Build quarkus modules | ||
| run: | | ||
| cd quarkus | ||
| ../mvnw clean install -B -q -DskipITs=true | ||
| - name: Upload test reports | ||
| if: always() | ||
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: quarkus-test-reports | ||
| path: quarkus/**/target/surefire-reports/ | ||
|
|
||
| publish: | ||
| runs-on: ubuntu-latest | ||
| needs: [ build ] | ||
| timeout-minutes: 30 | ||
| env: | ||
| JDK_VER: 17 | ||
| OSSRH_USER_TOKEN: ${{ secrets.OSSRH_USER_TOKEN }} | ||
| OSSRH_PWD_TOKEN: ${{ secrets.OSSRH_PWD_TOKEN }} | ||
| GPG_KEY: ${{ secrets.GPG_KEY }} | ||
| GPG_PWD: ${{ secrets.GPG_PWD }} | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
| - name: Set up OpenJDK ${{ env.JDK_VER }} | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| distribution: 'temurin' | ||
| java-version: ${{ env.JDK_VER }} | ||
| - name: Get quarkus version | ||
| run: | | ||
| QUARKUS_VERSION=$(./mvnw -B -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec -f quarkus/pom.xml) | ||
| echo "QUARKUS_VERSION=$QUARKUS_VERSION" >> $GITHUB_ENV | ||
| - name: Is SNAPSHOT release ? | ||
| if: contains(github.ref, 'master') && contains(env.QUARKUS_VERSION, '-SNAPSHOT') | ||
| run: | | ||
| echo "DEPLOY_OSSRH=true" >> $GITHUB_ENV | ||
| - name: Is Release version ? | ||
| if: startsWith(github.ref, 'refs/tags/quarkus-v') && !contains(env.QUARKUS_VERSION, '-SNAPSHOT') | ||
| run: | | ||
| echo "DEPLOY_OSSRH=true" >> $GITHUB_ENV | ||
| - name: Publish to ossrh | ||
| if: env.DEPLOY_OSSRH == 'true' | ||
| run: | | ||
| echo ${{ secrets.GPG_PRIVATE_KEY }} | base64 -d > private-key.gpg | ||
| export GPG_TTY=$(tty) | ||
| gpg --batch --import private-key.gpg | ||
| cd quarkus | ||
| ../mvnw -V -B -Dgpg.skip=false -DskipTests -s ../settings.xml deploy |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| name: Quarkus Agentic Release | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| rel_version: | ||
| description: 'Release version (examples: 0.1.0, 0.2.0-rc-1, 0.2.0-SNAPSHOT)' | ||
| required: true | ||
| type: string | ||
|
|
||
| jobs: | ||
| create-release: | ||
| name: Creates quarkus release tag | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| JDK_VER: '17' | ||
| steps: | ||
| - name: Check out code | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.DAPR_BOT_TOKEN }} | ||
| persist-credentials: false | ||
| - name: Set up OpenJDK ${{ env.JDK_VER }} | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| distribution: 'temurin' | ||
| java-version: ${{ env.JDK_VER }} | ||
| - name: Update quarkus version and tag | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.DAPR_BOT_TOKEN }} | ||
| run: | | ||
| set -ue | ||
| REL_VERSION="${{ inputs.rel_version }}" | ||
|
|
||
| git config user.email "daprweb@microsoft.com" | ||
| git config user.name "Dapr Bot" | ||
| git remote set-url origin https://x-access-token:${{ secrets.DAPR_BOT_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git | ||
|
|
||
| # Update version in all quarkus pom.xml files | ||
| cd quarkus | ||
| ../mvnw versions:set -DnewVersion=$REL_VERSION -DprocessDependencies=true | ||
| cd .. | ||
|
|
||
| if [[ "$REL_VERSION" == *-SNAPSHOT ]]; then | ||
| git commit -s -m "Update quarkus version to ${REL_VERSION}" -a | ||
| git push origin master | ||
| echo "Updated master with quarkus version ${REL_VERSION}." | ||
| else | ||
| git commit -s -m "Release quarkus-v${REL_VERSION}" -a | ||
| git tag "quarkus-v${REL_VERSION}" | ||
| git push origin master | ||
| git push origin "quarkus-v${REL_VERSION}" | ||
| echo "Tagged and pushed quarkus-v${REL_VERSION}." | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ | |
| <grpc.version>1.79.0</grpc.version> | ||
| <protobuf.version>3.25.5</protobuf.version> | ||
| <dapr.proto.baseurl>https://raw.githubusercontent.com/dapr/dapr/v1.17.0/dapr/proto</dapr.proto.baseurl> | ||
| <durabletask.proto.url>https://raw.githubusercontent.com/dapr/durabletask-protobuf/main/protos/orchestrator_service.proto</durabletask.proto.url> | ||
| <durabletask.proto.url>https://raw.githubusercontent.com/dapr/durabletask-protobuf/5bbe020faa18c66ff1cd1e21d5fa58a32f4f735b/protos/orchestrator_service.proto</durabletask.proto.url> | ||
| <dapr.sdk.version>1.18.0-SNAPSHOT</dapr.sdk.version> | ||
| <os-maven-plugin.version>1.7.1</os-maven-plugin.version> | ||
| <maven-dependency-plugin.version>3.8.1</maven-dependency-plugin.version> | ||
|
|
@@ -38,9 +38,9 @@ | |
| <maven-site-plugin.version>3.12.1</maven-site-plugin.version> | ||
| <maven-project-info-reports-plugin.version>3.7.0</maven-project-info-reports-plugin.version> | ||
| <maven-jar-plugin.version>3.4.2</maven-jar-plugin.version> | ||
| <maven.compiler.source>11</maven.compiler.source> | ||
| <maven.compiler.target>11</maven.compiler.target> | ||
| <maven.compiler.release>11</maven.compiler.release> | ||
| <maven.compiler.source>17</maven.compiler.source> | ||
| <maven.compiler.target>17</maven.compiler.target> | ||
| <maven.compiler.release>17</maven.compiler.release> | ||
| <maven.deploy.skip>true</maven.deploy.skip> | ||
| <jackson.version>2.16.2</jackson.version> | ||
| <gpg.skip>true</gpg.skip> | ||
|
|
@@ -715,6 +715,7 @@ | |
| <!-- We are following test containers artifact convention on purpose, don't rename --> | ||
| <module>testcontainers-dapr</module> | ||
| <module>durabletask-client</module> | ||
| <module>quarkus</module> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This new module should be independent from dapr-sdk and have its own release process
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can send this code to quarkus-Dapr. @yaron2 which comments, can you be more specific?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets keep it here, but not as a module of the sdk, it will have a different release process |
||
| </modules> | ||
|
|
||
| <profiles> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| # Quarkus Agentic Dapr | ||
|
|
||
| A Quarkus extension that bridges [LangChain4j's agentic framework](https://docs.langchain4j.dev/) with [Dapr Workflows](https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-overview/) for durable, observable AI agent orchestration. | ||
|
|
||
| ## What it does | ||
|
|
||
| Every LLM call and tool call becomes a **durable Dapr Workflow activity**. If the process crashes, completed activities are recovered from the workflow history. Agent orchestration (sequential, parallel, loop, conditional) is backed by Dapr Workflows with parent-child hierarchy. | ||
|
|
||
| | Capability | Without Dapr | With `quarkus-agentic-dapr` | | ||
| |---|---|---| | ||
| | Durability | Lost on crash | Full workflow history persisted | | ||
| | Observability | Logs only | Dapr dashboard + per-activity tracking | | ||
| | Tool call audit trail | None | Every call recorded with inputs/outputs | | ||
| | LLM call audit trail | None | Every LLM request/response recorded | | ||
| | Code changes | — | **None** — just swap the dependency | | ||
|
|
||
| ## Modules | ||
|
|
||
| ``` | ||
| quarkus/ | ||
| ├── runtime/ # Core extension (interceptors, workflows, activities) | ||
| ├── deployment/ # Build-time processing (annotation scanning, CDI decorators) | ||
| ├── quarkus-agentic-dapr-agents-registry/ # Optional: registers agents in Dapr state store | ||
| ├── quarkus-langchain4j-dapr/ # Optional: Dapr Conversation API as ChatModel provider | ||
| └── examples/ # Built-in examples | ||
| ``` | ||
|
|
||
| ## Supported Agent Types | ||
|
|
||
| All 5 LangChain4j orchestration types are supported: | ||
|
|
||
| | Annotation | Dapr Workflow | | ||
| |------------|---------------| | ||
| | `@Agent` | `AgentRunWorkflow` (per-agent ReAct loop) | | ||
| | `@SequenceAgent` | `SequentialOrchestrationWorkflow` | | ||
| | `@ParallelAgent` | `ParallelOrchestrationWorkflow` | | ||
| | `@LoopAgent` | `LoopOrchestrationWorkflow` | | ||
| | `@ConditionalAgent` | `ConditionalOrchestrationWorkflow` | | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ### 1. Add the dependency | ||
|
|
||
| ```xml | ||
| <dependency> | ||
| <groupId>io.dapr.quarkus</groupId> | ||
| <artifactId>quarkus-agentic-dapr</artifactId> | ||
| <version>0.1.0-SNAPSHOT</version> | ||
| </dependency> | ||
| ``` | ||
|
|
||
| ### 2. Configure | ||
|
|
||
| ```properties | ||
| quarkus.dapr.devservices.enabled=false | ||
| quarkus.dapr.workflow.enabled=false | ||
|
|
||
| # Dapr sidecar endpoints | ||
| dapr.grpc.endpoint=${DAPR_GRPC_ENDPOINT:http://localhost:40001} | ||
| dapr.http.endpoint=${DAPR_HTTP_ENDPOINT:http://localhost:3500} | ||
| ``` | ||
|
|
||
| ### 3. Write agents (standard LangChain4j — no Dapr-specific code) | ||
|
|
||
| ```java | ||
| public interface WeatherAssistant { | ||
|
|
||
| @ToolBox(WeatherTools.class) | ||
| @UserMessage("Check the weather in {{city}}") | ||
| @Agent(name = "weather-assistant", outputKey = "weather") | ||
| String checkWeather(@V("city") String city); | ||
| } | ||
| ``` | ||
|
|
||
| ### 4. Run with Dapr | ||
|
|
||
| ```bash | ||
| # Terminal 1: Dapr sidecar | ||
| dapr run --app-id my-agent --dapr-grpc-port 40001 --dapr-http-port 3500 \ | ||
| --resources-path ./components | ||
|
|
||
| # Terminal 2: Quarkus app | ||
| DAPR_GRPC_ENDPOINT=http://localhost:40001 \ | ||
| DAPR_HTTP_ENDPOINT=http://localhost:3500 \ | ||
| mvn quarkus:dev -Ddebug=false | ||
| ``` | ||
|
|
||
| ## LLM Provider Options | ||
|
|
||
| ### Ollama (direct) | ||
| ```properties | ||
| quarkus.langchain4j.ollama.chat-model.model-id=llama3.1:8b | ||
| ``` | ||
|
|
||
| ### Dapr Conversation API (provider-agnostic) | ||
| ```properties | ||
| quarkus.langchain4j.chat-model.provider=dapr-conversation | ||
| quarkus.langchain4j.dapr.component-name=llm | ||
| ``` | ||
|
|
||
| Swap LLM providers by changing the Dapr component YAML — no Java code changes. | ||
|
|
||
| ## Example Project | ||
|
|
||
| See [travel-planner-agents](https://github.com/javier-aliaga/travel-planner-agents) for a complete example with all agent types, Makefile targets, and Dapr components. | ||
|
|
||
| ## Known Limitations | ||
|
|
||
| - **Nested composites**: `@ParallelAgent` inside `@SequenceAgent` is unstable (input type mismatch) | ||
| - **Crash recovery**: Workflow history survives but mid-agent resumption requires future work | ||
| - **Small models**: llama3.2 (3B) sometimes malforms tool call arguments; llama3.1:8b+ recommended |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <parent> | ||
| <groupId>io.dapr.quarkus</groupId> | ||
| <artifactId>dapr-quarkus-agentic-parent</artifactId> | ||
| <version>0.1.0-SNAPSHOT</version> | ||
| <relativePath>../pom.xml</relativePath> | ||
| </parent> | ||
|
|
||
| <artifactId>quarkus-agentic-dapr-deployment</artifactId> | ||
| <name>Quarkus Agentic Dapr - Deployment</name> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>io.quarkiverse.dapr</groupId> | ||
| <artifactId>quarkus-dapr-deployment</artifactId> | ||
| <version>${quarkus-dapr.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.quarkiverse.langchain4j</groupId> | ||
| <artifactId>quarkus-langchain4j-agentic-deployment</artifactId> | ||
| <version>${quarkus-langchain4j.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.quarkus</groupId> | ||
| <artifactId>quarkus-arc-deployment</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.quarkus.gizmo</groupId> | ||
| <artifactId>gizmo</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.dapr.quarkus</groupId> | ||
| <artifactId>quarkus-agentic-dapr</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.apache.maven.plugins</groupId> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <version>3.13.0</version> | ||
| <configuration> | ||
| <annotationProcessorPaths> | ||
| <path> | ||
| <groupId>io.quarkus</groupId> | ||
| <artifactId>quarkus-extension-processor</artifactId> | ||
| <version>${quarkus.version}</version> | ||
| </path> | ||
| </annotationProcessorPaths> | ||
| </configuration> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| </project> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is very important to be sure that the extension can run in native mode, I think we need to add it here.