agno 2.4.4__py3-none-any.whl → 2.4.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -75,9 +75,7 @@ class LearnedKnowledgeStore(LearningStore):
75
75
  self._schema = self.config.schema or LearnedKnowledge
76
76
 
77
77
  if self.config.mode == LearningMode.HITL:
78
- log_warning(
79
- "LearnedKnowledgeStore does not support HITL mode. Use PROPOSE mode for human-in-the-loop approval. "
80
- )
78
+ log_warning("LearnedKnowledgeStore does not support HITL mode. Use PROPOSE mode for soft approval.")
81
79
 
82
80
  # =========================================================================
83
81
  # LearningStore Protocol Implementation
@@ -178,6 +176,9 @@ class LearnedKnowledgeStore(LearningStore):
178
176
  namespace: Namespace to save learnings to (default: "global").
179
177
  **kwargs: Additional context (ignored).
180
178
  """
179
+ # Reset state for this operation
180
+ self.learning_saved = False
181
+
181
182
  # process only supported in ALWAYS mode
182
183
  # for programmatic extraction, use extract_and_save directly
183
184
  if self.config.mode != LearningMode.ALWAYS:
@@ -204,6 +205,9 @@ class LearnedKnowledgeStore(LearningStore):
204
205
  **kwargs,
205
206
  ) -> None:
206
207
  """Async version of process."""
208
+ # Reset state for this operation
209
+ self.learning_saved = False
210
+
207
211
  if self.config.mode != LearningMode.ALWAYS:
208
212
  return
209
213
 
@@ -250,35 +254,45 @@ class LearnedKnowledgeStore(LearningStore):
250
254
  → Then incorporate any relevant findings into your response
251
255
 
252
256
  **RULE 2: ALWAYS search before saving.**
253
- When asked to save a learning or when you want to save an insight:
254
- First call `search_learnings` to check if similar knowledge exists
255
- → Only save if it's genuinely new (not a duplicate or minor variation)
257
+ Before saving anything, first call `search_learnings` to check if similar knowledge exists.
258
+ Only save if it's genuinely new (not a duplicate or minor variation).
259
+
260
+ **RULE 3: ALWAYS save when explicitly asked.**
261
+ When the user says "remember", "save", "note", "keep in mind", or similar:
262
+ → These are explicit directives - save what they asked (after searching for duplicates)
263
+
264
+ **RULE 4: ALWAYS save team/org goals, constraints, and policies.**
265
+ When the user shares organizational context:
266
+ → "We're trying to..." / "Our goal is..." (team goals)
267
+ → "We can't use..." / "We need to avoid..." (constraints)
268
+ → "Our policy is..." / "We always..." (policies)
269
+ → "Our priority is..." / "We prefer..." at org level (priorities)
270
+ These are shared context - save them so other users benefit too.
256
271
 
257
272
  ## Tools
258
273
 
259
274
  `search_learnings(query)` - Search for relevant prior insights. Use liberally.
260
- `save_learning(title, learning, context, tags)` - Save genuinely new insights.
275
+ `save_learning(title, learning, context, tags)` - Save new insights or context.
261
276
 
262
277
  ## When to Search
263
278
 
264
- ALWAYS search when the user:
279
+ Search when the user:
265
280
  - Asks for recommendations or best practices
266
281
  - Asks how to approach a problem
267
282
  - Asks about trade-offs or considerations
268
283
  - Mentions a technology, domain, or problem area
269
- - Asks you to save something (search first to check for duplicates!)
284
+ - Asks you to save something (check for duplicates first)
270
285
 
271
- ## When to Save
286
+ ## When to Save (Self-Discovered Insights)
272
287
 
273
- Only save insights that are:
288
+ For insights you discover yourself (not explicit requests or org context), only save if:
274
289
  - Non-obvious (required investigation to discover)
275
290
  - Reusable (applies to a category of problems)
276
291
  - Actionable (specific enough to apply directly)
277
- - Not already in the knowledge base (you checked by searching first!)
278
292
 
279
293
  Do NOT save:
280
294
  - Raw facts or common knowledge
281
- - User-specific preferences (use user memory instead)
295
+ - Individual user preferences (use user memory instead)
282
296
  - Duplicates of existing learnings
283
297
  </learning_system>\
284
298
  """)
@@ -308,7 +322,7 @@ class LearnedKnowledgeStore(LearningStore):
308
322
  If you discover something worth preserving, propose it at the end of your response:
