Base macro for Chain-of-Thought-powered agents.
Wraps use Jido.Agent with Jido.AI.Reasoning.ChainOfThought.Strategy wired in,
plus standard state fields and helper functions.
Usage
defmodule MyApp.Reasoner do
use Jido.AI.CoTAgent,
name: "reasoner",
description: "Solves problems using step-by-step reasoning",
model: "anthropic:claude-sonnet-4-20250514"
endOptions
:name(required) - Agent name:description- Agent description (default: "CoT agent #{name}"):model- Model alias or direct model spec (default: :fast, resolved via Jido.AI.resolve_model/1):system_prompt- Custom system prompt for CoT reasoning:skills- Additional skills to attach to the agent (TaskSupervisorSkill is auto-included)
Generated Functions
think/2,3- Async: sends prompt, returns{:ok, %Request{}}for later awaitingawait/1,2- Awaits a specific request's completionthink_sync/2,3- Sync convenience: sends prompt and waits for resultstrategy_opts/0- Returns the strategy options (for CLI access)on_before_cmd/2- Captures request in state before processingon_after_cmd/3- Updates request result when done
Request Tracking
Each think/2 call returns a Request struct that can be awaited:
{:ok, request} = MyAgent.think(pid, "What is 15% of 340?")
{:ok, result} = MyAgent.await(request, timeout: 30_000)Or use the synchronous convenience wrapper:
{:ok, result} = MyAgent.think_sync(pid, "What is 15% of 340?")Request Lifecycle Contract
think/3emitsai.cot.queryand returns a request handle immediately.await/2resolves the request handle to either{:ok, result}or{:error, reason}.think_sync/3wrapsthink/3 + await/2.- Default request policy is
:reject, so a concurrent in-flight request emitsai.request.errorwithreason: :busy. - Correlation is request-id based end-to-end via request handles, strategy state, and delegated worker lifecycle envelopes.
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 reasoning (backward compat):completed- Boolean indicating if the last reasoning is complete (backward compat)
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.Reasoner)
# Async pattern (preferred for concurrent requests)
{:ok, request} = MyApp.Reasoner.think(pid, "What is 15% of 340?")
{:ok, result} = MyApp.Reasoner.await(request)
# Sync pattern (convenience for simple cases)
{:ok, result} = MyApp.Reasoner.think_sync(pid, "What is 15% of 340?")