@@ -150,6 +150,7 @@ def _is_file_path(value: str) -> bool:
150150 from ..task .task import Task
151151 from .handoff import Handoff , HandoffConfig , HandoffResult
152152 from ..rag .models import RAGResult , ContextPack
153+ from ..eval .results import EvaluationLoopResult
153154
154155class Agent :
155156 # Class-level counter for generating unique display names for nameless agents
@@ -851,6 +852,24 @@ def __init__(
851852 elif memory is False :
852853 memory = None
853854
855+ # ─────────────────────────────────────────────────────────────────────
856+ # Resolve HISTORY from MemoryConfig - FAST PATH
857+ # History is enabled via memory="history" preset or MemoryConfig(history=True)
858+ # ─────────────────────────────────────────────────────────────────────
859+ _history_enabled = False
860+ _history_limit = 10
861+ _history_session_id = None
862+
863+ # Check if memory config has history settings
864+ if _memory_config is not None and isinstance (_memory_config , MemoryConfig ):
865+ if _memory_config .history :
866+ _history_enabled = True
867+ _history_limit = _memory_config .history_limit
868+
869+ # Use auto_save session if no explicit session and history is enabled
870+ if _history_enabled and _history_session_id is None and auto_save :
871+ _history_session_id = auto_save
872+
854873 # ─────────────────────────────────────────────────────────────────────
855874 # Resolve KNOWLEDGE param - FAST PATH
856875 # ─────────────────────────────────────────────────────────────────────
@@ -1353,6 +1372,11 @@ def __init__(
13531372 # Used when session_id is provided but no DB adapter
13541373 self ._session_store = None
13551374 self ._session_store_initialized = False
1375+
1376+ # History injection settings (for auto-injecting session history into context)
1377+ self ._history_enabled = _history_enabled
1378+ self ._history_limit = _history_limit
1379+ self ._history_session_id = _history_session_id
13561380
13571381 # Agent-centric feature instances (lazy loaded for zero performance impact)
13581382 self ._auto_memory = auto_memory
@@ -2298,6 +2322,99 @@ def handoff_to(
22982322 )
22992323 return handoff_obj .execute_programmatic (self , prompt , context )
23002324
2325+ def run_until (
2326+ self ,
2327+ prompt : str ,
2328+ criteria : str ,
2329+ threshold : float = 8.0 ,
2330+ max_iterations : int = 5 ,
2331+ mode : str = "optimize" ,
2332+ on_iteration : Optional [Callable [[Any ], None ]] = None ,
2333+ verbose : bool = False ,
2334+ ) -> "EvaluationLoopResult" :
2335+ """
2336+ Run agent iteratively until output meets quality criteria.
2337+
2338+ This method implements the "Ralph Loop" pattern: run agent → judge output
2339+ → improve based on feedback → repeat until threshold met.
2340+
2341+ Args:
2342+ prompt: The prompt to send to the agent
2343+ criteria: Evaluation criteria for the Judge (e.g., "Response is thorough")
2344+ threshold: Score threshold for success (default: 8.0, scale 1-10)
2345+ max_iterations: Maximum iterations before stopping (default: 5)
2346+ mode: "optimize" (stop on success) or "review" (run all iterations)
2347+ on_iteration: Optional callback called after each iteration
2348+ verbose: Enable verbose logging
2349+
2350+ Returns:
2351+ EvaluationLoopResult with iteration history and final score
2352+
2353+ Example:
2354+ ```python
2355+ agent = Agent(name="analyzer", instructions="Analyze systems")
2356+ result = agent.run_until(
2357+ "Analyze the auth flow",
2358+ criteria="Analysis is thorough and actionable",
2359+ threshold=8.0,
2360+ )
2361+ print(result.final_score) # 8.5
2362+ print(result.success) # True
2363+ ```
2364+ """
2365+ from ..eval .loop import EvaluationLoop
2366+
2367+ loop = EvaluationLoop (
2368+ agent = self ,
2369+ criteria = criteria ,
2370+ threshold = threshold ,
2371+ max_iterations = max_iterations ,
2372+ mode = mode ,
2373+ on_iteration = on_iteration ,
2374+ verbose = verbose ,
2375+ )
2376+ return loop .run (prompt )
2377+
2378+ async def run_until_async (
2379+ self ,
2380+ prompt : str ,
2381+ criteria : str ,
2382+ threshold : float = 8.0 ,
2383+ max_iterations : int = 5 ,
2384+ mode : str = "optimize" ,
2385+ on_iteration : Optional [Callable [[Any ], None ]] = None ,
2386+ verbose : bool = False ,
2387+ ) -> "EvaluationLoopResult" :
2388+ """
2389+ Async version of run_until().
2390+
2391+ Run agent iteratively until output meets quality criteria.
2392+
2393+ Args:
2394+ prompt: The prompt to send to the agent
2395+ criteria: Evaluation criteria for the Judge
2396+ threshold: Score threshold for success (default: 8.0)
2397+ max_iterations: Maximum iterations before stopping (default: 5)
2398+ mode: "optimize" (stop on success) or "review" (run all iterations)
2399+ on_iteration: Optional callback called after each iteration
2400+ verbose: Enable verbose logging
2401+
2402+ Returns:
2403+ EvaluationLoopResult with iteration history and final score
2404+ """
2405+ from ..eval .loop import EvaluationLoop
2406+
2407+ loop = EvaluationLoop (
2408+ agent = self ,
2409+ criteria = criteria ,
2410+ threshold = threshold ,
2411+ max_iterations = max_iterations ,
2412+ mode = mode ,
2413+ on_iteration = on_iteration ,
2414+ verbose = verbose ,
2415+ )
2416+ return await loop .run_async (prompt )
2417+
23012418 async def handoff_to_async (
23022419 self ,
23032420 target_agent : 'Agent' ,
@@ -3442,7 +3559,19 @@ def _build_messages(self, prompt, temperature=1.0, output_json=None, output_pyda
34423559 if system_prompt :
34433560 messages .append ({"role" : "system" , "content" : system_prompt })
34443561
3445- # Add chat history
3562+ # Inject session history if enabled (from persistent storage)
3563+ if self ._history_enabled and self ._session_store is not None :
3564+ try :
3565+ session_history = self ._session_store .get_chat_history (
3566+ self ._history_session_id ,
3567+ max_messages = self ._history_limit
3568+ )
3569+ if session_history :
3570+ messages .extend (session_history )
3571+ except Exception as e :
3572+ logging .debug (f"Failed to load session history: { e } " )
3573+
3574+ # Add in-memory chat history (current conversation)
34463575 if self .chat_history :
34473576 messages .extend (self .chat_history )
34483577
0 commit comments