@@ -112,6 +112,7 @@ def __init__(
112112 self ._required_tool_actions : Optional [Dict [str , Set [Optional [str ]]]] = None
113113 self .compressed_summary : Optional [str ] = None
114114 self .compressed_summary_tokens : int = 0
115+ self ._agent_data : Optional [Dict [str , Any ]] = None
115116
116117 def initialize (self ):
117118 """Initialize all required components for processing"""
@@ -359,22 +360,29 @@ def _get_data_from_api_key(self, api_key: str) -> Dict[str, Any]:
359360 return data
360361
361362 def _configure_source (self ):
362- """Configure the source based on agent data"""
363- api_key = self .data .get ("api_key" ) or self .agent_key
363+ """Configure the source based on agent data.
364364
365- if api_key :
366- agent_data = self ._get_data_from_api_key (api_key )
365+ The literal string ``"default"`` is a placeholder meaning "no
366+ ingested source" and is normalized to an empty source so that no
367+ retrieval is attempted.
368+ """
369+ if self ._agent_data :
370+ agent_data = self ._agent_data
367371
368372 if agent_data .get ("sources" ) and len (agent_data ["sources" ]) > 0 :
369373 source_ids = [
370- source ["id" ] for source in agent_data ["sources" ] if source .get ("id" )
374+ source ["id" ]
375+ for source in agent_data ["sources" ]
376+ if source .get ("id" ) and source ["id" ] != "default"
371377 ]
372378 if source_ids :
373379 self .source = {"active_docs" : source_ids }
374380 else :
375381 self .source = {}
376- self .all_sources = agent_data ["sources" ]
377- elif agent_data .get ("source" ):
382+ self .all_sources = [
383+ s for s in agent_data ["sources" ] if s .get ("id" ) != "default"
384+ ]
385+ elif agent_data .get ("source" ) and agent_data ["source" ] != "default" :
378386 self .source = {"active_docs" : agent_data ["source" ]}
379387 self .all_sources = [
380388 {
@@ -387,11 +395,24 @@ def _configure_source(self):
387395 self .all_sources = []
388396 return
389397 if "active_docs" in self .data :
390- self .source = {"active_docs" : self .data ["active_docs" ]}
398+ active_docs = self .data ["active_docs" ]
399+ if active_docs and active_docs != "default" :
400+ self .source = {"active_docs" : active_docs }
401+ else :
402+ self .source = {}
391403 return
392404 self .source = {}
393405 self .all_sources = []
394406
407+ def _has_active_docs (self ) -> bool :
408+ """Return True if a real document source is configured for retrieval."""
409+ active_docs = self .source .get ("active_docs" ) if self .source else None
410+ if not active_docs :
411+ return False
412+ if active_docs == "default" :
413+ return False
414+ return True
415+
395416 def _resolve_agent_id (self ) -> Optional [str ]:
396417 """Resolve agent_id from request, then fall back to conversation context."""
397418 request_agent_id = self .data .get ("agent_id" )
@@ -433,48 +454,39 @@ def _configure_agent(self):
433454 effective_key = self .data .get ("api_key" ) or self .agent_key
434455
435456 if effective_key :
436- data_key = self ._get_data_from_api_key (effective_key )
437- if data_key .get ("_id" ):
438- self .agent_id = str (data_key .get ("_id" ))
457+ self . _agent_data = self ._get_data_from_api_key (effective_key )
458+ if self . _agent_data .get ("_id" ):
459+ self .agent_id = str (self . _agent_data .get ("_id" ))
439460
440461 self .agent_config .update (
441462 {
442- "prompt_id" : data_key .get ("prompt_id" , "default" ),
443- "agent_type" : data_key .get ("agent_type" , settings .AGENT_NAME ),
463+ "prompt_id" : self . _agent_data .get ("prompt_id" , "default" ),
464+ "agent_type" : self . _agent_data .get ("agent_type" , settings .AGENT_NAME ),
444465 "user_api_key" : effective_key ,
445- "json_schema" : data_key .get ("json_schema" ),
446- "default_model_id" : data_key .get ("default_model_id" , "" ),
447- "models" : data_key .get ("models" , []),
466+ "json_schema" : self ._agent_data .get ("json_schema" ),
467+ "default_model_id" : self ._agent_data .get ("default_model_id" , "" ),
468+ "models" : self ._agent_data .get ("models" , []),
469+ "allow_system_prompt_override" : self ._agent_data .get (
470+ "allow_system_prompt_override" , False
471+ ),
448472 }
449473 )
450474
451475 # Set identity context
452476 if self .data .get ("api_key" ):
453477 # External API key: use the key owner's identity
454- self .initial_user_id = data_key .get ("user" )
455- self .decoded_token = {"sub" : data_key .get ("user" )}
478+ self .initial_user_id = self . _agent_data .get ("user" )
479+ self .decoded_token = {"sub" : self . _agent_data .get ("user" )}
456480 elif self .is_shared_usage :
457481 # Shared agent: keep the caller's identity
458482 pass
459483 else :
460484 # Owner using their own agent
461- self .decoded_token = {"sub" : data_key .get ("user" )}
462-
463- if data_key .get ("source" ):
464- self .source = {"active_docs" : data_key ["source" ]}
465- if data_key .get ("workflow" ):
466- self .agent_config ["workflow" ] = data_key ["workflow" ]
467- self .agent_config ["workflow_owner" ] = data_key .get ("user" )
468- if data_key .get ("retriever" ):
469- self .retriever_config ["retriever_name" ] = data_key ["retriever" ]
470- if data_key .get ("chunks" ) is not None :
471- try :
472- self .retriever_config ["chunks" ] = int (data_key ["chunks" ])
473- except (ValueError , TypeError ):
474- logger .warning (
475- f"Invalid chunks value: { data_key ['chunks' ]} , using default value 2"
476- )
477- self .retriever_config ["chunks" ] = 2
485+ self .decoded_token = {"sub" : self ._agent_data .get ("user" )}
486+
487+ if self ._agent_data .get ("workflow" ):
488+ self .agent_config ["workflow" ] = self ._agent_data ["workflow" ]
489+ self .agent_config ["workflow_owner" ] = self ._agent_data .get ("user" )
478490 else :
479491 # No API key — default/workflow configuration
480492 agent_type = settings .AGENT_NAME
@@ -497,14 +509,45 @@ def _configure_agent(self):
497509 )
498510
499511 def _configure_retriever (self ):
512+ """Assemble retriever config with precedence: request > agent > default."""
500513 doc_token_limit = calculate_doc_token_budget (model_id = self .model_id )
501514
515+ # Start with defaults
516+ retriever_name = "classic"
517+ chunks = 2
518+
519+ # Layer agent-level config (if present)
520+ if self ._agent_data :
521+ if self ._agent_data .get ("retriever" ):
522+ retriever_name = self ._agent_data ["retriever" ]
523+ if self ._agent_data .get ("chunks" ) is not None :
524+ try :
525+ chunks = int (self ._agent_data ["chunks" ])
526+ except (ValueError , TypeError ):
527+ logger .warning (
528+ f"Invalid agent chunks value: { self ._agent_data ['chunks' ]} , "
529+ "using default value 2"
530+ )
531+
532+ # Explicit request values win over agent config
533+ if "retriever" in self .data :
534+ retriever_name = self .data ["retriever" ]
535+ if "chunks" in self .data :
536+ try :
537+ chunks = int (self .data ["chunks" ])
538+ except (ValueError , TypeError ):
539+ logger .warning (
540+ f"Invalid request chunks value: { self .data ['chunks' ]} , "
541+ "using default value 2"
542+ )
543+
502544 self .retriever_config = {
503- "retriever_name" : self . data . get ( "retriever" , "classic" ) ,
504- "chunks" : int ( self . data . get ( " chunks" , 2 )) ,
545+ "retriever_name" : retriever_name ,
546+ "chunks" : chunks ,
505547 "doc_token_limit" : doc_token_limit ,
506548 }
507549
550+ # isNoneDoc without an API key forces no retrieval
508551 api_key = self .data .get ("api_key" ) or self .agent_key
509552 if not api_key and "isNoneDoc" in self .data and self .data ["isNoneDoc" ]:
510553 self .retriever_config ["chunks" ] = 0
@@ -528,6 +571,9 @@ def pre_fetch_docs(self, question: str) -> tuple[Optional[str], Optional[list]]:
528571 if self .data .get ("isNoneDoc" , False ) and not self .agent_id :
529572 logger .info ("Pre-fetch skipped: isNoneDoc=True" )
530573 return None , None
574+ if not self ._has_active_docs ():
575+ logger .info ("Pre-fetch skipped: no active docs configured" )
576+ return None , None
531577 try :
532578 retriever = self .create_retriever ()
533579 logger .info (
@@ -910,15 +956,23 @@ def create_agent(
910956 raw_prompt = get_prompt (prompt_id , self .prompts_collection )
911957 self ._prompt_content = raw_prompt
912958
913- rendered_prompt = self .prompt_renderer .render_prompt (
914- prompt_content = raw_prompt ,
915- user_id = self .initial_user_id ,
916- request_id = self .data .get ("request_id" ),
917- passthrough_data = self .data .get ("passthrough" ),
918- docs = docs ,
919- docs_together = docs_together ,
920- tools_data = tools_data ,
921- )
959+ # Allow API callers to override the system prompt when the agent
960+ # has opted in via allow_system_prompt_override.
961+ if (
962+ self .agent_config .get ("allow_system_prompt_override" , False )
963+ and self .data .get ("system_prompt_override" )
964+ ):
965+ rendered_prompt = self .data ["system_prompt_override" ]
966+ else :
967+ rendered_prompt = self .prompt_renderer .render_prompt (
968+ prompt_content = raw_prompt ,
969+ user_id = self .initial_user_id ,
970+ request_id = self .data .get ("request_id" ),
971+ passthrough_data = self .data .get ("passthrough" ),
972+ docs = docs ,
973+ docs_together = docs_together ,
974+ tools_data = tools_data ,
975+ )
922976
923977 provider = (
924978 get_provider_from_model_id (self .model_id )
0 commit comments