How to Implement Agent Reasoning and Decision-Making: A Technical Guide to the ai-agent-book Architecture
The ai-agent-book repository implements agent reasoning and decision-making through a modular three-layer architecture that transforms raw LLM responses into executable actions via an Agent policy loop while exposing complex reasoning as a dedicated tool service.
The bojieli/ai-agent-book repository provides a production-ready framework for building autonomous AI agents capable of complex problem-solving. Understanding how to implement agent reasoning and decision-making within this codebase requires examining its modular pipeline, which separates concerns between output parsing, policy execution, and dedicated reasoning capabilities.
The Three-Layer Reasoning Architecture
The repository structures agent reasoning into three distinct logical layers that process observations into actions.
Layer 1: Model-Output Parsing
The LlmOutputParser class in [aworld/agents/llm_agent.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/aworld/agents/llm_agent.py) transforms raw LLM responses into structured actions. Its parse() method (lines 44-66) receives a ModelResponse object and detects any tool_calls present in the output.
When the parser identifies tool calls, it constructs a list of ActionModel objects representing discrete operations. If no tool calls exist, the method treats the entire response content as a single textual action. This parsing layer ensures the agent can interpret whether the LLM intends to invoke tools or provide a direct answer.
Layer 2: Agent Core and Policy
The Agent class in [llm_agent.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/aworld/agents/llm_agent.py) (lines 126-165) serves as the central orchestrator. Its policy() method implements the core decision-making loop by executing four sequential steps:
- Prompt construction: Merges system instructions, user inputs, and tool descriptions through
_add_system_message_to_memoryand_add_human_input_to_memory - LLM invocation: Calls the language model via
acall_llm_modeloracall_llm_model_stream(defined in [aworld/models/llm.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/aworld/models/llm.py)) - Response parsing: Hands the raw
ModelResponseto themodel_output_parserinstance - Action dispatch: Evaluates
is_call_toolflags to determine whether to execute tools or return a final answer
This policy loop represents the decision-making engine that determines the agent's next move based on current observations.
Layer 3: Dedicated Reasoning Service
For complex multi-step problems, the repository exposes reasoning as a first-class tool through ThinkCollection in [examples/gaia/mcp_collections/intelligence.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/examples/gaia/mcp_collections/intelligence.py). The mcp_complex_problem_reasoning() method (lines 54-66) provides specialized "thinking" capabilities for mathematics, coding challenges, and logical puzzles.
This service receives a question and optional original_task parameter, builds a reasoning prompt via _prepare_reasoning_prompt, and calls the LLM through _call_reasoning_model. It returns an ActionResponse containing the full chain-of-thought text and execution metadata, enabling self-reflective decision-making.
The Decision-Making Execution Flow
The complete agent reasoning and decision-making process follows a five-step execution pipeline:
- Observation Input: External stimuli (user queries, screenshots) are encapsulated in
Observationobjects - Policy Execution:
Agent.policy(observation)constructs message lists and retrieves LLM responses - Action Parsing:
LlmOutputParserextracts tool calls; if present,Agent.execution_tools()processes them using_tools_aggregate_func - Memory Persistence: All interactions (system messages, human inputs, LLM outputs, tool results) are stored via the
MemoryFactoryin [aworld/memory/main.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/aworld/memory/main.py) - Output Generation: When tool execution completes without further calls, the agent returns a
Messageobject containing the finalMessageOutput
This flow ensures continuous context across multi-turn interactions while maintaining clear separation between reasoning and execution.
Key Implementation Details
Several mechanisms enhance the agent's reasoning capabilities:
- Agent Detection: The
is_agent_by_name(full_name)function in [aworld/core/agent/base.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/aworld/core/agent/base.py) distinguishes between recursive agent calls and standard tool invocations - Dynamic Tool Prompting: The
use_tools_in_promptflag embeds JSON-encodeduse_tool_listin system prompts, allowing the LLM to suggest specific tools for complex tasks - Reasoning Style Control: The
reasoning_styleparameter acceptsdetailed,concise, orstep-by-stepvalues, tailoring the LLM's output format for different problem types
Practical Code Examples
Creating an LLM-Driven Agent
The following example demonstrates instantiating an agent and executing its policy loop:
# Example 1 – Creating a simple LLM‑driven agent
from aworld.aworld import Agent # import from the package entry point
from aworld.core.context.base import Observation
# Instantiate the agent (uses the default config from aworld.conf)
my_agent = Agent(name="demo-agent")
# Build an observation (e.g., a user question)
obs = Observation(content="What is the sum of the first 100 prime numbers?")
# Run the policy – this will call the LLM, parse the response,
# and possibly invoke the reasoning tool if the LLM decides to.
actions = my_agent.policy(observation=obs)
# `actions` is a list of `ActionModel` objects.
for act in actions:
if act.tool_name == "intelligence_reasoning_service":
# The agent decided it needs a deep reasoning step.
# The tool is implemented in ThinkCollection (see think.py)
print("Reasoning tool invoked – result:")
print(act.params.get("content"))
else:
# Plain answer or other tool execution
print(act.params.get("content"))
Using the Reasoning Service Directly
For standalone complex problem solving without the full agent loop:
# Example 2 – Directly using the reasoning service (ThinkCollection)
from chapter8.gaia_experience.AWorld.examples.gaia.mcp_collections.intelligence.think import ThinkCollection
# Initialise the collection (it reads LLM config from env vars)
reasoner = ThinkCollection(arguments={})
# Ask a multi‑step math problem
resp = reasoner.mcp_complex_problem_reasoning(
question="Solve the diophantine equation x^2 + y^2 = 65 for integer pairs.",
reasoning_style="step-by-step"
)
print("Reasoning result:")
print(resp.message) # full chain‑of‑thought
print("Metadata:", resp.metadata)
Summary
- The three-layer architecture separates parsing (
LlmOutputParser), orchestration (Agent.policy()), and reasoning (ThinkCollection) into distinct concerns - Decision-making occurs through an interaction loop that transforms
Observationobjects intoActionModelinstances via LLM calls and structured parsing - Complex reasoning is exposed as a callable tool service rather than hidden internal logic, enabling recursive self-reflection
- Memory persistence via
MemoryFactorymaintains context across multi-turn conversations and tool executions - Dynamic prompting supports configurable reasoning styles and tool suggestions, allowing runtime adaptation to problem complexity
Frequently Asked Questions
How does the agent decide whether to use a tool or provide a direct answer?
The LlmOutputParser.parse() method in [llm_agent.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/aworld/agents/llm_agent.py) inspects the LLM response for tool_calls fields. If present, it sets is_call_tool to true and generates ActionModel objects for each tool invocation. If absent, the response content is wrapped as a direct answer action, which terminates the decision loop.
What is the difference between the general Agent policy and the ThinkCollection reasoning service?
The Agent.policy() method handles general interaction flow and tool dispatch, while ThinkCollection.mcp_complex_problem_reasoning() provides specialized deep reasoning for complex problems. The agent can invoke the reasoning service as one of its available tools, creating a hierarchical decision structure where the general policy handles high-level control and the reasoning service handles cognitive heavy lifting.
How does the framework maintain context across multiple reasoning steps?
All messages—system instructions, human inputs, LLM outputs, and tool results—are persisted through the MemoryFactory class in [aworld/memory/main.py](https://github.com/bojieli/ai-agent-book/blob/main/chapter8/gaia-experience/AWorld/aworld/memory/main.py). The agent's policy method references this shared memory when constructing prompts for subsequent LLM calls, ensuring the complete conversation history informs each new decision.
How can I customize the reasoning style for specific problem types?
Pass the reasoning_style parameter when calling mcp_complex_problem_reasoning() with values detailed, concise, or step-by-step. This string is appended to the reasoning prompt template, instructing the LLM to format its chain-of-thought accordingly. For the general agent, set use_tools_in_prompt to true and provide a specific use_tool_list to constrain available reasoning tools.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →