Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void testSwitch() throws InterruptedException, ExecutionException {
tasks
.switchCase(
switchOdd ->
switchOdd.functions(
switchOdd.onPredicate(
item ->
item.when(CallTest::isOdd).then(FlowDirectiveEnum.END)))
.callFn(callJava -> callJava.function(CallTest::zero)))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.api.types.func;

import io.serverlessworkflow.api.types.EventData;
import java.util.Objects;
import java.util.function.Function;

public class EventDataFunction extends EventData {

public <T, R> EventData withFunction(Function<T, R> value) {
setObject(value);
return this;
}

public <T, R> EventData withFunction(Function<T, R> value, Class<T> argClass) {
Objects.requireNonNull(argClass);
setObject(new TypedFunction<>(value, argClass));
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2020-Present The Serverless Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.serverlessworkflow.api.types.func;

import io.serverlessworkflow.api.types.EventData;
import java.util.Objects;
import java.util.function.Predicate;

public class EventDataPredicate extends EventData {

public <T> EventDataPredicate withPredicate(Predicate<T> predicate) {
setObject(predicate);
return this;
}

public <T> EventDataPredicate withPredicate(Predicate<T> predicate, Class<T> clazz) {
Objects.requireNonNull(clazz);
setObject(new TypedPredicate<>(predicate, clazz));
return this;
}
}
10 changes: 10 additions & 0 deletions fluent/agentic/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@
<artifactId>serverlessworkflow-experimental-agentic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-json-jackson</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-impl-jackson</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,31 @@
import io.serverlessworkflow.api.types.AnyEventConsumptionStrategy;
import io.serverlessworkflow.api.types.ListenTask;
import io.serverlessworkflow.api.types.func.UntilPredicate;
import io.serverlessworkflow.fluent.spec.ListenTaskBuilder;
import io.serverlessworkflow.fluent.func.FuncListenToBuilder;
import io.serverlessworkflow.fluent.func.spi.ConditionalTaskBuilder;
import io.serverlessworkflow.fluent.spec.AbstractListenTaskBuilder;
import java.util.function.Predicate;

public class AgentListenTaskBuilder extends ListenTaskBuilder<AgentTaskItemListBuilder> {
public class AgentListenTaskBuilder
extends AbstractListenTaskBuilder<AgentTaskItemListBuilder, FuncListenToBuilder>
implements ConditionalTaskBuilder<AgentListenTaskBuilder> {

private UntilPredicate untilPredicate;

public AgentListenTaskBuilder() {
super(new AgentTaskItemListBuilder());
}

@Override
protected AgentListenTaskBuilder self() {
return this;
}

@Override
protected FuncListenToBuilder newEventConsumptionStrategyBuilder() {
return new FuncListenToBuilder();
}

public <T> AgentListenTaskBuilder until(Predicate<T> predicate, Class<T> predClass) {
untilPredicate = new UntilPredicate().withPredicate(predicate, predClass);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public interface Agents {
interface ChatBot {
@UserMessage(
"""
You are a happy chat bot, reply to my message:
{{userInput}}.
""")
You are a happy chat bot, reply to my message:
{{userInput}}.
""")
@Agent
String chat(@V("userInput") String userInput);
}
Expand All @@ -37,11 +37,11 @@ interface MovieExpert {

@UserMessage(
"""
You are a great evening planner.
Propose a list of 3 movies matching the given mood.
The mood is {{mood}}.
Provide a list with the 3 items and nothing else.
""")
You are a great evening planner.
Propose a list of 3 movies matching the given mood.
The mood is {{mood}}.
Provide a list with the 3 items and nothing else.
""")
@Agent
List<String> findMovie(@V("mood") String mood);
}
Expand All @@ -50,10 +50,10 @@ interface SettingAgent extends AgentSpecification {

@UserMessage(
"""
Create a vivid {{style}} setting. It should include the time period, the state of technology,
key locations, and a brief description of the world’s political or social situation.
Make it imaginative, atmospheric, and suitable for a {{style}} novel.
""")
Create a vivid {{style}} setting. It should include the time period, the state of technology,
key locations, and a brief description of the world’s political or social situation.
Make it imaginative, atmospheric, and suitable for a {{style}} novel.
""")
@Agent(
"Generates an imaginative setting including timeline, technology level, and world structure")
String invoke(@V("style") String style);
Expand All @@ -63,9 +63,9 @@ interface HeroAgent extends AgentSpecification {

@UserMessage(
"""
Invent a compelling protagonist for a {{style}} story. Describe their background, personality,
motivations, and any unique skills or traits.
""")
Invent a compelling protagonist for a {{style}} story. Describe their background, personality,
motivations, and any unique skills or traits.
""")
@Agent("Creates a unique and relatable protagonist with rich backstory and motivations.")
String invoke(@V("style") String style);
}
Expand All @@ -74,10 +74,10 @@ interface ConflictAgent extends AgentSpecification {

@UserMessage(
"""
Generate a central conflict or threat for a {{style}} plot. It can be external or
internal (e.g. moral dilemma, personal transformation).
Make it high-stakes and thematically rich.
""")
Generate a central conflict or threat for a {{style}} plot. It can be external or
internal (e.g. moral dilemma, personal transformation).
Make it high-stakes and thematically rich.
""")
@Agent("Proposes a central conflict or dramatic tension to drive a compelling narrative.")
String invoke(@V("style") String style);
}
Expand All @@ -86,8 +86,8 @@ interface FactAgent extends AgentSpecification {

@UserMessage(
"""
Generate a unique sci-fi fact about an alien civilization's {{goal}} environment or evolutionary history. Make it imaginative and specific.
""")
Generate a unique sci-fi fact about an alien civilization's {{goal}} environment or evolutionary history. Make it imaginative and specific.
""")
@Agent("Generates a core fact that defines the foundation of an civilization.")
String invoke(@V("fact") String fact);
}
Expand All @@ -96,10 +96,10 @@ interface CultureAgent extends AgentSpecification {

@UserMessage(
"""
Given the following sci-fi fact about an civilization, describe 3–5 unique cultural traits, traditions, or societal structures that naturally emerge from this environment.
Fact:
{{fact}}
""")
Given the following sci-fi fact about an civilization, describe 3–5 unique cultural traits, traditions, or societal structures that naturally emerge from this environment.
Fact:
{{fact}}
""")
@Agent("Derives cultural traits from the environmental/evolutionary fact.")
List<String> invoke(@V("fact") String fact);
}
Expand All @@ -108,10 +108,10 @@ interface TechnologyAgent extends AgentSpecification {

@UserMessage(
"""
Given the following sci-fi fact about an alien civilization, describe 3–5 technologies or engineering solutions they might have developed. Focus on tools, transportation, communication, and survival systems.
Fact:
{{fact}}
""")
Given the following sci-fi fact about an alien civilization, describe 3–5 technologies or engineering solutions they might have developed. Focus on tools, transportation, communication, and survival systems.
Fact:
{{fact}}
""")
@Agent("Derives plausible technological inventions from the fact.")
List<String> invoke(@V("fact") String fact);
}
Expand All @@ -120,9 +120,9 @@ interface StorySeedAgent extends AgentSpecification {

@UserMessage(
"""
You are a science fiction writer. Given the following title, come up with a short story premise. Describe the world, the central concept, and the thematic direction (e.g., dystopia, exploration, AI ethics).
Title: {{title}}
""")
You are a science fiction writer. Given the following title, come up with a short story premise. Describe the world, the central concept, and the thematic direction (e.g., dystopia, exploration, AI ethics).
Title: {{title}}
""")
@Agent("Generates a high-level sci-fi premise based on a title.")
String invoke(@V("title") String title);
}
Expand All @@ -131,10 +131,10 @@ interface PlotAgent extends AgentSpecification {

@UserMessage(
"""
Using the following premise, outline a three-act structure for a science fiction short story. Include a brief description of the main character, the inciting incident, the rising conflict, and the resolution.
Premise:
{{premise}}
""")
Using the following premise, outline a three-act structure for a science fiction short story. Include a brief description of the main character, the inciting incident, the rising conflict, and the resolution.
Premise:
{{premise}}
""")
@Agent("Transforms a premise into a structured sci-fi plot.")
String invoke(@V("premise") String premise);
}
Expand All @@ -143,10 +143,10 @@ interface SceneAgent extends AgentSpecification {

@UserMessage(
"""
Write the opening scene of a science fiction short story based on the following plot outline. Introduce the main character and immerse the reader in the setting. Use vivid, cinematic language.
Plot:
{{plot}}
""")
Write the opening scene of a science fiction short story based on the following plot outline. Introduce the main character and immerse the reader in the setting. Use vivid, cinematic language.
Plot:
{{plot}}
""")
@Agent("Generates the opening scene of the story from a plot outline.")
String invoke(@V("plot") String plot);
}
Expand All @@ -155,13 +155,13 @@ interface MeetingInvitationDraft extends AgentSpecification {

@UserMessage(
"""
You are a professional meeting invitation writer. Draft a concise and clear meeting invitation email based on the following details:
Subject: {{subject}}
Date: {{date}}
Time: {{time}}
Location: {{location}}
Agenda: {{agenda}}
""")
You are a professional meeting invitation writer. Draft a concise and clear meeting invitation email based on the following details:
Subject: {{subject}}
Date: {{date}}
Time: {{time}}
Location: {{location}}
Agenda: {{agenda}}
""")
@Agent("Drafts a professional meeting invitation email.")
String invoke(
@V("subject") String subject,
Expand All @@ -175,10 +175,63 @@ interface MeetingInvitationStyle extends AgentSpecification {

@UserMessage(
"""
You are a professional meeting invitation writer. Rewrite the following meeting invitation email to better fit the {{style}} style:
Original Invitation: {{invitation}}
""")
You are a professional meeting invitation writer. Rewrite the following meeting invitation email to better fit the {{style}} style:
Original Invitation: {{invitation}}
""")
@Agent("Edits a meeting invitation email to better fit a given style.")
String invoke(@V("invitation") String invitation, @V("style") String style);
}

interface EmailDrafter {

@UserMessage(
"""
You are a precise email drafting assistant.

GOAL
- Draft a professional email that achieves the stated purpose.
- Keep it concise and skimmable.

INPUT
recipient_name: {{recipientName}}
sender_name: {{senderName}}
purpose: {{purpose}} // e.g., follow-up, scheduling, proposal, apology, onboarding
key_points: {{keyPoints}} // bullet list or comma-separated facts
tone: {{tone}} // e.g., friendly, neutral, formal
length: {{length}} // short|medium
call_to_action: {{cta}} // e.g., "reply with a time", "confirm receipt", or empty
signature: {{signature}} // prebuilt block; do NOT invent
allowed_domains: {{allowedDomains}} // e.g., ["acme.com","example.com"]
known_links: {{links}} // URLs you may use; if not in allowed_domains, do not include

HARD RULES
- Never fabricate facts, prices, or promises.
- Only include links from allowed_domains and only those listed in known_links.
- Do not include internal/confidential URLs.
- If you lack a detail, write a neutral placeholder (e.g., "[DATE]").
- Keep subject <= 60 characters if possible.
- One clear CTA max.

OUTPUT
Return ONLY a compact JSON object with keys:
{
"subject": "...",
"body_plain": "...",
"links": ["..."] // subset of known_links, or empty
}
No markdown, no explanations, no extra text.
""")
@Agent("Drafts a new outbound email from structured inputs; returns JSON.")
String draftNew(
@V("recipientName") String recipientName,
@V("senderName") String senderName,
@V("purpose") String purpose,
@V("keyPoints") List<String> keyPoints,
@V("tone") String tone,
@V("length") String length,
@V("cta") String cta,
@V("signature") String signature,
@V("allowedDomains") List<String> allowedDomains,
@V("links") List<String> links);
}
}
Loading