DSL
You can also create agents using a DSL in Kotlin or Java.
This is useful for workflows where you want an atomic action that is complete in itself but may contain multiple steps or actions.
Standard Workflows
Section titled “Standard Workflows”There are a number of standard workflows, constructed by builders, that meet common requirements.
These can be used to create agents that will be exposed as Spring beans, or within @Action methods within other agents.
All are type safe.
As far as possible, they use consistent APIs.
SimpleAgentBuilder: The simplest agent, with no preconditions or postconditions.ScatterGatherBuilder: Fork join pattern for parallel processing.ConsensusBuilder: A pattern for reaching consensus among multiple sources. Specialization ofScatterGather.RepeatUntil: Repeats a step until a condition is met.RepeatUntilAcceptable: Repeats a step while a condition is met, with a separate evaluator providing feedback.
Creating a simple agent:
var agent = SimpleAgentBuilder .returning(Joke.class) (1) .running(tac -> tac.ai() (2) .withDefaultLlm() .createObject("Tell me a joke", Joke.class)) .buildAgent("joker", "This is guaranteed to return a dreadful joke"); (3)val agent = SimpleAgentBuilder .returning(Joke::class.java) (1) .running { tac -> tac.ai() (2) .withDefaultLlm() .createObject("Tell me a joke", Joke::class.java) } .buildAgent("joker", "This is guaranteed to return a dreadful joke") (3)- Specify the return type.
- specify the action to run. Takes a
SupplierActionContext<RESULT>OperationContextparameter allowing access to the currentAgentProcess. - Build an agent with the given name and description.
A more complex example:
@ActionFactChecks runAndConsolidateFactChecks( DistinctFactualAssertions distinctFactualAssertions, ActionContext context) { var llmFactChecks = properties.models().stream() .flatMap(model -> factCheckWithSingleLlm(model, distinctFactualAssertions, context)) .toList(); return ScatterGatherBuilder (1) .returning(FactChecks.class) (2) .fromElements(FactCheck.class) (3) .generatedBy(llmFactChecks) (4) .consolidatedBy(this::reconcileFactChecks) (5) .asSubProcess(context); (6) }@Actionfun runAndConsolidateFactChecks( distinctFactualAssertions: DistinctFactualAssertions, context: ActionContext): FactChecks { val llmFactChecks = properties.models .flatMap { model -> factCheckWithSingleLlm(model, distinctFactualAssertions, context) } return ScatterGatherBuilder (1) .returning(FactChecks::class.java) (2) .fromElements(FactCheck::class.java) (3) .generatedBy(llmFactChecks) (4) .consolidatedBy(this::reconcileFactChecks) (5) .asSubProcess(context) (6)}- Start building a scatter gather agent.
- Specify the return type of the overall agent.
- Specify the type of elements to be gathered.
- Specify the list of functions to run in parallel, each generating an element, here of type
FactCheck. - Specify a function to consolidate the results. In this case it will take a list of
FactCheckand return aFactCheckand return aFactChecksobject. - Build and run the agent as a subprocess of the current process. This is an alternative to
buildAgentshown in theSimpleAgentBuilderexample. The API is consistent.
Registering Agent beans
Section titled “Registering Agent beans”Whereas the @Agent annotation causes a class to be picked up immediately by Spring, with the DSL you’ll need an extra step to register an agent with Spring. As shown in the example below, any @Bean of Agent type results auto registration, just like declaring a class annotated with @Agent does.
@Configurationpublic class FactCheckerAgentConfiguration {
@Bean public Agent factChecker(FactCheckerProperties factCheckerProperties) { return factCheckerAgent( List.of( LlmOptions.create(AnthropicModels.CLAUDE_35_HAIKU).withTemperature(0.3), LlmOptions.create(AnthropicModels.CLAUDE_35_HAIKU).withTemperature(0.0) ), factCheckerProperties ); }}@Configurationclass FactCheckerAgentConfiguration {
@Bean fun factChecker(factCheckerProperties: FactCheckerProperties): Agent { return factCheckerAgent( llms = listOf( LlmOptions(AnthropicModels.CLAUDE_35_HAIKU).withTemperature(.3), LlmOptions(AnthropicModels.CLAUDE_35_HAIKU).withTemperature(.0), ), properties = factCheckerProperties, ) }}