309
323
 
310
324
  ---
311
- **💡 Proposed Learning**
325
+ **Proposed Learning**
312
326
  **Title:** [Concise title]
313
327
  **Context:** [When this applies]
314
328
  **Insight:** [The learning - specific and actionable]
@@ -484,15 +498,17 @@ class LearnedKnowledgeStore(LearningStore):
484
498
  tools = []
485
499
 
486
500
  if self.config.agent_can_search:
487
- tools.append(self._create_search_learnings_tool(user_id=user_id))
501
+ tools.append(
502
+ self._create_search_learnings_tool(namespace=namespace or self.config.namespace, user_id=user_id)
503
+ )
488
504
 
489
505
  if self.config.agent_can_save:
490
506
  tools.append(
491
507
  self._create_save_learning_tool(
508
+ namespace=namespace or self.config.namespace,
492
509
  user_id=user_id,
493
510
  agent_id=agent_id,
494
511
  team_id=team_id,
495
- default_namespace=namespace,
496
512
  )
497
513
  )
498
514
 
@@ -509,15 +525,17 @@ class LearnedKnowledgeStore(LearningStore):
509
525
  tools = []
510
526
 
511
527
  if self.config.agent_can_search:
512
- tools.append(self._create_async_search_learnings_tool(user_id=user_id))
528
+ tools.append(
529
+ self._create_async_search_learnings_tool(namespace=namespace or self.config.namespace, user_id=user_id)
530
+ )
513
531
 
514
532
  if self.config.agent_can_save:
515
533
  tools.append(
516
534
  self._create_async_save_learning_tool(
535
+ namespace=namespace or self.config.namespace,
517
536
  user_id=user_id,
518
537
  agent_id=agent_id,
519
538
  team_id=team_id,
520
- default_namespace=namespace,
521
539
  )
522
540
  )
523
541
 
@@ -529,10 +547,10 @@ class LearnedKnowledgeStore(LearningStore):
529
547
 
530
548
  def _create_save_learning_tool(
531
549
  self,
550
+ namespace: str,
532
551
  user_id: Optional[str] = None,
533
552
  agent_id: Optional[str] = None,
534
553
  team_id: Optional[str] = None,
535
- default_namespace: Optional[str] = None,
536
554
  ) -> Callable:
537
555
  """Create the save_learning tool for the agent."""
538
556
 
@@ -541,31 +559,20 @@ class LearnedKnowledgeStore(LearningStore):
541
559
  learning: str,
542
560
  context: Optional[str] = None,
543
561
  tags: Optional[List[str]] = None,
544
- namespace: Optional[str] = None,
545
562
  ) -> str:
546
- """Save a reusable insight to the knowledge base.
563
+ """Save a reusable insight or organizational context to the knowledge base.
547
564
 
548
- IMPORTANT: Before calling this, you MUST first call search_learnings to check
549
- if similar knowledge already exists. Do not save duplicates!
550
-
551
- Only save insights that are:
552
- - Non-obvious (not common knowledge)
553
- - Reusable (applies beyond this specific case)
554
- - Actionable (specific enough to apply directly)
555
- - Not already saved (you searched first, right?)
565
+ IMPORTANT: You MUST call search_learnings first to check for duplicates.
556
566
 
557
567
  Args:
558
- title: Concise, searchable title (e.g., "Cloud egress cost variations").
559
- learning: The insight - specific and actionable.
560
- context: When/where this applies (e.g., "When selecting cloud providers").
561
- tags: Categories for organization (e.g., ["cloud", "costs"]).
562
- namespace: Access scope - "global" (shared) or "user" (private).
568
+ title: Concise, searchable title.
569
+ learning: The insight or context - specific and actionable.
570
+ context: When/where this applies.
571
+ tags: Categories for organization.
563
572
 
564
573
  Returns:
565
574
  Confirmation message.
