A simple recursive agent that uses events and async to solve problems.
This agent provides a declarative event-driven approach to problem-solving. It will continue attempting to solve the problem until it either succeeds, fails explicitly, or reaches the maximum number of iterations.
Architecture
The agent uses three main components:
- GoalState - Tracks the problem-solving state through iterations
- EventEmitter - GenServer that manages event subscriptions and async dispatch
- SimpleRecursiveAgent - Orchestrates the problem-solving process
Events
The agent emits the following events during problem-solving:
GoalSubmittedEvent- When a problem is submittedIterationCompletedEvent- After each iteration completesGoalAchievedEvent- When the goal is successfully achievedGoalFailedEvent- When the goal explicitly failsTimeoutEvent- When the process times out
Usage
alias Mojentic.LLM.{Broker, Gateways.Ollama}
alias Mojentic.LLM.Tools.DateResolver
alias Mojentic.Agents.SimpleRecursiveAgent
broker = Broker.new("qwen3:32b", Ollama)
agent = SimpleRecursiveAgent.new(
broker,
tools: [DateResolver],
max_iterations: 5
)
case SimpleRecursiveAgent.solve(agent, "What's the date next Friday?") do
{:ok, result} -> IO.puts("Result: #{result}")
{:error, reason} -> IO.puts("Error: #{inspect(reason)}")
endOptions
:tools- List of tool modules available to the LLM (default: []):max_iterations- Maximum number of iterations before giving up (default: 5):system_prompt- Custom system prompt (default: problem-solving assistant prompt)
Completion Indicators
The agent monitors responses for these keywords:
- "DONE" (case-insensitive) - Task completed successfully
- "FAIL" (case-insensitive) - Task cannot be completed
Summary
Functions
Creates a new SimpleRecursiveAgent.
Solves a problem asynchronously using the recursive agent.
Types
@type t() :: %Mojentic.Agents.SimpleRecursiveAgent{ broker: Mojentic.LLM.Broker.t(), emitter: pid(), max_iterations: pos_integer(), system_prompt: String.t(), tools: [module()] }
Functions
@spec new( Mojentic.LLM.Broker.t(), keyword() ) :: t()
Creates a new SimpleRecursiveAgent.
Parameters
broker- The LLM broker to use for generating responsesopts- Keyword list of options::tools- List of tool modules (default: []):max_iterations- Maximum iterations (default: 5):system_prompt- Custom system prompt (default: problem-solving prompt)
Examples
broker = Broker.new("qwen3:32b", Ollama)
# With defaults
agent = SimpleRecursiveAgent.new(broker)
# With custom options
agent = SimpleRecursiveAgent.new(broker,
tools: [MyTool],
max_iterations: 10,
system_prompt: "You are a specialized assistant."
)
Solves a problem asynchronously using the recursive agent.
This method runs the event-driven problem-solving process with a 300-second timeout. The agent will continue iterating until:
- The task is completed successfully ("DONE")
- The task fails explicitly ("FAIL")
- The maximum number of iterations is reached
- The process times out (300 seconds)
Parameters
agent- The SimpleRecursiveAgent instanceproblem- The problem or request to be solved
Returns
{:ok, solution}- Success with the solution{:error, reason}- Error during solving
Examples
{:ok, result} = SimpleRecursiveAgent.solve(agent, "Calculate 2+2")
# => {:ok, "2+2 equals 4."}
{:ok, result} = SimpleRecursiveAgent.solve(agent, "What's the weather tomorrow?")
# Uses tools to gather info and answer