Base macro for Tree-of-Thoughts-powered agents.
Wraps use Jido.Agent with Jido.AI.Reasoning.TreeOfThoughts.Strategy wired in,
plus standard state fields and helper functions.
Usage
defmodule MyApp.PuzzleSolver do
use Jido.AI.ToTAgent,
name: "puzzle_solver",
description: "Solves complex puzzles using tree exploration",
branching_factor: 4,
max_depth: 5,
traversal_strategy: :best_first
endOptions
:name(required) - Agent name:description- Agent description (default: "ToT agent #{name}"):model- Model alias or direct model spec (default: :fast, resolved via Jido.AI.resolve_model/1):branching_factor,:max_depth,:traversal_strategy- Core tree exploration knobs:top_k,:min_depth,:max_nodes,:max_duration_ms,:beam_width- Search budget and shaping knobs:early_success_threshold,:convergence_window,:min_score_improvement,:max_parse_retries- Deterministic stopping/parser controls:tools,:tool_context,:tool_timeout_ms,:tool_max_retries,:tool_retry_backoff_ms,:max_tool_round_trips- Tool orchestration controls:effect_policy,:strategy_effect_policy- Effect policy controls (strategy may only narrow):generation_prompt- Custom prompt for thought generation:evaluation_prompt- Custom prompt for thought evaluation:skills- Additional skills to attach to the agent (TaskSupervisorSkill is auto-included)
Generated Functions
explore/2,3- Async: sends prompt, returns{:ok, %Request{}}for later awaitingawait/1,2- Awaits a specific request's completionexplore_sync/2,3- Sync convenience: sends prompt and waits for resulton_before_cmd/2- Captures request in state before processingon_after_cmd/3- Updates request result when donebest_answer/1,top_candidates/2,result_summary/1- Structured result helpers
Request Tracking
Each explore/2 call returns a Request struct that can be awaited:
{:ok, request} = MyAgent.explore(pid, "Solve the 8-puzzle")
{:ok, result} = MyAgent.await(request, timeout: 30_000)Or use the synchronous convenience wrapper:
{:ok, result} = MyAgent.explore_sync(pid, "Solve the 8-puzzle")State Fields
The agent state includes:
:model- The LLM model being used:requests- Map of request_id => request state (for concurrent tracking):last_request_id- ID of the most recent request:last_prompt- The most recent prompt (backward compat):last_result- The final result from the last completed exploration (backward compat):completed- Boolean indicating if the last exploration is complete (backward compat)
Structured Result Contract
explore_sync/3 (and awaited async requests) resolve to a structured map:
best- best-ranked candidatecandidates- ranked candidate listtermination- reason/status/depth/node-count/duration metadatatree- search topology metadatausage- LLM usage metadatadiagnostics- parser/tool-round/convergence diagnostics
Task Supervisor
Each agent instance gets its own Task.Supervisor automatically started via the
Jido.AI.Plugins.TaskSupervisor. This supervisor is used for:
- LLM streaming operations
- Other async operations within the agent's lifecycle
Example
{:ok, pid} = Jido.AgentServer.start(agent: MyApp.PuzzleSolver)
# Async pattern (preferred for concurrent requests)
{:ok, request} = MyApp.PuzzleSolver.explore(pid, "Solve the 8-puzzle: [2,8,3,1,6,4,7,_,5]")
{:ok, result} = MyApp.PuzzleSolver.await(request)
# Sync pattern (convenience for simple cases)
{:ok, result} = MyApp.PuzzleSolver.explore_sync(pid, "Solve the 8-puzzle: [2,8,3,1,6,4,7,_,5]")Traversal Strategies
:bfs- Breadth-first search: explores all nodes at current depth before going deeper:dfs- Depth-first search: explores deeply before backtracking:best_first- Explores highest-scored nodes first (default)