566
575
  """
567
- effective_namespace = namespace or default_namespace or "global"
568
-
569
576
  success = self.save(
570
577
  title=title,
571
578
  learning=learning,
@@ -574,21 +581,21 @@ class LearnedKnowledgeStore(LearningStore):
574
581
  user_id=user_id,
575
582
  agent_id=agent_id,
576
583
  team_id=team_id,
577
- namespace=effective_namespace,
584
+ namespace=namespace,
578
585
  )
579
586
  if success:
580
587
  self.learning_saved = True
581
- return f"Learning saved: {title} (namespace: {effective_namespace})"
588
+ return f"Learning saved: {title} (namespace: {namespace})"
582
589
  return "Failed to save learning"
583
590
 
584
591
  return save_learning
585
592
 
586
593
  def _create_async_save_learning_tool(
587
594
  self,
595
+ namespace: str,
588
596
  user_id: Optional[str] = None,
589
597
  agent_id: Optional[str] = None,
590
598
  team_id: Optional[str] = None,
591
- default_namespace: Optional[str] = None,
592
599
  ) -> Callable:
593
600
  """Create the async save_learning tool for the agent."""
594
601
 
@@ -597,31 +604,20 @@ class LearnedKnowledgeStore(LearningStore):
597
604
  learning: str,
598
605
  context: Optional[str] = None,
599
606
  tags: Optional[List[str]] = None,
600
- namespace: Optional[str] = None,
601
607
  ) -> str:
602
- """Save a reusable insight to the knowledge base.
608
+ """Save a reusable insight or organizational context to the knowledge base.
603
609
 
604
- IMPORTANT: Before calling this, you MUST first call search_learnings to check
605
- if similar knowledge already exists. Do not save duplicates!
606
-
607
- Only save insights that are:
608
- - Non-obvious (not common knowledge)
609
- - Reusable (applies beyond this specific case)
610
- - Actionable (specific enough to apply directly)
611
- - Not already saved (you searched first, right?)
610
+ IMPORTANT: You MUST call search_learnings first to check for duplicates.
612
611
 
613
612
  Args:
614
- title: Concise, searchable title (e.g., "Cloud egress cost variations").
615
- learning: The insight - specific and actionable.
616
- context: When/where this applies (e.g., "When selecting cloud providers").
617
- tags: Categories for organization (e.g., ["cloud", "costs"]).
618
- namespace: Access scope - "global" (shared) or "user" (private).
613
+ title: Concise, searchable title.
614
+ learning: The insight or context - specific and actionable.
615
+ context: When/where this applies.
616
+ tags: Categories for organization.
619
617
 
620
618
  Returns:
621
619
  Confirmation message.
622
620
  """
623
- effective_namespace = namespace or default_namespace or "global"
624
-
625
621
  success = await self.asave(
626
622
  title=title,
627
623
  learning=learning,
@@ -630,11 +626,11 @@ class LearnedKnowledgeStore(LearningStore):
630
626
  user_id=user_id,
631
627
  agent_id=agent_id,
632
628
  team_id=team_id,
633
- namespace=effective_namespace,
629
+ namespace=namespace,
634
630
  )
635
631
  if success:
636
632
  self.learning_saved = True
637
- return f"Learning saved: {title} (namespace: {effective_namespace})"
633
+ return f"Learning saved: {title} (namespace: {namespace})"
638
634
  return "Failed to save learning"
639
635
 
640
636
  return save_learning
@@ -645,6 +641,7 @@ class LearnedKnowledgeStore(LearningStore):
645
641
 
646
642
  def _create_search_learnings_tool(
647
643
  self,
644
+ namespace: str,
648
645
  user_id: Optional[str] = None,
649
646
  ) -> Callable:
650
647
  """Create the search_learnings tool for the agent."""
@@ -652,7 +649,6 @@ class LearnedKnowledgeStore(LearningStore):
652
649
  def search_learnings(
653
650
  query: str,
654
651
  limit: int = 5,
655
- namespace: Optional[str] = None,
656
652
  ) -> str:
657
653
  """Search for relevant insights in the knowledge base.
658
654
 
@@ -662,9 +658,8 @@ class LearnedKnowledgeStore(LearningStore):
662
658
 
663
659
  Args:
664
660
  query: Keywords describing what you're looking for.
665
- Examples: "cloud costs", "API rate limiting", "database migration"
661
+ Examples: "cloud costs", "API rate limiting", "team goals"
666
662
  limit: Maximum results (default: 5)
667
- namespace: Filter by scope (None = all, "global", "user", or custom)
668
663
 
669
664
  Returns:
670
665
  List of relevant learnings, or message if none found.
@@ -686,6 +681,7 @@ class LearnedKnowledgeStore(LearningStore):
686
681
 
687
682
  def _create_async_search_learnings_tool(
688
683
  self,
684
+ namespace: str,
689
685
  user_id: Optional[str] = None,
690
686
  ) -> Callable:
691
687
  """Create the async search_learnings tool for the agent."""
@@ -693,7 +689,6 @@ class LearnedKnowledgeStore(LearningStore):
693
689
  async def search_learnings(
694
690
  query: str,
695
691
  limit: int = 5,
696
- namespace: Optional[str] = None,
697
692
  ) -> str:
698
693
  """Search for relevant insights in the knowledge base.
