From d21e5e9944d962cf7008c1c9188a5627abd72bbd Mon Sep 17 00:00:00 2001 From: Sameer6305 Date: Fri, 31 Jul 2026 17:50:40 +0530 Subject: [PATCH] fix(agno): log decision tracking failures in shared context - #779 --- CHANGELOG.md | 5 +++++ integrations/agno/shared_context.py | 4 ++-- tests/integrations/agno/test_shared_context.py | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27448242..c8e06d41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- **Agno `_AgentScopedStore.upsert_memory` silently swallowed decision recording failures** (#779) + - `upsert_memory()` now logs `logger.warning("[%s] record_decision failed: %s", self._role, exc)` when `record_decision()` fails, matching the error-logging convention used for `store()` in the same method + - Preserves graceful fallback behavior: `record_decision()` remains optional and `upsert_memory()` continues without propagating the exception + - Added regression coverage in `tests/integrations/agno/test_shared_context.py` for both `store()` and `record_decision()` warning paths + - **MCP `handle_get_causal_chain` returned an empty-but-valid-looking response when both `CausalChainAnalyzer` and the graph fallback were unavailable** (#781, #817) by @Sameer6305 and @KaifAhmad1 - Returns an explicit `{"error": "Causal chain analysis is not supported on this graph backend", "chain": []}` instead of `{"chain": [], "count": 0, "direction": ...}`, letting clients distinguish "unsupported" from a legitimately empty chain - The fallback path now introspects `graph.get_causal_chain`'s signature to forward `direction`/`max_depth` (or a `depth` kwarg, or nothing, depending on what the backend accepts) instead of always calling with just `decision_id`, matching the primary analyzer path's behavior diff --git a/integrations/agno/shared_context.py b/integrations/agno/shared_context.py index e6799a8c..47ad2667 100644 --- a/integrations/agno/shared_context.py +++ b/integrations/agno/shared_context.py @@ -94,8 +94,8 @@ class _AgentScopedStore(AgnoContextStore): outcome="stored", confidence=1.0, ) - except Exception: - pass + except Exception as exc: + logger.warning("[%s] record_decision failed: %s", self._role, exc) if hasattr(memory, "id"): memory.id = mem_id diff --git a/tests/integrations/agno/test_shared_context.py b/tests/integrations/agno/test_shared_context.py index 5db29d70..b6576303 100644 --- a/tests/integrations/agno/test_shared_context.py +++ b/tests/integrations/agno/test_shared_context.py @@ -174,6 +174,24 @@ class TestSharedMemoryPool(unittest.TestCase): memories = self.analyst.read_memories(limit=2) self.assertTrue(len(memories) <= 2) + def test_upsert_memory_store_failure_logs_warning(self): + self.shared._context.store.side_effect = RuntimeError("store error") + with self.assertLogs("semantica.integrations.agno.shared_context", level="WARNING") as cm: + mem = self.researcher.upsert_memory(self._make_row("Test store fail")) + self.assertIsNotNone(mem) + self.assertIn(mem.id, self.researcher._memories) + self.assertTrue(any("store failed:" in msg and "store error" in msg for msg in cm.output)) + self.shared._context.store.side_effect = None + + def test_upsert_memory_record_decision_failure_logs_warning(self): + self.shared._context.record_decision.side_effect = RuntimeError("decision error") + with self.assertLogs("semantica.integrations.agno.shared_context", level="WARNING") as cm: + mem = self.researcher.upsert_memory(self._make_row("Test decision fail")) + self.assertIsNotNone(mem) + self.assertIn(mem.id, self.researcher._memories) + self.assertTrue(any("record_decision failed:" in msg and "decision error" in msg for msg in cm.output)) + self.shared._context.record_decision.side_effect = None + class TestSharedContextDecisions(unittest.TestCase):