Mojentic.Agents.SimpleRecursiveAgent (Mojentic v1.2.0)

Copy Markdown View Source

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:

  1. GoalState - Tracks the problem-solving state through iterations
  2. EventEmitter - GenServer that manages event subscriptions and async dispatch
  3. SimpleRecursiveAgent - Orchestrates the problem-solving process

Events

The agent emits the following events during problem-solving:

  • GoalSubmittedEvent - When a problem is submitted
  • IterationCompletedEvent - After each iteration completes
  • GoalAchievedEvent - When the goal is successfully achieved
  • GoalFailedEvent - When the goal explicitly fails
  • TimeoutEvent - 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)}")
end

Options

  • :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

t()

@type t() :: %Mojentic.Agents.SimpleRecursiveAgent{
  broker: Mojentic.LLM.Broker.t(),
  emitter: pid(),
  max_iterations: pos_integer(),
  system_prompt: String.t(),
  tools: [module()]
}

Functions

new(broker, opts \\ [])

@spec new(
  Mojentic.LLM.Broker.t(),
  keyword()
) :: t()

Creates a new SimpleRecursiveAgent.

Parameters

  • broker - The LLM broker to use for generating responses
  • opts - 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."
)

solve(agent, problem)

@spec solve(t(), String.t()) :: {:ok, String.t()} | {:error, term()}

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 instance
  • problem - 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