699
694
 
@@ -703,9 +698,8 @@ class LearnedKnowledgeStore(LearningStore):
703
698
 
704
699
  Args:
705
700
  query: Keywords describing what you're looking for.
706
- Examples: "cloud costs", "API rate limiting", "database migration"
701
+ Examples: "cloud costs", "API rate limiting", "team goals"
707
702
  limit: Maximum results (default: 5)
708
- namespace: Filter by scope (None = all, "global", "user", or custom)
709
703
 
710
704
  Returns:
711
705
  List of relevant learnings, or message if none found.
@@ -893,7 +887,7 @@ class LearnedKnowledgeStore(LearningStore):
893
887
  log_warning("LearnedKnowledgeStore.save: no knowledge base configured")
894
888
  return False
895
889
 
896
- effective_namespace = namespace or "global"
890
+ effective_namespace = namespace or self.config.namespace
897
891
 
898
892
  # Validate "user" namespace has user_id
899
893
  if effective_namespace == "user" and not user_id:
@@ -963,7 +957,7 @@ class LearnedKnowledgeStore(LearningStore):
963
957
  log_warning("LearnedKnowledgeStore.asave: no knowledge base configured")
964
958
  return False
965
959
 
966
- effective_namespace = namespace or "global"
960
+ effective_namespace = namespace or self.config.namespace
967
961
 
968
962
  # Validate "user" namespace has user_id
969
963
  if effective_namespace == "user" and not user_id:
@@ -988,7 +982,7 @@ class LearnedKnowledgeStore(LearningStore):
988
982
  learning_obj = self.schema(**learning_data)
989
983
  text_content = self._to_text_content(learning=learning_obj)
990
984
 
991
- # Build metadata for filtering - THIS IS THE KEY FIX!
985
+ # Build metadata for filtering
992
986
  # Metadata must be passed separately to insert for filters to work
