From 42dafee655c1b1a39fb4d17b3a88deed7e1c5fd8 Mon Sep 17 00:00:00 2001 From: octo-patch Date: Thu, 23 Apr 2026 10:06:42 +0800 Subject: [PATCH 1/2] fix: suppress memory prompt when past_memories is empty (fixes #572) Conditionally include both the memory content and the surrounding instruction only when past_memories is non-empty. Prevents agents from hallucinating past lessons when no memories have been stored yet. Affected agents: Bull Researcher, Bear Researcher, Research Manager, Portfolio Manager, Trader. --- tradingagents/agents/managers/portfolio_manager.py | 9 +++++++-- tradingagents/agents/managers/research_manager.py | 13 +++++++------ .../agents/researchers/bear_researcher.py | 14 ++++++++++++-- .../agents/researchers/bull_researcher.py | 14 ++++++++++++-- tradingagents/agents/trader/trader.py | 10 +++++++--- 5 files changed, 45 insertions(+), 15 deletions(-) diff --git a/tradingagents/agents/managers/portfolio_manager.py b/tradingagents/agents/managers/portfolio_manager.py index 6c69ae9f..0506cde6 100644 --- a/tradingagents/agents/managers/portfolio_manager.py +++ b/tradingagents/agents/managers/portfolio_manager.py @@ -22,6 +22,12 @@ def create_portfolio_manager(llm, memory): for i, rec in enumerate(past_memories, 1): past_memory_str += rec["recommendation"] + "\n\n" + lessons_line = ( + f"- Lessons from past decisions: **{past_memory_str}**\n" + if past_memories + else "" + ) + prompt = f"""As the Portfolio Manager, synthesize the risk analysts' debate and deliver the final trading decision. {instrument_context} @@ -38,8 +44,7 @@ def create_portfolio_manager(llm, memory): **Context:** - Research Manager's investment plan: **{research_plan}** - Trader's transaction proposal: **{trader_plan}** -- Lessons from past decisions: **{past_memory_str}** - +{lessons_line} **Required Output Structure:** 1. **Rating**: State one of Buy / Overweight / Hold / Underweight / Sell. 2. **Executive Summary**: A concise action plan covering entry strategy, position sizing, key risk levels, and time horizon. diff --git a/tradingagents/agents/managers/research_manager.py b/tradingagents/agents/managers/research_manager.py index 5b4b4fdc..a2483c98 100644 --- a/tradingagents/agents/managers/research_manager.py +++ b/tradingagents/agents/managers/research_manager.py @@ -20,6 +20,12 @@ def create_research_manager(llm, memory): for i, rec in enumerate(past_memories, 1): past_memory_str += rec["recommendation"] + "\n\n" + past_memory_block = ( + f'Take into account your past mistakes on similar situations. Use these insights to refine your decision-making and ensure you are learning and improving. Present your analysis conversationally, as if speaking naturally, without special formatting. \n\nHere are your past reflections on mistakes:\n"{past_memory_str}"\n\n' + if past_memories + else "" + ) + prompt = f"""As the portfolio manager and debate facilitator, your role is to critically evaluate this round of debate and make a definitive decision: align with the bear analyst, the bull analyst, or choose Hold only if it is strongly justified based on the arguments presented. Summarize the key points from both sides concisely, focusing on the most compelling evidence or reasoning. Your recommendation—Buy, Sell, or Hold—must be clear and actionable. Avoid defaulting to Hold simply because both sides have valid points; commit to a stance grounded in the debate's strongest arguments. @@ -29,12 +35,7 @@ Additionally, develop a detailed investment plan for the trader. This should inc Your Recommendation: A decisive stance supported by the most convincing arguments. Rationale: An explanation of why these arguments lead to your conclusion. Strategic Actions: Concrete steps for implementing the recommendation. -Take into account your past mistakes on similar situations. Use these insights to refine your decision-making and ensure you are learning and improving. Present your analysis conversationally, as if speaking naturally, without special formatting. - -Here are your past reflections on mistakes: -\"{past_memory_str}\" - -{instrument_context} +{past_memory_block}{instrument_context} Here is the debate: Debate History: diff --git a/tradingagents/agents/researchers/bear_researcher.py b/tradingagents/agents/researchers/bear_researcher.py index a44212dc..c9312d3e 100644 --- a/tradingagents/agents/researchers/bear_researcher.py +++ b/tradingagents/agents/researchers/bear_researcher.py @@ -19,6 +19,17 @@ def create_bear_researcher(llm, memory): for i, rec in enumerate(past_memories, 1): past_memory_str += rec["recommendation"] + "\n\n" + memory_section = ( + f"Reflections from similar situations and lessons learned: {past_memory_str}\n" + if past_memories + else "" + ) + memory_instruction = ( + " You must also address reflections and learn from lessons and mistakes you made in the past." + if past_memories + else "" + ) + prompt = f"""You are a Bear Analyst making the case against investing in the stock. Your goal is to present a well-reasoned argument emphasizing risks, challenges, and negative indicators. Leverage the provided research and data to highlight potential downsides and counter bullish arguments effectively. Key points to focus on: @@ -37,8 +48,7 @@ Latest world affairs news: {news_report} Company fundamentals report: {fundamentals_report} Conversation history of the debate: {history} Last bull argument: {current_response} -Reflections from similar situations and lessons learned: {past_memory_str} -Use this information to deliver a compelling bear argument, refute the bull's claims, and engage in a dynamic debate that demonstrates the risks and weaknesses of investing in the stock. You must also address reflections and learn from lessons and mistakes you made in the past. +{memory_section}Use this information to deliver a compelling bear argument, refute the bull's claims, and engage in a dynamic debate that demonstrates the risks and weaknesses of investing in the stock.{memory_instruction} """ response = llm.invoke(prompt) diff --git a/tradingagents/agents/researchers/bull_researcher.py b/tradingagents/agents/researchers/bull_researcher.py index d23d4d76..f015f9eb 100644 --- a/tradingagents/agents/researchers/bull_researcher.py +++ b/tradingagents/agents/researchers/bull_researcher.py @@ -19,6 +19,17 @@ def create_bull_researcher(llm, memory): for i, rec in enumerate(past_memories, 1): past_memory_str += rec["recommendation"] + "\n\n" + memory_section = ( + f"Reflections from similar situations and lessons learned: {past_memory_str}\n" + if past_memories + else "" + ) + memory_instruction = ( + " You must also address reflections and learn from lessons and mistakes you made in the past." + if past_memories + else "" + ) + prompt = f"""You are a Bull Analyst advocating for investing in the stock. Your task is to build a strong, evidence-based case emphasizing growth potential, competitive advantages, and positive market indicators. Leverage the provided research and data to address concerns and counter bearish arguments effectively. Key points to focus on: @@ -35,8 +46,7 @@ Latest world affairs news: {news_report} Company fundamentals report: {fundamentals_report} Conversation history of the debate: {history} Last bear argument: {current_response} -Reflections from similar situations and lessons learned: {past_memory_str} -Use this information to deliver a compelling bull argument, refute the bear's concerns, and engage in a dynamic debate that demonstrates the strengths of the bull position. You must also address reflections and learn from lessons and mistakes you made in the past. +{memory_section}Use this information to deliver a compelling bull argument, refute the bear's concerns, and engage in a dynamic debate that demonstrates the strengths of the bull position.{memory_instruction} """ response = llm.invoke(prompt) diff --git a/tradingagents/agents/trader/trader.py b/tradingagents/agents/trader/trader.py index 07e9f262..5e091a53 100644 --- a/tradingagents/agents/trader/trader.py +++ b/tradingagents/agents/trader/trader.py @@ -20,8 +20,12 @@ def create_trader(llm, memory): if past_memories: for i, rec in enumerate(past_memories, 1): past_memory_str += rec["recommendation"] + "\n\n" - else: - past_memory_str = "No past memories found." + + memory_instruction = ( + f" Apply lessons from past decisions to strengthen your analysis. Here are reflections from similar situations you traded in and the lessons learned: {past_memory_str}" + if past_memories + else "" + ) context = { "role": "user", @@ -31,7 +35,7 @@ def create_trader(llm, memory): messages = [ { "role": "system", - "content": f"""You are a trading agent analyzing market data to make investment decisions. Based on your analysis, provide a specific recommendation to buy, sell, or hold. End with a firm decision and always conclude your response with 'FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL**' to confirm your recommendation. Apply lessons from past decisions to strengthen your analysis. Here are reflections from similar situations you traded in and the lessons learned: {past_memory_str}""", + "content": f"You are a trading agent analyzing market data to make investment decisions. Based on your analysis, provide a specific recommendation to buy, sell, or hold. End with a firm decision and always conclude your response with 'FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL**' to confirm your recommendation.{memory_instruction}", }, context, ] From 25cc0e144c36284b084ec97a3bbcef89d72e68fa Mon Sep 17 00:00:00 2001 From: octo-patch Date: Thu, 23 Apr 2026 13:16:32 +0800 Subject: [PATCH 2/2] fix: strip trailing newlines from past_memory_str and gate thesis instruction Addresses gemini-code-assist review feedback: - All five files (portfolio_manager, research_manager, bear/bull researchers, trader) now call .strip() on past_memory_str before injecting it into prompts, removing the trailing '\n\n' artifacts from the construction loop. - portfolio_manager now also makes the 'past reflections' phrasing in the Investment Thesis instruction conditional on past_memories being non-empty, so an empty memory section can't trigger hallucinated past reflections. --- tradingagents/agents/managers/portfolio_manager.py | 9 +++++++-- tradingagents/agents/managers/research_manager.py | 2 +- tradingagents/agents/researchers/bear_researcher.py | 2 +- tradingagents/agents/researchers/bull_researcher.py | 2 +- tradingagents/agents/trader/trader.py | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tradingagents/agents/managers/portfolio_manager.py b/tradingagents/agents/managers/portfolio_manager.py index 0506cde6..5d4631b8 100644 --- a/tradingagents/agents/managers/portfolio_manager.py +++ b/tradingagents/agents/managers/portfolio_manager.py @@ -23,10 +23,15 @@ def create_portfolio_manager(llm, memory): past_memory_str += rec["recommendation"] + "\n\n" lessons_line = ( - f"- Lessons from past decisions: **{past_memory_str}**\n" + f"- Lessons from past decisions: **{past_memory_str.strip()}**\n" if past_memories else "" ) + thesis_instruction = ( + "3. **Investment Thesis**: Detailed reasoning anchored in the analysts' debate and past reflections." + if past_memories + else "3. **Investment Thesis**: Detailed reasoning anchored in the analysts' debate." + ) prompt = f"""As the Portfolio Manager, synthesize the risk analysts' debate and deliver the final trading decision. @@ -48,7 +53,7 @@ def create_portfolio_manager(llm, memory): **Required Output Structure:** 1. **Rating**: State one of Buy / Overweight / Hold / Underweight / Sell. 2. **Executive Summary**: A concise action plan covering entry strategy, position sizing, key risk levels, and time horizon. -3. **Investment Thesis**: Detailed reasoning anchored in the analysts' debate and past reflections. +{thesis_instruction} --- diff --git a/tradingagents/agents/managers/research_manager.py b/tradingagents/agents/managers/research_manager.py index a2483c98..03e32e49 100644 --- a/tradingagents/agents/managers/research_manager.py +++ b/tradingagents/agents/managers/research_manager.py @@ -21,7 +21,7 @@ def create_research_manager(llm, memory): past_memory_str += rec["recommendation"] + "\n\n" past_memory_block = ( - f'Take into account your past mistakes on similar situations. Use these insights to refine your decision-making and ensure you are learning and improving. Present your analysis conversationally, as if speaking naturally, without special formatting. \n\nHere are your past reflections on mistakes:\n"{past_memory_str}"\n\n' + f'Take into account your past mistakes on similar situations. Use these insights to refine your decision-making and ensure you are learning and improving. Present your analysis conversationally, as if speaking naturally, without special formatting. \n\nHere are your past reflections on mistakes:\n"{past_memory_str.strip()}"\n\n' if past_memories else "" ) diff --git a/tradingagents/agents/researchers/bear_researcher.py b/tradingagents/agents/researchers/bear_researcher.py index c9312d3e..e3922e8c 100644 --- a/tradingagents/agents/researchers/bear_researcher.py +++ b/tradingagents/agents/researchers/bear_researcher.py @@ -20,7 +20,7 @@ def create_bear_researcher(llm, memory): past_memory_str += rec["recommendation"] + "\n\n" memory_section = ( - f"Reflections from similar situations and lessons learned: {past_memory_str}\n" + f"Reflections from similar situations and lessons learned: {past_memory_str.strip()}\n" if past_memories else "" ) diff --git a/tradingagents/agents/researchers/bull_researcher.py b/tradingagents/agents/researchers/bull_researcher.py index f015f9eb..9724415d 100644 --- a/tradingagents/agents/researchers/bull_researcher.py +++ b/tradingagents/agents/researchers/bull_researcher.py @@ -20,7 +20,7 @@ def create_bull_researcher(llm, memory): past_memory_str += rec["recommendation"] + "\n\n" memory_section = ( - f"Reflections from similar situations and lessons learned: {past_memory_str}\n" + f"Reflections from similar situations and lessons learned: {past_memory_str.strip()}\n" if past_memories else "" ) diff --git a/tradingagents/agents/trader/trader.py b/tradingagents/agents/trader/trader.py index 5e091a53..96473346 100644 --- a/tradingagents/agents/trader/trader.py +++ b/tradingagents/agents/trader/trader.py @@ -22,7 +22,7 @@ def create_trader(llm, memory): past_memory_str += rec["recommendation"] + "\n\n" memory_instruction = ( - f" Apply lessons from past decisions to strengthen your analysis. Here are reflections from similar situations you traded in and the lessons learned: {past_memory_str}" + f" Apply lessons from past decisions to strengthen your analysis. Here are reflections from similar situations you traded in and the lessons learned: {past_memory_str.strip()}" if past_memories else "" )