This content originally appeared on DEV Community and was authored by answeryt
The ‘Demo Spell’ and ‘Production Dilemma’ of AI Agents: How I Built a Self-Learning Agent SystemIntroduction: From “Amazing” to “Usable,” How Far Do AI Agents Still Have to Go?Since 2024, “AI Agent” has undoubtedly been the hottest term in the tech community. From the shock of AutoGPT to the agent frameworks launched by major companies (like the very famous LangChain, LlamaIndex, etc.), we’ve all seen an exciting future: a “digital employee” capable of understanding complex instructions, planning autonomously, and executing tasks. The stunning demo videos on social media seem to be heralding a new era.However, like every wave of technology, once the initial excitement fades, sober reflection emerges. I believe there are three “hard truths” facing AI Agents today:Fragile Systems: In multi-step workflows, every small failure rate is amplified exponentially, causing the success rate of the entire task chain to be shockingly low.High Costs: As conversations and tasks progress, the ever-growing context window leads to quadratic token costs, making them commercially unsustainable.Mismatched Design: The industry generally pins its hopes on more powerful LLMs, but the real bottleneck is how to design “tools” that agents can effectively understand and use, and a “feedback system” that allows them to learn from failure. This requires agent framework developers to find a very clever balance between failure and feedback.An amazing demo might only need to succeed once, but a stable and reliable production system must work correctly 99% of the time, which is clearly something current AI agents cannot do.Undeniably, current AI has already demonstrated astonishing capabilities in many scenarios. As a developer, I also enjoy the efficiency dividends brought by AI. Programming assistants like Cursor and Claude Code can indeed compress hours of coding work into minutes. However, after this “honeymoon” period, a series of practical problems emerge, which I believe every friend who uses AI deeply can relate to:The Side Effects of Being “Helpful”: AI sometimes “takes matters into its own hands,” modifying code you didn’t ask it to touch and introducing unexpected bugs.Lack of “Self-Awareness”: The AI makes a mistake but is completely unaware of it, leading us into the awkward situation of “five minutes of coding, two hours of debugging.”The “Instruction Discount” Problem: When you ask the AI to generate a detailed 2000-word report, it might only deliver a draft of a few hundred words, with its understanding and execution of core requirements falling far short of expectations.These “minor frictions” in daily use precisely validate my point: although current AI Agents are powerful, there is still a significant gap between them and a truly “usable” productivity tool in terms of reliability, controllability, and depth of task understanding.So, how do we cross this chasm? Do we wait for the next, more powerful version of GPT, or do we build a more robust and adaptive framework from a systems engineering perspective?Faced with these challenges, I have also been exploring over the past period. A common misconception is that we place all our hopes for a breakthrough on the next, more powerful foundational model (LLM). But this is like expecting a genius race car driver to set a world record in a mediocre car, ignoring the importance of the vehicle itself.I believe the relationship between an AI Agent framework and a foundational large model is like that of a race car and its driver. The foundational model is the driver with incredible reflexes and decision-making abilities, while the AI Agent framework is the meticulously tuned race car with an advanced suspension and stable braking system. A great driver can push a car to its limits, while an excellent car allows the driver to race more confidently and stably on complex tracks, even compensating for the driver’s occasional mistakes.Therefore, rather than passively waiting for the “genius driver” to arrive, we should proactively build a more reliable and intelligent “race car.” Based on this philosophy, I have constructed a complex AI Agent decision-making system. The complete program has been open-sourced on GitHub, and interested readers can find it here: https://github.com/answeryt/Neosgenesis. Its core design is precisely to provide the strongest support for the “driver” (LLM) and to confront and solve the three major challenges mentioned above. This article will deconstruct the architecture of this system and share how I, starting from engineering practice, built a self-learning, self-optimizing AI Agent system aimed at moving beyond the “demo spell” and toward “production usability.”Part 1: Confronting Fragility—How to Counter Exponential Error Accumulation?Imagine an agent with a 99% success rate for a single step. After executing 100 consecutive steps, the total success rate drops to just 36.6%. This “success rate avalanche” is a challenge that all complex automation systems must face. A traditional linear agent workflow is like a fragile glass rod; a break in any single link causes the entire task to fail.My solution is this: replace the fragile “glass rod” with a resilient “high-elasticity fiber bundle” through systemic redundancy and adaptive capabilities.Solution 1: Verify Before Executing—Nipping Fragility in the Bud with “Thought Verification” (controller.py)A major flaw of traditional agents is being a “giant in execution, but a dwarf in thought.” They receive an instruction and immediately dive into the details of execution, rarely stopping to think, “Is my plan itself reliable?” If the initial direction is wrong, then no matter how perfectly each subsequent step is executed, it’s just racing down the road to failure. This is the root cause of error accumulation.To cut off this fragility at its source, my system introduces the core principle of “verify before executing.” Before the agent invests any substantial execution cost, it must first subject its own “thoughts” to rigorous self-scrutiny.In controller.py -> MainControllerdef make_decision(self, user_query: str, …):
“””
Five-stage intelligent verification-learning decision process
“””
# …
# 🧠 Stage 1: A Priori Reasoning - Generate a thinking seed
thinking_seed = self.prior_reasoner.get_thinking_seed(user_query, execution_context)
# 🔍 Stage 2: Verify the thinking seed (New) - Quickly verify the high-level direction
seed_verification_result = self.verify_idea_feasibility(
idea_text=thinking_seed,
context={'stage': 'thinking_seed', ...}
)
# ...
# 🛤 Stage 3: Path Generation - Generate a list of reasoning paths based on the (verified) seed
all_reasoning_paths = self.path_generator.generate_paths(...)
# 🚀 Stage 4: Path Verification and Learning - Verify paths one by one and learn instantly
for i, path in enumerate(paths_to_verify, 1):
path_verification_result = self.verify_idea_feasibility(
idea_text=f"{path.path_type}: {path.description}",
context={'stage': 'reasoning_path', ...}
)
# 💡 Instant Learning: Immediately feed the verification result back to the MAB system
self.mab_converger.update_path_performance(
path_id=path.strategy_id,
success=(path_verification_result.get('feasibility_score', 0) > 0.3),
reward=path_verification_result.get('reward_score', 0.0)
)
# 🎯 Stage 5: Intelligent Final Decision - Make a decision based on verification results
# ...
This multi-layered verification mechanism ensures that every decision the agent makes is built on a more reliable, scrutinized foundation. It nips fragility in the bud by replacing expensive, high-risk “physical execution” with low-cost, front-loaded “thought experiments,” thereby dramatically reducing the probability of the entire task chain failing due to a directional error.Solution 2: From a Single Path to a Strategy Matrix (path_generator.py & mab_converger.py)A traditional agent usually follows a fixed plan. If any step in that plan fails (e.g., a tool call), the entire task gets stuck. My system, however, believes that there’s never just one way to solve a problem. Therefore, we’ve introduced a “multi-path reasoning” mechanism:Generate Diverse Strategies: At the start of a task, the PathGenerator module steps in. It doesn’t just create one plan; it generates multiple ReasoningPaths with different styles based on the nature of the task. For example, for a complex technical problem, it might generate:A “Systematic Analysis” path: Emphasizes logical decomposition and step-by-step execution.An “Innovative Breakthrough” path: Encourages out-of-the-box thinking and shortcuts.A “Practical & Pragmatic” path: Prioritizes the simplest, most direct solution.Select Based on Experience: After the paths are generated, the choice is handed over to the MABConverger (the learning core of our system, detailed later). It evaluates which type of path has the highest success rate and best performance for similar problems based on historical data, and then makes a selection.In path_generator.py -> ReasoningPathTemplates@staticmethod
def get_all_templates() -> Dict[str, ReasoningPath]:
“””Get all predefined path templates”””
return {
# Systematic thinking
“systematic_analytical”: ReasoningPath(
path_id=”systematic_analytical_v1″,
path_type=”Systematic Analysis”,
description=”Systematically decompose and analyze problems…”,
…
),
# Innovative thinking
“creative_innovative”: ReasoningPath(
path_id=”creative_innovative_v1″,
path_type=”Innovative Breakthrough”,
description=”Think outside the box to find innovations and breakthroughs…”,
…
),
# … more templates
}
In mab_converger.py -> MABConvergerdef select_best_path(self, paths: List[ReasoningPath], …) -> ReasoningPath:
“””Select the optimal path from a list of reasoning paths”””
# …
# Automatically select an algorithm (thompson_sampling, ucb_variant, etc.)
algorithm = self._select_best_algorithm_for_paths()
if algorithm == 'thompson_sampling':
best_arm = self._thompson_sampling_for_paths(available_arms)
# ...
selected_path = strategy_to_path_mapping.get(best_arm.path_id)
return selected_path
This design provides fault tolerance at the strategy level. If the agent chooses the “Systematic Analysis” path this time and fails, the MABConverger records this failure. When faced with a similar problem in the future, its decision weight might lean towards the “Practical & Pragmatic” path, thus automatically bypassing the previous point of failure. The system no longer follows a single track but dynamically seeks the optimal solution within a strategy matrix.Solution 3: “A Light at the End of the Tunnel”—Intelligent Detour Thinking (controller.py)Even with multiple alternative paths, it’s possible to reach a dead end where all known paths are unworkable. At this point, a truly intelligent system shouldn’t just spin its wheels or give up. For this, we designed an advanced fault-tolerance mechanism called “Aha-Moment” or “Intelligent Detour Thinking.”In controller.py -> MainControllerdef _check_aha_moment_trigger(self, chosen_path) -> Tuple[bool, str]:
“””Check if an Aha-Moment decision (detour thinking) needs to be triggered”””
# Trigger condition 1: Path confidence is too low
path_confidence = self.mab_converger.get_path_confidence(chosen_path.strategy_id)
if path_confidence < self.aha_moment_stats[‘confidence_threshold’]:
return True, f”Selected path confidence is too low ({path_confidence:.3f})”
# Trigger condition 2: All paths are performing poorly
if self.mab_converger.check_low_confidence_scenario(...):
return True, "Confidence in all available paths is low"
# Trigger condition 3: Too many consecutive failures
if self.aha_moment_stats['consecutive_failures'] >= self.aha_moment_stats['failure_threshold']:
return True, f"Consecutive failures: {self.aha_moment_stats['consecutive_failures']}"
return False, "Normal decision path is performing as expected"
def _execute_aha_moment_thinking(self, …):
“””Execute Aha-Moment detour thinking”””
# Step 1: Generate creative detour paths
creative_paths = self.path_generator.generate_paths(
…,
mode=’creative_bypass’ # Key: enter creative detour mode
)
# Step 2: Combine and re-select
combined_paths = original_paths + creative_paths
final_chosen_path = self.mab_converger.select_best_path(combined_paths)
return final_chosen_path, combined_paths
This is essentially a meta-cognitive ability. The system can recognize, “It seems none of my current methods are working,” and then proactively and strategically “brainstorm” instead of endlessly retrying on a failing path.Part 2: Breaking the Cost Curse—Structured State and Information CompressionThe second point directly addresses the core pain point of commercializing AI Agents: cost. As the task chain lengthens, simply concatenating all dialogue history and tool call results causes the context to expand dramatically, leading to quadratic growth in token costs.Our strategy is to replace disordered, lengthy “running ledger” contexts with structured memory and front-end information compression.Solution 1: Goodbye to “Running Ledgers,” Hello to “Structured Memory” (state_manager.py)One of the biggest problems with traditional agents is processing all context information as one giant, undifferentiated block of text. This is not only expensive but also inefficient. Our StateManager module changes this by upgrading the agent’s memory from “text” to “objects.”In state_manager.py@dataclass
class ConversationTurn:
“””Data structure for a conversation turn”””
turn_id: str
timestamp: float
user_input: str
llm_response: str
tool_calls: List[Dict[str, Any]] = field(default_factory=list)
# …
@dataclass
class UserGoal:
“””Data structure for a user goal”””
goal_id: str
original_query: str
status: GoalStatus = GoalStatus.PENDING
progress: float = 0.0
# …
@dataclass
class IntermediateResult:
“””Data structure for an intermediate result”””
result_id: str
source: str # tool_name or “llm_analysis”
content: Any
relevance_score: float = 0.0
# …
class StateManager:
def init(self, session_id: Optional[str] = None):
self.conversation_history: List[ConversationTurn] = []
self.user_goals: List[UserGoal] = []
self.intermediate_results: List[IntermediateResult] = []
# …
By making the state “object-oriented” rather than “text-based,” we fundamentally solve the problem of infinite context growth, paving the way for controlling token costs and achieving commercial viability.Solution 2: Front-End Information Noise Reduction—RAG Thinking Seeds (rag_seed_generator.py)Many tasks require an agent to retrieve information from the outside world. Our RAGSeedGenerator module adopts a strategy of “information preprocessing and compression.” Before a task officially begins, it uses Retrieval-Augmented Generation (RAG) to produce a highly condensed “thinking seed.”In rag_seed_generator.py -> RAGSeedGeneratordef generate_rag_seed(self, user_query: str, …) -> str:
“””Generate a RAG-based thinking seed – a three-stage core process”””
# Stage 1: Understand the problem and devise a search strategy
search_strategy = self._analyze_and_plan_search(user_query, …)
# Stage 2: Execute a web search
search_results = self._execute_web_search(search_strategy)
# Stage 3: Synthesize information and generate the seed
synthesis_result = self._synthesize_information(
user_query, search_strategy, search_results, ...
)
return synthesis_result.contextual_seed
This “thinking seed” acts as a custom “mission briefing” for the agent. Subsequent modules, like PathGenerator, work around this refined seed, avoiding the repeated processing of large amounts of raw information and further controlling context length and cost.Part 3: The Soul of the System—Building a Feedback Loop that Learns and ReflectsThe third point, and the most central challenge, lies in the design of tools and feedback systems. An agent that cannot learn from experience will forever remain a “toy.” This is precisely the soul of my system’s design.Solution 1: The Core of Learning—The Empiricism of Multi-Armed Bandits (MAB) (mab_converger.py)I introduced an empirical learning mechanism for the agent. Every “reasoning path” and every “tool” is treated as an EnhancedDecisionArm, recording its historical performance.In data_structures.py@dataclass
class EnhancedDecisionArm:
“””A decision arm – tracks the performance of a reasoning path”””
path_id: str
success_count: int = 0
failure_count: int = 0
total_reward: float = 0.0
rl_reward_history: List[float] = field(default_factory=list)
# …
def update_performance(self, success: bool, reward: float):
if success:
self.success_count += 1
else:
self.failure_count += 1
self.total_reward += reward
self.rl_reward_history.append(reward)
# ...
In mab_converger.py -> MABConvergerdef update_path_performance(self, path_id: str, success: bool, reward: float = 0.0):
“””Update the performance feedback for a path or tool”””
if path_id in self.path_arms:
target_arm = self.path_arms[path_id]
target_arm.update_performance(success, reward)
# …
This MAB system is the concrete engineering implementation of the “feedback system” I mentioned. It turns every action the agent takes into a learning opportunity. Good strategies and tools are reinforced, while poor ones are gradually phased out, allowing the system to achieve continuous self-optimization.Solution 2: Beyond “Success/Failure,” Pursuing “Effectiveness”—High-Quality Feedback from an LLM Referee (controller.py)Simply providing feedback of “success” or “failure” is not enough. To solve this, I introduced an innovative mechanism: the “LLM Referee.”In controller.py -> MainControllerdef _calculate_tool_reward(self, tool_result: Any, original_prompt: str) -> float:
“”” LLM Referee reward calculation system”””
# Prioritize the LLM referee system
llm_reward = self._llm_judge_tool_effectiveness(tool_result, original_prompt)
if llm_reward is not None:
logger.info(f” LLM Referee reward: {llm_reward:.3f}”)
return llm_reward
# … fallback to traditional calculation
def _llm_judge_tool_effectiveness(self, tool_result: Any, original_prompt: str) -> Optional[float]:
“”” LLM Referee: Assess how helpful the tool’s result is for solving the problem”””
judge_prompt = f”””
You are an expert AI tool effectiveness evaluator.
Original user problem: {original_prompt}
Tool execution result: {tool_result}
Evaluation task: Please assess how helpful the tool result is for solving the user’s original problem and provide a numerical score from -1.0 to 1.0.
Score:”””
llm_response = self._call_llm_for_parameters(judge_prompt)
score = self._parse_llm_judgment_score(llm_response)
return score
This provides an extremely high-quality, contextually relevant feedback signal. The MAB learns not just “Will this API crash?” but a deeper, utility-focused knowledge: “For solving this type of problem, how useful is this tool?”Solution 3: The System’s “Self-Awareness”—Cold Start Detection and Decision Mode Switching (mab_converger.py & controller.py)MAB relies on historical data, so how does it make a decision when faced with a brand-new tool or strategy (the “cold start” problem)? I solved this by giving the system a form of “self-awareness.”In mab_converger.py -> MABConvergerdef is_tool_cold(self, tool_name: str) -> Dict[str, any]:
“”” Determine if a tool is in a cold start state”””
tool_arm = self.tool_arms.get(tool_name)
if not tool_arm or tool_arm.activation_count < cold_start_config[“min_usage_count”]:
# …
return {‘is_cold_start’: True, …}
# …
return {‘is_cold_start’: False, …}
In controller.py -> MainControllerdef _mab_decide_action(self, …, available_tools: List[str]) -> Optional[str]:
“”” Step 3: Hybrid Decision Core – MAB experience + LLM intelligent exploration”””
# …
# Stage 2: MAB’s initial recommendation
mab_recommendation = self.mab_converger.select_best_tool(real_tools)
# Stage 3: Check experience level
cold_analysis = self.mab_converger.is_tool_cold(mab_recommendation)
# Stage 4: Intelligent mode switching
if cold_analysis['is_cold_start']:
# 🧠 Insufficient tool experience → Switch to LLM exploration mode
logger.info("🧠 Switching to exploration mode (LLM-led decision)")
return self._llm_explore_tool_selection(...)
else:
# 📊 Rich tool experience → Trust MAB's recommendation, use experience mode
logger.info("📊 Using experience mode (MAB-led decision)")
return mab_recommendation
This is a very elegant “exploitation vs. exploration” balancing strategy. It perfectly combines the decision-making efficiency of MAB when there is sufficient data with the generalization ability of LLM when facing new situations. The system can thus safely and efficiently learn and adopt new tools and strategies, solving the core problem of agent capability expansion.Conclusion: Beyond Prompt Engineering, a Return to Systems ThinkingLooking back at the three challenges I outlined, we find that the root of all problems points in a common direction: building a truly usable AI Agent is far more than just writing clever prompts (Prompt Engineering); it is a complex and serious systems engineering endeavor.The system I’ve built is a practical application of this philosophy. By introducing redundancy and adaptability to combat fragility, using structured state management to control costs, and most importantly, by building a feedback learning loop based on MAB and an LLM referee, we give the agent three valuable abilities:Learning from ExperienceRecovery from FailureExploration under UncertaintyThis is perhaps the key for AI Agents to move beyond the “demo spell,” evolving from “cool-looking” toys into “digital employees” that can create real value in a production environment. The road ahead is still long, but I believe that returning to a systems engineering mindset and building frameworks that can self-learn and reflect is the right path to that future. Of course, the current system is in development and still faces many difficulties and challenges to be solved. If you have great ideas and opinions, please point them out. Thank you very much for your valuable feedback, I will continue to improve!
This content originally appeared on DEV Community and was authored by answeryt