993
987
  filter_metadata: dict[str, Any] = {
994
988
  "namespace": effective_namespace,
@@ -1181,49 +1175,48 @@ class LearnedKnowledgeStore(LearningStore):
1181
1175
  from agno.models.message import Message
1182
1176
 
1183
1177
  system_prompt = dedent("""\
1184
- You are a Learning Extractor. Your job is to identify genuinely reusable insights
1185
- from conversations - the kind of knowledge that would help with similar tasks in the future.
1178
+ You are a Learning Extractor. Your job is to identify knowledge worth preserving
1179
+ from conversations for future use.
1180
+
1181
+ ## What to Save
1186
1182
 
1187
- ## What Makes Something Worth Saving
1183
+ **1. Discovered Insights** - Knowledge that emerged through the conversation:
1184
+ - Non-obvious (required reasoning or investigation)
1185
+ - Reusable (applies to a category of problems)
1186
+ - Actionable (specific enough to apply directly)
1187
+ - Durable (won't become outdated quickly)
1188
1188
 
1189
- A good learning is:
1190
- - **Discovered, not stated**: The insight emerged through work, not just repeated from the user
1191
- - **Non-obvious**: It required reasoning, investigation, or experience to arrive at
1192
- - **Reusable**: It applies to a category of problems, not just this exact situation
1193
- - **Actionable**: Someone encountering a similar situation could apply it directly
1194
- - **Durable**: It won't become outdated quickly
1189
+ **2. Organizational Context** - Explicit directives shared by the user:
1190
+ - Explicit save requests: "remember that...", "note that...", "keep in mind..."
1191
+ - Team/org goals: "we're trying to...", "our goal is...", "our priority is..."
1192
+ - Constraints: "we can't use...", "we need to avoid..."
1193
+ - Policies: "our policy is...", "we always...", "we never..."
1195
1194
 
1196
1195
  ## What NOT to Save
1197
1196
 
1198
- - **Raw facts**: "Python 3.12 was released in October 2023" (use search for retrieval)
1199
- - **User-specific info**: "User prefers TypeScript" (belongs in user memory)
1200
- - **Common knowledge**: "Use version control for code" (everyone knows this)
1201
- - **One-off answers**: "The error was a typo on line 42" (not generalizable)
1202
- - **Summaries**: Recaps of what was discussed (no new insight)
1203
- - **Uncertain conclusions**: If you're not confident, don't save it
1197
+ - Raw facts (use search for retrieval)
1198
+ - Individual user preferences (belongs in user memory)
1199
+ - Common knowledge (everyone knows this)
1200
+ - One-off answers (not generalizable)
1201
+ - Summaries without insight
1202
+ - Uncertain conclusions
1204
1203
 
1205
- ## Examples of Good Learnings
1204
+ ## Examples
1206
1205
 
1207
- From a debugging session:
1206
+ Good - Discovered insight:
1208
1207
  > **Title:** Debugging intermittent PostgreSQL connection timeouts
1209
- > **Learning:** When connection timeouts are intermittent, check for connection pool exhaustion
1210
- > before investigating network issues. Monitor active connections vs pool size, and look for
1211
- > long-running transactions that hold connections.
1212
- > **Context:** Diagnosing database connectivity issues in production
1208
+ > **Learning:** Check for connection pool exhaustion before investigating network issues.
1209
+ > **Context:** Diagnosing database connectivity issues
1213
1210
 
1214
- From an architecture discussion:
1215
- > **Title:** Event sourcing trade-offs for audit requirements
1216
- > **Learning:** Event sourcing adds complexity but provides natural audit trails. For systems
1217
- > where audit is the primary driver, consider a simpler append-only log table with the main
1218
- > data model unchanged - you get audit without the full event sourcing overhead.
1219
- > **Context:** Evaluating architecture patterns when audit trails are required
1211
+ Good - Organizational context:
1212
+ > **Title:** Team goal: reduce cloud egress costs
1213
+ > **Learning:** Factor egress costs into architecture decisions.
1214
+ > **Context:** Infrastructure and vendor decisions
1220
1215
 
1221
- ## Examples of What NOT to Save
1222
-
1223
- - "The user's API endpoint was returning 500 errors" (specific incident, not insight)
1224
- - "React is a popular frontend framework" (common knowledge)
1225
- - "We discussed three options for the database" (summary, no insight)
1226
- - "Always write tests" (too vague to be actionable)
1216
+ Bad (don't save):
1217
+ - "The error was a typo on line 42" (one-off)
1218
+ - "React is popular" (common knowledge)
1219
+ - "We discussed options" (summary, no insight)
1227
1220
 
1228
1221
  """)
1229
1222
 
@@ -1239,14 +1232,14 @@ These insights are already in the knowledge base. Do not save variations of thes
1239
1232
  system_prompt += dedent("""\
1240
1233
  ## Your Task
1241
1234
 
1242
- Review the conversation below. If - and only if - it contains a genuinely reusable insight
1243
- that isn't already captured, save it using the save_learning tool.
1235
+ Review the conversation below. Save anything that fits the criteria above:
1236
+ - Discovered insights worth preserving
1237
+ - Organizational context the user shared (goals, constraints, policies)
1244
1238
 
1245
1239
  **Important:**
1246
- - Most conversations will NOT produce a learning. That's expected and correct.
1240
+ - Most conversations will NOT produce a learning. That's expected.
1247
1241
  - When in doubt, don't save. Quality over quantity.
1248
- - One excellent learning is worth more than five mediocre ones.
1249
- - It's perfectly fine to do nothing if there's nothing worth saving.\
1242
+ - It's fine to do nothing if there's nothing worth saving.\
1250
1243
  """)
1251
1244
 
1252
1245
  return [
@@ -1262,7 +1255,7 @@ These insights are already in the knowledge base. Do not save variations of thes
1262
1255
  namespace: Optional[str] = None,
1263
1256
  ) -> List[Callable]:
1264
1257
  """Get sync extraction tools."""
1265
- effective_namespace = namespace or "global"
1258
+ effective_namespace = namespace or self.config.namespace
1266
1259
 
1267
1260
  def save_learning(
1268
1261
  title: str,
@@ -1270,18 +1263,12 @@ These insights are already in the knowledge base. Do not save variations of thes
1270
1263
  context: Optional[str] = None,
1271
1264
  tags: Optional[List[str]] = None,
1272
1265
  ) -> str:
1273
- """Save a genuinely reusable insight discovered in this conversation.
1274
-
1275
- Only call this if you've identified something that:
1276
- - Required investigation or reasoning to discover
1277
- - Would help with similar future tasks
1278
- - Isn't already captured in existing learnings
1279
- - Is specific and actionable enough to apply directly
1266
+ """Save a reusable insight or organizational context.
1280
1267
 
1281
1268
  Args:
1282
- title: Concise, searchable title that captures the topic.
1283
- learning: The insight itself - specific enough to apply, general enough to reuse.
1284
- context: When/where this applies (helps with future relevance matching).
1269
+ title: Concise, searchable title.
1270
+ learning: The insight or context - specific and actionable.
1271
+ context: When/where this applies.
1285
1272
  tags: Categories for organization.
1286
1273
 
1287
1274
  Returns:
@@ -1309,7 +1296,7 @@ These insights are already in the knowledge base. Do not save variations of thes
1309
1296
  namespace: Optional[str] = None,
1310
1297
  ) -> List[Callable]:
