[ICML 26] An evaluation framework assessing long-context retention and long-horizon memory performance for agentic applications (AMA-bench).
See the codeAMA-Bench is a benchmark for evaluating agent memory on long-horizon agent trajectories.

AMA-Bench evaluates whether a method can:
All methods share a unified two-stage interface defined in src/method/base_method.py:
memory_construction(traj_text, task="") โ build a memory object from trajectory textmemory_retrieve(memory, question) โ retrieve relevant context for a question
Each memory method is implemented in two stages:
| Stage | Function | Input | Output |
|---|---|---|---|
| Construction | memory_construction | trajectory text + task | memory object |
| Retrieval | memory_retrieve | memory object + question | context string |
Requirements: Python 3.9โ3.11 ยท Linux ยท CUDA GPU (recommended)
git clone https://github.com/AMA-Bench/AMA-Hub.git
cd AMA-Hub
python -m venv ama_venv
source ama_venv/bin/activate
pip install -r requirements.txt
Official dataset: huggingface.co/datasets/AMA-bench/AMA-bench
huggingface-cli download AMA-bench/AMA-bench --repo-type dataset --local-dir ./dataset
The default evaluation path is dataset/test/. The dataset contains only a test split โ there is no training split or qa_set directory.
dataset/
โโโ test/
โโโ open_end_qa_set.jsonl
bash scripts/run.sh
Launches a local vLLM server (per scripts/launch_vllm_32B.sh) and then runs generation + LLM-as-judge. All logs (vLLM server + pipeline output) are written to logs/<timestamp>/.
bash scripts/run_api.sh
Skips the vLLM launch and calls a remote API (OpenAI / Gemini / Anthropic, etc.) configured via LLM_CONFIG. Pipeline output is written to logs/<timestamp>/run.log.
python src/run.py \
--llm-server vllm \
--llm-config configs/qwen3-32B.yaml \
--subset openend \
--method longcontext \
--test-dir dataset/test \
--judge-config configs/llm_judge.yaml
codex / claude_code)You can also evaluate an external coding agent that reads the trajectory with its own tools (grep/jq/python over many turns) and answers a whole episode in one session:
python src/run.py \
--llm-server api \
--llm-config configs/codex_gpt5_mini.yaml \
--judge-config configs/llm_judge_gpt5_mini.yaml \
--subset openend \
--method codex \
--episode-ids 30,31,32,33,34,35,36,37,38,39
# swap in --method claude_code to run Claude Code instead
The agent gets the full, untruncated trajectory as trajectory.jsonl. codex uses an OpenAI-compatible key (OPENAI_API_KEY, optional OPENAI_BASE_URL); claude_code uses your local Claude Code login (or the standard ANTHROPIC_* env).
src/run.py runs answer generation followed by LLM-as-judge scoring, saving outputs to results/.
To evaluate an existing answer file separately:
bash scripts/evaluate.sh \
--answers-file results/openend/answers_xxx.jsonl \
--test-file dataset/test/open_end_qa_set.jsonl \
--judge-config configs/llm_judge.yaml
We performed a comprehensive consistency check for the LLM-as-judge setup, evaluating multiple judge models and analyzing their agreement patterns.
Performance against human annotations
| Metric | Value |
|---|---|
| Accuracy | 92.67% |
| Precision | 96.45% |
| Recall | 92.68% |
| F1 Score | 94.53% |
Overall Judge Accuracy Scores
| Judge Model | Accuracy | Notes |
|---|---|---|
| Qwen3-32B | 0.4880 | โ ๏ธ Highest accuracy, but shows leniency bias |
| Claude-4.6 | 0.3986 | Reference judge, balanced |
| GPT-5.4 | 0.3906 | Moderate strictness |
| GPT-5.2 | 0.3550 | More strict |
| DeepSeek-v3.2 | 0.3309 | Most strict judge |
Model Agreement Rates
Highest Agreement (> 90%):
Qwen3-32B Agreement with Others:
Leniency Bias Analysis
Qwen3-32B shows systematic leniency bias, particularly on:
Example 1: Accepting Core Concepts Without Complete Details
Task: babaisai (Game domain) Question: Based on game mechanics, what hidden movement mechanic can be inferred when pushing blocks?
Reference Answer: When pushing a text block, that block and adjacent blocks forming a phrase move as a group diagonally (one step in push direction and one step to the left).
Predicted Answer: Pushing a block causes adjacent blocks in the same rule line to shift, suggesting rule blocks are connected and move together.
Example 2: Accepting Partial Explanations
Task: crafter (Game domain) Question: What inventory change occurred and why is it critical for future crafting?
Reference Answer: Agent gained wood. Critical because wood is needed to craft a workbench, and without a workbench, the agent cannot craft any other tools, halting technological progression.
Predicted Answer: Agent gained wood. Critical because wood is required to craft tools (e.g., Wood Pickaxe), which are prerequisites for mining stone and other resources.
Recommendations: While Qwen3-32B achieves the highest accuracy, its leniency bias means it may accept incomplete answers. For critical evaluations, consider using Claude-4.6 as the reference judge or employing ensemble voting across multiple judges.
Full per-run logs (model outputs, judge outputs, and pipeline traces) for our AMA-Bench / AMA-Agent experiments are mirrored to Google Drive:
๐ AMA-Bench / AMA-Agent experiment logs
Use these to reproduce reported numbers, inspect raw judge decisions, or compare your own runs against ours.
| Script | Description |
|---|---|
scripts/launch_vllm_32B.sh | Launch vLLM server from a YAML config |
scripts/run.sh | End-to-end pipeline using a local vLLM server |
scripts/run_api.sh | End-to-end pipeline using a remote API (OpenAI / Gemini / Anthropic) |
scripts/evaluate.sh | Evaluate an existing answers JSONL with LLM-as-judge |
scripts/run_cross_validation.sh | Run cross-validation with multiple judges |
scripts/cross_validate.py | Compare evaluation results from two judges |
launch_vllm_32B.sh โ reads model and server settings from YAML, starts a vLLM OpenAI-compatible API, waits for the health endpoint. The vLLM log path is controlled by VLLM_LOG (default logs/vllm_server.log).
run.sh โ local-vLLM pipeline. Launches the vLLM server if needed, runs answer generation with the configured method, then evaluates with LLM-as-judge. Per-run logs (including the vLLM server log) are written to logs/<RUN_ID>/.
run_api.sh โ API-based pipeline. Same generation + judge flow as run.sh but skips the vLLM launch and points --llm-server at api. Per-run logs are written to logs/<RUN_ID>/.
evaluate.sh โ standalone judge evaluation for pre-generated answer files, useful for re-evaluating with a different judge model.
run_cross_validation.sh โ evaluates answers with both GPT-5.2 and Qwen3-32B judges, then compares results to measure inter-rater reliability.
cross_validate.py โ compares two evaluation result files and generates agreement statistics, including Cohen's Kappa and detailed disagreement analysis.
Visit the AMA-Bench Leaderboard and upload a JSONL file where each line is:
{"episode_id": 0, "answer_list": ["(A)", "(B)(C)"], "reasoning_trace": "..."}
Required fields: episode_id, answer_list. reasoning_trace is optional.
AMA-Bench/
โโโ src/
โ โโโ method/ # Memory method implementations (BM25, embedding, AMA-Agent, โฆ)
โ โโโ synthetic_data_gen/ # Trajectory synthesis tools (BabyAI, TextWorld, Crafter)
โ โโโ run.py # Main evaluation entry point
โ โโโ evaluate.py # LLM-as-judge evaluation
โ โโโ model_client.py # Unified client for different LLM providers
โโโ configs/ # Model / judge / method configs
โ โโโ llm_judge.yaml # VLLM judge config (Qwen3-32B)
โ โโโ llm_judge_api.yaml # API judge config (GPT-5.2, etc.)
โโโ scripts/ # Shell scripts for launching and evaluation
โ โโโ run.sh
โ โโโ evaluate.sh
โ โโโ run_cross_validation.sh # Cross-validation pipeline
โ โโโ cross_validate.py # Cross-validation comparison tool
โโโ docs/ # Documentation
โ โโโ CROSS_VALIDATION.md # Cross-validation guide
โโโ dataset/ # Local dataset (test split, downloaded separately)
โโโ results/ # Prediction outputs and evaluation metrics
โโโ assets/ # Figures
โโโ utils/ # Shared utilities
src/synthetic_data_gen/ provides tools for generating trajectories used in the benchmark:
Both include trajectory generation, automatic QA pair creation via state tracking, and token-based length binning. See src/synthetic_data_gen/README.md for details.
Create a subclass of BaseMethod and implement both stages:
from src.method.base_method import BaseMethod
class MyMethod(BaseMethod):
def memory_construction(self, traj_text: str, task: str = ""):
# Build and return a memory object from the trajectory
...
def memory_retrieve(self, memory, question: str) -> str:
# Return relevant context string for the question
...
Then register it in src/method_register.py to make it available via --method.
If your method is an external agent that reads the trajectory with its own tools (instead of the two-stage build/retrieve flow), subclass AgentHarnessMethod. It is driven once per episode with the raw trajectory and all questions, and returns the Answer[i] block:
from src.method.agent_method import AgentHarnessMethod
class MyAgentMethod(AgentHarnessMethod):
def run_episode(self, *, trajectory, task, questions, mcq_mode) -> str:
# run your agent over `trajectory`, return the "Answer[i]: ..." block
...
Register it the same way ("my_agent": ("src.method.agent_method", "MyAgentMethod")) and --method my_agent just works โ no change to the eval loop. See codex / claude_code for working examples.
@misc{zhao2026amabenchevaluatinglonghorizonmemory,
title={AMA-Bench: Evaluating Long-Horizon Memory for Agentic Applications},
author={Yujie Zhao and Boqin Yuan and Junbo Huang and Haocheng Yuan and Zhongming Yu and Haozhou Xu and Lanxiang Hu and Abhilash Shankarampeta and Zimeng Huang and Wentao Ni and Yuandong Tian and Jishen Zhao},
year={2026},
eprint={2602.22769},
archivePrefix={arXiv},
primaryClass={cs.AI},
url={https://arxiv.org/abs/2602.22769}
}
MIT License. See LICENSE.
[ICML 26] An evaluation framework assessing long-context retention and long-horizon memory performance for agentic applications (AMA-bench).
See the codeAMA-Bench is a benchmark for evaluating agent memory on long-horizon agent trajectories.

AMA-Bench evaluates whether a method can:
All methods share a unified two-stage interface defined in src/method/base_method.py:
memory_construction(traj_text, task="") โ build a memory object from trajectory textmemory_retrieve(memory, question) โ retrieve relevant context for a question
Each memory method is implemented in two stages:
| Stage | Function | Input | Output |
|---|---|---|---|
| Construction | memory_construction | trajectory text + task | memory object |
| Retrieval | memory_retrieve | memory object + question | context string |
Requirements: Python 3.9โ3.11 ยท Linux ยท CUDA GPU (recommended)
git clone https://github.com/AMA-Bench/AMA-Hub.git
cd AMA-Hub
python -m venv ama_venv
source ama_venv/bin/activate
pip install -r requirements.txt
Official dataset: huggingface.co/datasets/AMA-bench/AMA-bench
huggingface-cli download AMA-bench/AMA-bench --repo-type dataset --local-dir ./dataset
The default evaluation path is dataset/test/. The dataset contains only a test split โ there is no training split or qa_set directory.
dataset/
โโโ test/
โโโ open_end_qa_set.jsonl
bash scripts/run.sh
Launches a local vLLM server (per scripts/launch_vllm_32B.sh) and then runs generation + LLM-as-judge. All logs (vLLM server + pipeline output) are written to logs/<timestamp>/.
bash scripts/run_api.sh
Skips the vLLM launch and calls a remote API (OpenAI / Gemini / Anthropic, etc.) configured via LLM_CONFIG. Pipeline output is written to logs/<timestamp>/run.log.
python src/run.py \
--llm-server vllm \
--llm-config configs/qwen3-32B.yaml \
--subset openend \
--method longcontext \
--test-dir dataset/test \
--judge-config configs/llm_judge.yaml
codex / claude_code)You can also evaluate an external coding agent that reads the trajectory with its own tools (grep/jq/python over many turns) and answers a whole episode in one session:
python src/run.py \
--llm-server api \
--llm-config configs/codex_gpt5_mini.yaml \
--judge-config configs/llm_judge_gpt5_mini.yaml \
--subset openend \
--method codex \
--episode-ids 30,31,32,33,34,35,36,37,38,39
# swap in --method claude_code to run Claude Code instead
The agent gets the full, untruncated trajectory as trajectory.jsonl. codex uses an OpenAI-compatible key (OPENAI_API_KEY, optional OPENAI_BASE_URL); claude_code uses your local Claude Code login (or the standard ANTHROPIC_* env).
src/run.py runs answer generation followed by LLM-as-judge scoring, saving outputs to results/.
To evaluate an existing answer file separately:
bash scripts/evaluate.sh \
--answers-file results/openend/answers_xxx.jsonl \
--test-file dataset/test/open_end_qa_set.jsonl \
--judge-config configs/llm_judge.yaml
We performed a comprehensive consistency check for the LLM-as-judge setup, evaluating multiple judge models and analyzing their agreement patterns.
Performance against human annotations
| Metric | Value |
|---|---|
| Accuracy | 92.67% |
| Precision | 96.45% |
| Recall | 92.68% |
| F1 Score | 94.53% |
Overall Judge Accuracy Scores
| Judge Model | Accuracy | Notes |
|---|---|---|
| Qwen3-32B | 0.4880 | โ ๏ธ Highest accuracy, but shows leniency bias |
| Claude-4.6 | 0.3986 | Reference judge, balanced |
| GPT-5.4 | 0.3906 | Moderate strictness |
| GPT-5.2 | 0.3550 | More strict |
| DeepSeek-v3.2 | 0.3309 | Most strict judge |
Model Agreement Rates
Highest Agreement (> 90%):
Qwen3-32B Agreement with Others:
Leniency Bias Analysis
Qwen3-32B shows systematic leniency bias, particularly on:
Example 1: Accepting Core Concepts Without Complete Details
Task: babaisai (Game domain) Question: Based on game mechanics, what hidden movement mechanic can be inferred when pushing blocks?
Reference Answer: When pushing a text block, that block and adjacent blocks forming a phrase move as a group diagonally (one step in push direction and one step to the left).
Predicted Answer: Pushing a block causes adjacent blocks in the same rule line to shift, suggesting rule blocks are connected and move together.
Example 2: Accepting Partial Explanations
Task: crafter (Game domain) Question: What inventory change occurred and why is it critical for future crafting?
Reference Answer: Agent gained wood. Critical because wood is needed to craft a workbench, and without a workbench, the agent cannot craft any other tools, halting technological progression.
Predicted Answer: Agent gained wood. Critical because wood is required to craft tools (e.g., Wood Pickaxe), which are prerequisites for mining stone and other resources.
Recommendations: While Qwen3-32B achieves the highest accuracy, its leniency bias means it may accept incomplete answers. For critical evaluations, consider using Claude-4.6 as the reference judge or employing ensemble voting across multiple judges.
Full per-run logs (model outputs, judge outputs, and pipeline traces) for our AMA-Bench / AMA-Agent experiments are mirrored to Google Drive:
๐ AMA-Bench / AMA-Agent experiment logs
Use these to reproduce reported numbers, inspect raw judge decisions, or compare your own runs against ours.
| Script | Description |
|---|---|
scripts/launch_vllm_32B.sh | Launch vLLM server from a YAML config |
scripts/run.sh | End-to-end pipeline using a local vLLM server |
scripts/run_api.sh | End-to-end pipeline using a remote API (OpenAI / Gemini / Anthropic) |
scripts/evaluate.sh | Evaluate an existing answers JSONL with LLM-as-judge |
scripts/run_cross_validation.sh | Run cross-validation with multiple judges |
scripts/cross_validate.py | Compare evaluation results from two judges |
launch_vllm_32B.sh โ reads model and server settings from YAML, starts a vLLM OpenAI-compatible API, waits for the health endpoint. The vLLM log path is controlled by VLLM_LOG (default logs/vllm_server.log).
run.sh โ local-vLLM pipeline. Launches the vLLM server if needed, runs answer generation with the configured method, then evaluates with LLM-as-judge. Per-run logs (including the vLLM server log) are written to logs/<RUN_ID>/.
run_api.sh โ API-based pipeline. Same generation + judge flow as run.sh but skips the vLLM launch and points --llm-server at api. Per-run logs are written to logs/<RUN_ID>/.
evaluate.sh โ standalone judge evaluation for pre-generated answer files, useful for re-evaluating with a different judge model.
run_cross_validation.sh โ evaluates answers with both GPT-5.2 and Qwen3-32B judges, then compares results to measure inter-rater reliability.
cross_validate.py โ compares two evaluation result files and generates agreement statistics, including Cohen's Kappa and detailed disagreement analysis.
Visit the AMA-Bench Leaderboard and upload a JSONL file where each line is:
{"episode_id": 0, "answer_list": ["(A)", "(B)(C)"], "reasoning_trace": "..."}
Required fields: episode_id, answer_list. reasoning_trace is optional.
AMA-Bench/
โโโ src/
โ โโโ method/ # Memory method implementations (BM25, embedding, AMA-Agent, โฆ)
โ โโโ synthetic_data_gen/ # Trajectory synthesis tools (BabyAI, TextWorld, Crafter)
โ โโโ run.py # Main evaluation entry point
โ โโโ evaluate.py # LLM-as-judge evaluation
โ โโโ model_client.py # Unified client for different LLM providers
โโโ configs/ # Model / judge / method configs
โ โโโ llm_judge.yaml # VLLM judge config (Qwen3-32B)
โ โโโ llm_judge_api.yaml # API judge config (GPT-5.2, etc.)
โโโ scripts/ # Shell scripts for launching and evaluation
โ โโโ run.sh
โ โโโ evaluate.sh
โ โโโ run_cross_validation.sh # Cross-validation pipeline
โ โโโ cross_validate.py # Cross-validation comparison tool
โโโ docs/ # Documentation
โ โโโ CROSS_VALIDATION.md # Cross-validation guide
โโโ dataset/ # Local dataset (test split, downloaded separately)
โโโ results/ # Prediction outputs and evaluation metrics
โโโ assets/ # Figures
โโโ utils/ # Shared utilities
src/synthetic_data_gen/ provides tools for generating trajectories used in the benchmark:
Both include trajectory generation, automatic QA pair creation via state tracking, and token-based length binning. See src/synthetic_data_gen/README.md for details.
Create a subclass of BaseMethod and implement both stages:
from src.method.base_method import BaseMethod
class MyMethod(BaseMethod):
def memory_construction(self, traj_text: str, task: str = ""):
# Build and return a memory object from the trajectory
...
def memory_retrieve(self, memory, question: str) -> str:
# Return relevant context string for the question
...
Then register it in src/method_register.py to make it available via --method.
If your method is an external agent that reads the trajectory with its own tools (instead of the two-stage build/retrieve flow), subclass AgentHarnessMethod. It is driven once per episode with the raw trajectory and all questions, and returns the Answer[i] block:
from src.method.agent_method import AgentHarnessMethod
class MyAgentMethod(AgentHarnessMethod):
def run_episode(self, *, trajectory, task, questions, mcq_mode) -> str:
# run your agent over `trajectory`, return the "Answer[i]: ..." block
...
Register it the same way ("my_agent": ("src.method.agent_method", "MyAgentMethod")) and --method my_agent just works โ no change to the eval loop. See codex / claude_code for working examples.
@misc{zhao2026amabenchevaluatinglonghorizonmemory,
title={AMA-Bench: Evaluating Long-Horizon Memory for Agentic Applications},
author={Yujie Zhao and Boqin Yuan and Junbo Huang and Haocheng Yuan and Zhongming Yu and Haozhou Xu and Lanxiang Hu and Abhilash Shankarampeta and Zimeng Huang and Wentao Ni and Yuandong Tian and Jishen Zhao},
year={2026},
eprint={2602.22769},
archivePrefix={arXiv},
primaryClass={cs.AI},
url={https://arxiv.org/abs/2602.22769}
}
MIT License. See LICENSE.