Context window management controls which conversation, tool, retrieval, and shared-state information enters the model’s limited context window. It is not the same as memory: short-term memory holds recent turns, while long-term memory is retrieved selectively across sessions. section 1.3.4 section 1.3.4
Think of the window as a workbench with limited space. Larger workbenches help, but crowded surfaces cost more, slow work, and can reduce reasoning quality. Good management decides what to retain, summarize, filter, chunk, or evict. section 1.3.4
Manage the main sources of context deliberately:
- Keep recent conversation turns while moving durable preferences, decisions, and projects into selectively retrieved long-term memory. section 1.3.4
- Filter or chunk large tool outputs before returning them to the model. section 1.3.4
- Rank and trim retrieval results before insertion, rather than inserting every candidate. section 1.3.4
- Coordinate shared state across agents without allowing every participant to receive every detail. section 1.3.4
Truncating findings in a research loop
A ten-iteration research loop passes only its five most recent findings to the agent. Earlier findings have less room because later findings are expected to synthesize them, leaving space for reasoning and new tool results. The loop can instead summarize or compress earlier findings when retaining more history matters. section 9.2.5 section 9.6
Listing 9.5 04_deep_research_loop.py (complete research loop)
async def run_research_loop( #1
goal: str, max_iterations: int = 10
) -> ResearchState:
search_server = MCPServerStdio(
name="Brave Search",
params={
"command": "npx",
"args": ["-y", "@anthropic/brave-search-mcp"],
"env": {"BRAVE_API_KEY": os.environ["BRAVE_API_KEY"]},
},
)
async with search_server:
agent = research_agent.clone(
mcp_servers=[search_server]
)
state = ResearchState( #2
goal=goal,
max_iterations=max_iterations,
follow_up_questions=[goal],
)
while state.should_continue: #3
state.iteration_count += 1
question = state.follow_up_questions.pop(0)
input_context = dict(
current_question=question,
accumulated_state=state.to_context(),
research_plan=state.plan.to_context(),
)
print(f"\n--- Iteration {state.iteration_count} ---")
print(f"Investigating: {question}")
result = await Runner.run(
agent, input=str(input_context)
)
iteration = result.final_output
state.findings.append(iteration.summary_of_findings)
state.sources_consulted.extend(iteration.sources_used)
state.follow_up_questions.extend(
iteration.follow_up_questions
)
apply_plan_updates(state.plan, iteration)
if iteration.goal_satisfied: #4
state.status = "complete"
print(f"Goal satisfied (confidence: "
f"{iteration.confidence:.0%})")
print(f"Found: {iteration.summary_of_findings[:100]}...")
print(f"New questions: {len(iteration.follow_up_questions)}")
print(f"Plan: {state.plan.progress_summary}")
return state
async def main(): #5
state = await run_research_loop(
goal="What are the latest advances in solid-state batteries "
"and which companies are leading commercialization?",
max_iterations=8,
)
print(f"\n{'='*50}")
print(f"Research complete after {state.iteration_count} iterations")
print(f"Sources consulted: {len(state.sources_consulted)}")
print(f"Status: {state.status}")
print(f"Plan progress: {state.plan.progress_summary}")
if state.plan.sub_topics:
for st in state.plan.sub_topics:
print(f" [{st.status}] {st.name}")
for i, finding in enumerate(state.findings, 1):
print(f"\nFinding {i}: {finding[:200]}...")
asyncio.run(main())
Inspect the complete research-loop implementation to see context selection placed inside typed state management, iteration control, and tool execution. section 9.2.5