1311
1298
  """Get async extraction tools."""
1312
- effective_namespace = namespace or "global"
1299
+ effective_namespace = namespace or self.config.namespace
1313
1300
 
1314
1301
  async def save_learning(
1315
1302
  title: str,
@@ -1317,18 +1304,12 @@ These insights are already in the knowledge base. Do not save variations of thes
1317
1304
  context: Optional[str] = None,
1318
1305
  tags: Optional[List[str]] = None,
1319
1306
  ) -> str:
1320
- """Save a genuinely reusable insight discovered in this conversation.
1321
-
1322
- Only call this if you've identified something that:
1323
- - Required investigation or reasoning to discover
1324
- - Would help with similar future tasks
1325
- - Isn't already captured in existing learnings
1326
- - Is specific and actionable enough to apply directly
1307
+ """Save a reusable insight or organizational context.
1327
1308
 
1328
1309
  Args:
1329
- title: Concise, searchable title that captures the topic.
1330
- learning: The insight itself - specific enough to apply, general enough to reuse.
1331
- context: When/where this applies (helps with future relevance matching).
1310
+ title: Concise, searchable title.
1311
+ learning: The insight or context - specific and actionable.
1312
+ context: When/where this applies.
1332
1313
  tags: Categories for organization.
1333
1314
 
1334
1315
  Returns:
@@ -1399,10 +1380,6 @@ These insights are already in the knowledge base. Do not save variations of thes
1399
1380
  # Private Helpers
1400
1381
  # =========================================================================
1401
1382
 
1402
- def _build_learning_id(self, title: str) -> str:
1403
- """Build a unique learning ID from title."""
1404
- return f"learning_{title.lower().replace(' ', '_')[:32]}"
1405
-
1406
1383
  def _parse_result(self, result: Any) -> Optional[Any]:
1407
1384
  """Parse a search result into a learning object."""
1408
1385
  import json
agno/team/team.py CHANGED
@@ -343,6 +343,8 @@ class Team:
343
343
  # Add a tool to search the knowledge base (aka Agentic RAG)
344
344
  # Only added if knowledge is provided.
345
345
  search_knowledge: bool = True
346
+ # If True, add search_knowledge instructions to the system prompt
347
+ add_search_knowledge_instructions: bool = True
346
348
 
347
349
  # If False, media (images, videos, audio, files) is only available to tools and not sent to the LLM
348
350
  send_media_to_model: bool = True
@@ -530,6 +532,7 @@ class Team:
530
532
  share_member_interactions: bool = False,
531
533
  get_member_information_tool: bool = False,
532
534
  search_knowledge: bool = True,
535
+ add_search_knowledge_instructions: bool = True,
533
536
  read_chat_history: bool = False,
534
537
  store_media: bool = True,
535
538
  store_tool_messages: bool = True,
@@ -653,6 +656,7 @@ class Team:
653
656
  self.share_member_interactions = share_member_interactions
654
657
  self.get_member_information_tool = get_member_information_tool
655
658
  self.search_knowledge = search_knowledge
659
+ self.add_search_knowledge_instructions = add_search_knowledge_instructions
656
660
  self.read_chat_history = read_chat_history
657
661
 
658
662
  self.store_media = store_media
@@ -5675,16 +5679,6 @@ class Team:
5675
5679
  if self.name is not None and self.add_name_to_context:
5676
5680
  additional_information.append(f"Your name is: {self.name}.")
