1515 */
1616package io .serverlessworkflow .fluent .agentic .langchain4j ;
1717
18+ import static io .serverlessworkflow .fluent .agentic .AgentWorkflowBuilder .workflow ;
19+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newAstrologyAgent ;
20+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newAudienceEditor ;
21+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newCreativeWriter ;
22+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newFoodExpert ;
23+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newMovieExpert ;
24+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newStyleEditor ;
25+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newStyleScorer ;
26+ import static io .serverlessworkflow .fluent .agentic .AgentsUtils .newSummaryStory ;
27+ import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .*;
1828import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .AudienceEditor ;
1929import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .CreativeWriter ;
2030import static io .serverlessworkflow .fluent .agentic .langchain4j .Agents .StyleEditor ;
2131import static io .serverlessworkflow .fluent .agentic .langchain4j .Models .BASE_MODEL ;
32+ import static org .junit .jupiter .api .Assertions .assertEquals ;
33+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
2234import static org .mockito .ArgumentMatchers .any ;
2335import static org .mockito .ArgumentMatchers .eq ;
2436import static org .mockito .Mockito .spy ;
2537import static org .mockito .Mockito .verify ;
2638
27- import dev .langchain4j .agentic .AgenticServices ;
2839import dev .langchain4j .agentic .UntypedAgent ;
40+ import dev .langchain4j .agentic .scope .AgenticScope ;
2941import dev .langchain4j .agentic .workflow .WorkflowAgentsBuilder ;
42+ import io .serverlessworkflow .fluent .agentic .AgenticServices ;
43+ import io .serverlessworkflow .fluent .agentic .AgentsUtils ;
44+ import java .util .List ;
3045import java .util .Map ;
46+ import java .util .function .Function ;
47+ import java .util .function .Predicate ;
48+ import java .util .stream .IntStream ;
3149import org .junit .jupiter .api .Test ;
3250
3351public class WorkflowAgentsIT {
@@ -38,21 +56,21 @@ void sequential_agents_tests() {
3856
3957 CreativeWriter creativeWriter =
4058 spy (
41- AgenticServices .agentBuilder (CreativeWriter .class )
59+ dev . langchain4j . agentic . AgenticServices .agentBuilder (CreativeWriter .class )
4260 .chatModel (BASE_MODEL )
4361 .outputName ("story" )
4462 .build ());
4563
4664 AudienceEditor audienceEditor =
4765 spy (
48- AgenticServices .agentBuilder (AudienceEditor .class )
66+ dev . langchain4j . agentic . AgenticServices .agentBuilder (AudienceEditor .class )
4967 .chatModel (BASE_MODEL )
5068 .outputName ("story" )
5169 .build ());
5270
5371 StyleEditor styleEditor =
5472 spy (
55- AgenticServices .agentBuilder (StyleEditor .class )
73+ dev . langchain4j . agentic . AgenticServices .agentBuilder (StyleEditor .class )
5674 .chatModel (BASE_MODEL )
5775 .outputName ("story" )
5876 .build ());
@@ -77,4 +95,123 @@ void sequential_agents_tests() {
7795 verify (audienceEditor ).editStory (any (), eq ("young adults" ));
7896 verify (styleEditor ).editStory (any (), eq ("fantasy" ));
7997 }
98+
99+ @ Test
100+ public void sequenceHelperTest () {
101+ var creativeWriter = newCreativeWriter ();
102+ var audienceEditor = newAudienceEditor ();
103+ var styleEditor = newStyleEditor ();
104+
105+ AgentsUtils .NovelCreator novelCreator =
106+ io .serverlessworkflow .fluent .agentic .AgenticServices .of (AgentsUtils .NovelCreator .class )
107+ .flow (workflow ("seqFlow" ).sequence (creativeWriter , audienceEditor , styleEditor ))
108+ .build ();
109+
110+ String story = novelCreator .createNovel ("dragons and wizards" , "young adults" , "fantasy" );
111+ assertNotNull (story );
112+ }
113+
114+ @ Test
115+ public void agentAndSequenceHelperTest () {
116+ var creativeWriter = newCreativeWriter ();
117+ var audienceEditor = newAudienceEditor ();
118+ var styleEditor = newStyleEditor ();
119+
120+ AgentsUtils .NovelCreator novelCreator =
121+ io .serverlessworkflow .fluent .agentic .AgenticServices .of (AgentsUtils .NovelCreator .class )
122+ .flow (workflow ("seqFlow" ).agent (creativeWriter ).sequence (audienceEditor , styleEditor ))
123+ .build ();
124+
125+ String story = novelCreator .createNovel ("dragons and wizards" , "young adults" , "fantasy" );
126+ assertNotNull (story );
127+ }
128+
129+ @ Test
130+ public void agentAndSequenceAndAgentHelperTest () {
131+ var creativeWriter = newCreativeWriter ();
132+ var audienceEditor = newAudienceEditor ();
133+ var styleEditor = newStyleEditor ();
134+ var summaryStory = newSummaryStory ();
135+
136+ AgentsUtils .NovelCreator novelCreator =
137+ io .serverlessworkflow .fluent .agentic .AgenticServices .of (AgentsUtils .NovelCreator .class )
138+ .flow (
139+ workflow ("seqFlow" )
140+ .agent (creativeWriter )
141+ .sequence (audienceEditor , styleEditor )
142+ .agent (summaryStory ))
143+ .build ();
144+
145+ String story = novelCreator .createNovel ("dragons and wizards" , "young adults" , "fantasy" );
146+ assertNotNull (story );
147+ }
148+
149+ @ Test
150+ public void parallelWorkflow () {
151+ var foodExpert = newFoodExpert ();
152+ var movieExpert = newMovieExpert ();
153+
154+ Function <AgenticScope , List <EveningPlan >> planEvening =
155+ input -> {
156+ List <String > movies = (List <String >) input .readState ("movies" );
157+ List <String > meals = (List <String >) input .readState ("meals" );
158+
159+ int max = Math .min (movies .size (), meals .size ());
160+ return IntStream .range (0 , max )
161+ .mapToObj (i -> new EveningPlan (movies .get (i ), meals .get (i )))
162+ .toList ();
163+ };
164+
165+ EveningPlannerAgent eveningPlannerAgent =
166+ AgenticServices .of (EveningPlannerAgent .class )
167+ .flow (workflow ("parallelFlow" ).parallel (foodExpert , movieExpert ).outputAs (planEvening ))
168+ .build ();
169+ List <EveningPlan > result = eveningPlannerAgent .plan ("romantic" );
170+ assertEquals (3 , result .size ());
171+ }
172+
173+ @ Test
174+ public void loopTest () {
175+ var creativeWriter = newCreativeWriter ();
176+ var scorer = newStyleScorer ();
177+ var editor = newStyleEditor ();
178+
179+ Predicate <AgenticScope > until = s -> s .readState ("score" , 0.0 ) >= 0.8 ;
180+
181+ StyledWriter styledWriter =
182+ AgenticServices .of (StyledWriter .class )
183+ .flow (workflow ("loopFlow" ).agent (creativeWriter ).loop (until , scorer , editor ))
184+ .build ();
185+
186+ String story = styledWriter .writeStoryWithStyle ("dragons and wizards" , "fantasy" );
187+ assertNotNull (story );
188+ }
189+
190+ @ Test
191+ public void humanInTheLoop () {
192+ var astrologyAgent = newAstrologyAgent ();
193+
194+ var askSign =
195+ new Function <AgenticScope , AgenticScope >() {
196+ @ Override
197+ public AgenticScope apply (AgenticScope holder ) {
198+ System .out .println ("What's your star sign?" );
199+ // var sign = System.console().readLine();
200+ holder .writeState ("sign" , "piscis" );
201+ return holder ;
202+ }
203+ };
204+
205+ String result =
206+ AgenticServices .of (Agents .HoroscopeAgent .class )
207+ .flow (
208+ workflow ("humanInTheLoop" )
209+ .inputFrom (askSign )
210+ // .tasks(tasks -> tasks.callFn(fn(askSign))) // TODO should work too
211+ .agent (astrologyAgent ))
212+ .build ()
213+ .invoke ("My name is Mario. What is my horoscope?" );
214+
215+ assertNotNull (result );
216+ }
80217}
0 commit comments