| name | awesome-long-horizon-agents-survey |
| description | Comprehensive resource and taxonomy for long-horizon AI agents research, covering foundations, harnesses, optimization, and applications |
| triggers | ["show me research on long-horizon agents","what are the latest papers on AI agent capabilities","how do I build agents that work on multi-step tasks","explain long-horizon agent architectures","find papers about agent memory and context","what's the difference between agent harness and optimization","benchmark datasets for evaluating AI agents","research on agent reasoning over long time horizons"] |
Awesome Long-Horizon Agents Survey
Skill by ara.so — AI Agent Skills collection.
This skill helps you navigate and utilize the RUC-NLPIR/Awesome-Long-Horizon-Agents repository, a comprehensive survey and curated reading list covering the landscape of long-horizon AI agents. The resource organizes research into two main pillars: externalized harness engineering (loops, memory, tools, orchestration) and internalized model optimization (training, RL, self-evolution).
Overview
The repository accompanies the paper "Towards Long-Horizon Agents: A Survey" and provides:
- Three-level formalization (H1→H2→H3) of long-horizon tasks
- Evolution timeline from prompt engineering (2020-2023) to runtime harnesses (2025+)
- Systematic taxonomy of agent capabilities and implementation patterns
- Curated paper lists organized by technique and application domain
- Benchmarks and evaluation frameworks for long-horizon tasks
Key Concept: Long-Horizon Defined
The survey defines long-horizon agents across three nested levels:
| Level | Horizon | Capability Required |
|---|
| H1 | Intra-context (~minutes) | Interactive reasoning within one context window |
| H2 | Cross-context (~hours-days) | State persistence and memory across sessions |
| H3 | Cross-task (open-ended) | Experience accumulation and self-evolution |
Agent Formula: Agent = π_θ ⊕ H (base policy + harness)
Installation & Access
Clone the Repository
git clone https://github.com/RUC-NLPIR/Awesome-Long-Horizon-Agents.git
cd Awesome-Long-Horizon-Agents
Access the Resources
The repository is primarily a curated markdown document with links to papers, not executable code. Use it as:
- Reference guide for researching agent techniques
- Reading list organized by capability area
- Taxonomy for categorizing your own agent implementations
Quick Links
Key Research Areas & Paper Collections
1. Foundations: Formalizing Agents
Core Papers:
Use Case: Understanding foundational agent reasoning patterns
class ReActAgent:
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
def run(self, task):
thought = self.llm.generate(f"Thought: {task}")
action = self.parse_action(thought)
observation = self.tools[action['name']].execute(action['args'])
return self.llm.generate(f"Based on {observation}, the answer is...")
def parse_action(self, thought):
return {'name': 'search', 'args': ['query']}
2. Harnesses: External Capabilities (Pillar I)
Loops and Workflows
Key Papers:
- Reflexion - Self-reflection for iterative improvement
- Voyager - Curriculum learning in open worlds
- AutoGPT - Autonomous task execution loops
Pattern: Agent control flow architecture
class AgentHarness:
def __init__(self, agents: dict, memory: Memory):
self.agents = agents
self.memory = memory
async def execute_workflow(self, task):
"""H2-level: Cross-context workflow"""
plan = await self.agents['planner'].decompose(task)
self.memory.save('plan', plan)
for step in plan.steps:
context = self.memory.retrieve_relevant(step)
result = await self.agents['executor'].run(step, context)
self.memory.save(f'step_{step.id}', result)
if not self.verify(result):
result = await self.agents['refiner'].fix(result, context)
return self.agents['synthesizer'].combine(self.memory.get_all())
def ():
result.confidence >
Context and Memory
Key Papers:
- RAG (NeurIPS 2020): Retrieval-Augmented Generation
- RAPTOR (ICLR 2024): Tree-organized hierarchical retrieval
- MemGPT: Operating system for LLM memory management
Pattern: Long-term memory systems
from sentence_transformers import SentenceTransformer
class HierarchicalMemory:
def __init__(self, embedding_model='all-MiniLM-L6-v2'):
self.encoder = SentenceTransformer(embedding_model)
self.short_term = []
self.long_term = {}
self.semantic = {}
def add(self, text, metadata=None):
"""Add to short-term, periodically consolidate"""
embedding = self.encoder.encode(text)
self.short_term.append({
'text': text,
'embedding': embedding,
'metadata': metadata,
'timestamp': time.time()
})
if len(self.short_term) > 100:
self.consolidate()
def retrieve_relevant(self, query, k=5):
"""H2 capability: Cross-context retrieval"""
query_emb = self.encoder.encode(query)
all_memories = self.short_term + list(.long_term.values())
scores = [cosine_similarity(query_emb, m[])
m all_memories]
top_k = ((scores, all_memories), reverse=)[:k]
[m[] _, m top_k]
():
summary = .summarize_cluster(.short_term)
.long_term[summary[]] = summary
.short_term = []
Tools, MCP, and Skills
Model Context Protocol (MCP): Standard for agent-tool integration
from typing import Protocol
class MCPTool(Protocol):
"""Standard interface for agent tools"""
name: str
description: str
def get_schema(self) -> dict:
"""Return JSON schema for tool parameters"""
...
async def execute(self, **kwargs) -> dict:
"""Execute tool and return structured result"""
...
class WebSearchTool:
name = "web_search"
description = "Search the web for current information"
def get_schema(self):
return {
"type": "object",
"properties": {
"query": {"type": "string"},
"num_results": {"type": "integer", "default": 5}
},
"required": ["query"]
}
async def execute(self, query: str, num_results: int = 5):
os
api_key = os.getenv()
results = search_api.query(query, limit=num_results)
{: results, : (results)}
:
():
.llm = llm
.tools = {t.name: t t tools}
():
tool_schemas = {n: t.get_schema() n, t .tools.items()}
decision = .llm.select_tool(task, tool_schemas)
result = .tools[decision[]].execute(**decision[])
.llm.synthesize(task, result)
Verification
Key Papers:
- Self-Consistency: Multiple sampling for verification
- Critic models: Learned verification functions
- Process supervision: Step-by-step correctness checking
class VerificationHarness:
def __init__(self, critic_model, test_suite):
self.critic = critic_model
self.tests = test_suite
async def verify_with_feedback(self, agent_output, task):
"""Multi-level verification with repair loop"""
if not self.validate_format(agent_output):
return {'valid': False, 'feedback': 'Format error'}
critique = await self.critic.evaluate(agent_output, task)
if critique.score < 0.7:
return {'valid': False, 'feedback': critique.reasoning}
if self.tests:
test_results = self.tests.run(agent_output)
if not test_results.all_passed():
return {
'valid': False,
'feedback': f'Failed tests: {test_results.failures}'
}
{: }
():
3. Optimization: Internal Capabilities (Pillar II)
Agentic Reinforcement Learning
Key Papers:
- AgentQ: Online RL for web agents
- Agent-FLAN: Multi-task instruction tuning
- Reflexion: Reinforcement via verbal feedback
Pattern: Training agents with trajectory feedback
class AgentRLTrainer:
def __init__(self, base_model, environment, reward_model):
self.policy = base_model
self.env = environment
self.reward_model = reward_model
def train_episode(self, task):
"""Single training episode with trajectory collection"""
trajectory = []
state = self.env.reset(task)
for step in range(max_steps):
action = self.policy.generate_action(state)
next_state, env_reward = self.env.step(action)
reward = self.reward_model.score(
state=state,
action=action,
outcome=next_state,
success=env_reward
)
trajectory.append({
'state': state,
'action': action,
'reward': reward
})
if self.env.is_done():
break
state = next_state
self.update_policy(trajectory)
return sum(t['reward'] for t in trajectory)
def update_policy():
Self-Evolution
Key Papers:
- Voyager: Skill library via self-play
- AutoGPT: Autonomous capability expansion
- Self-Instruct: Bootstrap via self-generated data
Pattern: H3-level cross-task learning
class EvolvingAgent:
def __init__(self, base_model):
self.model = base_model
self.skill_library = {}
self.experience_buffer = []
def execute_and_learn(self, task):
"""H3: Learn from task execution"""
relevant_skills = self.match_skills(task)
result = self.model.run(
task,
context=relevant_skills,
exploration=True
)
if result.success:
self.experience_buffer.append({
'task': task,
'solution': result.trajectory,
'performance': result.metrics
})
if len(self.experience_buffer) > 100:
self.evolve_skills()
return result
def evolve_skills(self):
"""Abstract common patterns into skills"""
clusters = self.cluster_experiences(self.experience_buffer)
for cluster in clusters:
skill = .model.abstract_skill(cluster)
skill_name =
.validate_skill(skill):
.skill_library[skill_name] = skill
.experience_buffer = []
():
[s s .skill_library.values()
s.is_applicable(task)]
Application Domains
Software Engineering
Key Projects:
- SWE-agent: Solves GitHub issues via command-line interface
- Devin: Autonomous software engineer
- AutoCodeRover: Automated program repair
class CodeAgent:
def solve_issue(self, repo_path, issue_description):
codebase = self.analyze_repo(repo_path)
fix = self.model.generate_code(
issue=issue_description,
context=codebase.relevant_files,
constraints=codebase.style_guide
)
test_results = self.run_tests(repo_path, fix)
if not test_results.passed:
fix = self.model.refine_code(fix, test_results.errors)
return fix
Computer Use
Key Projects:
- Claude Computer Use: Control desktop via screenshots
- OpenHands: General computer control agent
- OS-Copilot: Operating system automation
class ComputerUseAgent:
def __init__(self, vision_model, action_model):
self.vision = vision_model
self.action = action_model
async def execute_task(self, instruction):
"""Control computer via vision + actions"""
for _ in range(max_steps):
screenshot = self.capture_screen()
state = self.vision.parse_ui(screenshot)
action = self.action.plan(
goal=instruction,
current_state=state
)
await self.execute_action(action)
if self.task_complete(instruction):
break
Benchmark Datasets
The survey references key evaluation benchmarks:
| Benchmark | Focus | Horizon Level |
|---|
| SWE-bench | GitHub issue resolution | H1-H2 |
| WebArena | Web task completion | H1 |
| GAIA | General assistant tasks | H2 |
| AgentBench | Multi-domain evaluation | H1-H2 |
| METR Task Standard | Time-to-completion metric | H1-H3 |
Using Benchmarks
from agent_benchmark import SWEBench
def evaluate_agent(agent, benchmark='swe-bench-lite'):
dataset = SWEBench.load(benchmark)
results = []
for task in dataset:
result = agent.solve_issue(
repo=task.repo,
issue=task.issue_description
)
success = benchmark.verify(result, task.ground_truth)
results.append({
'task_id': task.id,
'success': success,
'steps': len(result.trajectory),
'time': result.duration
})
horizon = calculate_horizon(results, success_rate=0.5)
return {
'success_rate': sum(r['success'] for r in results) / len(results),
'avg_steps': sum(r['steps'] for r in results) / len(results),
'horizon_50': horizon
}
Common Patterns & Best Practices
Pattern 1: ReAct Loop with Memory
class PersistentReActAgent:
"""Combines ReAct reasoning with cross-context memory (H2)"""
def __init__(self, llm, tools, memory):
self.llm = llm
self.tools = tools
self.memory = memory
async def run(self, task, session_id):
context = self.memory.retrieve_by_session(session_id)
max_iterations = 20
for i in range(max_iterations):
prompt = self.build_prompt(task, context, i)
response = await self.llm.generate(prompt)
if response.is_final_answer():
self.memory.save(session_id, {
'task': task,
'answer': response.answer,
'trajectory': context
})
return response.answer
action = self.parse_action(response)
observation = await self.tools[action.tool].execute(**action.args)
context.append({
'thought': response.thought,
'action': action,
'observation': observation
})
Pattern 2: Hierarchical Planning
class HierarchicalAgent:
"""Decompose long-horizon tasks into subtasks (H2→H1)"""
async def solve(self, complex_task):
plan = await self.planner.decompose(complex_task)
results = {}
for subtask in plan.subtasks:
agent = self.select_specialist(subtask.type)
results[subtask.id] = await agent.execute(subtask)
plan = self.planner.replan(plan, results)
return self.synthesizer.combine(results, complex_task)
def select_specialist(self, task_type):
"""Route to specialized agent (orchestration)"""
specialists = {
'code': self.code_agent,
'search': self.search_agent,
'analysis': self.analysis_agent
}
return specialists.get(task_type, self.general_agent)
Pattern 3: Verification-Driven Refinement
async def verified_generation(agent, task, verifier, max_attempts=3):
"""Generate with verification loop"""
for attempt in range(max_attempts):
result = await agent.generate(task)
verification = await verifier.check(result, task)
if verification.passed:
return result
task = task.with_feedback(verification.errors)
raise Exception("Could not generate valid result")
Troubleshooting
Issue: Agent Gets Stuck in Loops
Solution: Implement loop detection and breaking
class LoopDetector:
def __init__(self, window=5):
self.history = []
self.window = window
def add_step(self, state):
self.history.append(state)
if len(self.history) > self.window:
self.history.pop(0)
def is_looping(self):
"""Detect repeated states"""
if len(self.history) < self.window:
return False
recent = self.history[-self.window//2:]
earlier = self.history[:self.window//2]
return recent == earlier
Issue: Context Window Overflow (H1→H2 Transition)
Solution: Implement memory consolidation
def summarize_context(long_context, max_tokens=4000):
"""Compress context when approaching limits"""
if len(long_context) < max_tokens:
return long_context
recent = long_context[-1000:]
earlier = long_context[:-1000]
summary = llm.summarize(earlier, max_length=max_tokens - 1000)
return summary + "\n\n[Recent context]\n" + recent
Issue: Poor Tool Selection
Solution: Provide better tool descriptions and examples
def enhance_tool_schema(tool):
"""Add usage examples to tool schema"""
schema = tool.get_schema()
schema['examples'] = [
{
'input': {'query': 'current weather in Paris'},
'output': {'temp': 18, 'condition': 'cloudy'},
'when_to_use': 'User asks about current conditions'
}
]
return schema
Research & Development Workflow
1. Exploring Papers by Topic
git clone https://github.com/RUC-NLPIR/Awesome-Long-Horizon-Agents.git
cd Awesome-Long-Horizon-Agents
grep -n "memory" README.md | head -20
grep -n "reinforcement learning" README.md
2. Building on Survey Taxonomy
When designing your own agent:
- Identify horizon level (H1/H2/H3) for your target tasks
- Choose harness components (which loops, memory, tools needed)
- Select optimization strategy (fine-tuning, RL, self-evolution)
- Reference relevant papers from corresponding sections
3. Contributing to the Survey
git checkout -b add-paper-xyz
echo "- **\`NeurIPS 2026\`** Your Paper Title. [[paper](https://arxiv.org/abs/xxxx)]" >> README.md
git commit -m "Add: Your Paper Title"
git push origin add-paper-xyz
Key Takeaways for Implementation
- Start with H1: Build intra-context agents before tackling cross-context tasks
- Harness first, optimize later: Externalize capabilities in the harness, then consider internalizing via training
- Memory is critical for H2: Implement effective retrieval for cross-session persistence
- Verification enables iteration: Add verification loops to improve reliability
- Measure horizon empirically: Use time-to-completion at fixed success rate (METR methodology)
Citation
When using this survey in your research:
@article{dong2026longhorizon,
title={Towards Long-Horizon Agents: A Survey},
author={Dong, Guanting and Song, Xiaoshuai and Hu, Yuyang and others},
journal={Preprints},
year={2026},
doi={10.20944/preprints202607.1328.v1},
url={https://openreview.net/pdf?id=HyhfhlbWGh}
}
Additional Resources
This skill provides the conceptual framework and implementation patterns for building long-horizon agents based on the comprehensive survey taxonomy.