5677
5681
 
5678
- # Add knowledge context using protocol's build_context
5679
- if self.knowledge is not None:
5680
- build_context_fn = getattr(self.knowledge, "build_context", None)
5681
- if callable(build_context_fn):
5682
- knowledge_context = build_context_fn(
5683
- enable_agentic_filters=self.enable_agentic_knowledge_filters,
5684
- )
5685
- if knowledge_context:
5686
- additional_information.append(knowledge_context)
5687
-
5688
5682
  # 2 Build the default system message for the Agent.
5689
5683
  system_message_content: str = ""
5690
5684
  if self.members is not None and len(self.members) > 0:
@@ -5788,6 +5782,16 @@ class Team:
5788
5782
  "You should ALWAYS prefer information from this conversation over the past summary.\n\n"
5789
5783
  )
5790
5784
 
5785
+ # Add search_knowledge instructions to the system prompt
5786
+ if self.knowledge is not None and self.search_knowledge and self.add_search_knowledge_instructions:
5787
+ build_context_fn = getattr(self.knowledge, "build_context", None)
5788
+ if callable(build_context_fn):
5789
+ knowledge_context = build_context_fn(
5790
+ enable_agentic_filters=self.enable_agentic_knowledge_filters,
5791
+ )
5792
+ if knowledge_context:
5793
+ system_message_content += knowledge_context + "\n"
5794
+
5791
5795
  if self.description is not None:
5792
5796
  system_message_content += f"<description>\n{self.description}\n</description>\n\n"
5793
5797
 
@@ -5971,16 +5975,6 @@ class Team:
5971
5975
  if self.name is not None and self.add_name_to_context:
5972
5976
  additional_information.append(f"Your name is: {self.name}.")
5973
5977
 
5974
- # Add knowledge context using protocol's build_context
5975
- if self.knowledge is not None:
5976
- build_context_fn = getattr(self.knowledge, "build_context", None)
5977
- if callable(build_context_fn):
5978
- knowledge_context = build_context_fn(
5979
- enable_agentic_filters=self.enable_agentic_knowledge_filters,
5980
- )
5981
- if knowledge_context:
5982
- additional_information.append(knowledge_context)
5983
-
5984
5978
  # 2 Build the default system message for the Agent.
5985
5979
  system_message_content: str = ""
5986
5980
  system_message_content += "You are the leader of a team and sub-teams of AI Agents.\n"
@@ -6089,6 +6083,16 @@ class Team:
6089
6083
  "You should ALWAYS prefer information from this conversation over the past summary.\n\n"
6090
6084
  )
6091
6085
 
6086
+ # Add search_knowledge instructions to the system prompt
6087
+ if self.knowledge is not None and self.search_knowledge and self.add_search_knowledge_instructions:
6088
+ build_context_fn = getattr(self.knowledge, "build_context", None)
6089
+ if callable(build_context_fn):
6090
+ knowledge_context = build_context_fn(
6091
+ enable_agentic_filters=self.enable_agentic_knowledge_filters,
6092
+ )
6093
+ if knowledge_context:
6094
+ system_message_content += knowledge_context + "\n"
6095
+
6092
6096
  if self.description is not None:
6093
6097
  system_message_content += f"<description>\n{self.description}\n</description>\n\n"
6094
6098
 
@@ -8359,6 +8363,8 @@ class Team:
8359
8363
  config["add_knowledge_to_context"] = self.add_knowledge_to_context
8360
8364
  if not self.search_knowledge: # default is True
8361
8365
  config["search_knowledge"] = self.search_knowledge
8366
+ if self.add_search_knowledge_instructions:
8367
+ config["add_search_knowledge_instructions"] = self.add_search_knowledge_instructions
8362
8368
  if self.references_format != "json": # default is "json"
8363
8369
  config["references_format"] = self.references_format
8364
8370
 
@@ -8717,6 +8723,7 @@ class Team:
8717
8723
  add_knowledge_to_context=config.get("add_knowledge_to_context", False),
8718
8724
  update_knowledge=config.get("update_knowledge", False),
8719
8725
  search_knowledge=config.get("search_knowledge", True),
8726
+ add_search_knowledge_instructions=config.get("add_search_knowledge_instructions", True),
8720
8727
  references_format=config.get("references_format", "json"),
8721
8728
  # --- Tools ---
8722
8729
  tools=config.get("tools"),