FAMAS is a spectrum-based failure attribution framework for multi-agent systems (MASs). It attributes failures to suspicious actions by comparing one failed trajectory against multiple replayed trajectories, and then ranking action-level and agent-level responsibility.
This repository includes:
- spectrum matrix construction
- spectrum-based failure attribution
- evaluation metric computation
- optional LLM-based abstraction and clustering
This repository does not implement trajectory replay itself. It starts from prepared trajectory logs under data/trajectories/.
The end-to-end workflow is:
- Replay a failed task to obtain multiple rerun trajectories plus one original failed log
- Abstract raw logs into action-label steps
- Cluster semantically equivalent action-label steps
- Build spectrum matrices
- Run failure attribution
- Compute evaluation metrics
Replay is external to this repository. For the MAS systems referenced in our workflow, see:
Current released scripts assume the task-local trajectory set follows the FAMAS data convention used in this repository: 0.jsonl to 19.jsonl are rerun trajectories, and 20.jsonl is the original failed log.
conda env create -f environment.yml
conda activate FAMASenvAll commands in this README are expected to be run from the repository root.
For a first run, we recommend starting from the spectrum stage only.
The repository already includes clustered trajectories under data/trajectories/.../llm_cluster/, so you can directly build spectrum matrices and run failure attribution without replay or LLM-based abstraction.
This is the recommended first experience because abstraction and clustering are much slower:
- they require repeated external LLM calls across many trajectory files
- each task contains multiple runs, so the total number of LLM requests grows quickly
- incomplete or malformed LLM outputs may trigger automatic retries
- they require API configuration and incur latency and cost
To avoid overwriting existing outputs, run:
python code/run_full_pipeline.py \
--matrix_root tmp/quickstart_sbfl_matrixs \
--results_root tmp/quickstart_results \
--metrics_root tmp/quickstart_metric \
--rebuild-matrixThis command will:
- build spectrum matrices from the existing clustered trajectories
- run failure attribution for all benchmarks
- generate action-level and agent-level metrics
Main outputs:
tmp/quickstart_sbfl_matrixs/tmp/quickstart_results/tmp/quickstart_metric/
The main data directories are:
data/
├── trajectories/
│ └── <source_group>/<task_id>/
│ ├── jsonl/
│ ├── answers.txt
│ ├── llm_path/ # optional abstraction output
│ └── llm_cluster/ # clustered trajectories used by spectrum analysis
└── expected_results/
Notes:
data/trajectories/stores raw replay logs and task-local preprocessing outputsdata/expected_results/stores benchmark-level ground truth for evaluation- spectrum matrices are generated on demand and are not tracked in the repository
Important distinction:
- trajectory data is stored by source group, such as
gaia_level1,gaia_level3,assistantbench_hard,algorithmgenerated_plan, andalgorithmgenerated_normal - spectrum analysis and evaluation are reported under two benchmark groups:
hand_craftedandalgorithm_generated - during matrix construction, source groups are merged into those two benchmark groups
If you want to regenerate llm_path/ and llm_cluster/, use the abstraction pipeline.
Supported LLM providers:
openaideepseek
You can pass API keys directly with --api-key, or use environment variables:
export OPENAI_API_KEY=YOUR_OPENAI_API_KEY
export DEEPSEEK_API_KEY=YOUR_DEEPSEEK_API_KEYRun abstraction first and clustering second for all source groups under data/trajectories/:
python code/run_abstraction_pipeline.py \
--trajectories-root data/trajectories \
--base-url https://api.openai.com/v1 \
--model gpt-4o-mini \
--provider openaiOr with DeepSeek:
python code/run_abstraction_pipeline.py \
--trajectories-root data/trajectories \
--base-url https://api.deepseek.com/v1 \
--model deepseek-chat \
--provider deepseekPer task, the pipeline runs:
- abstraction over all
jsonl/*.jsonl - clustering over the generated abstraction results
Generated task-local outputs:
llm_path/: abstracted action-label trajectoriesllm_cluster/: clustered action-label trajectoriesabstractor.log: abstraction logcluster.log: clustering log
If your goal is only to reproduce the spectrum stage or inspect the final localization outputs, you can skip this stage entirely and use the precomputed llm_cluster/ directories already included in the repository.
To build spectrum matrices from clustered trajectories:
python code/spectrum/sbfl_martix.pyThis reads llm_cluster/ from each task directory, merges source groups into the two benchmark groups, and writes matrices to:
data/sbfl_matrixs/
├── hand_crafted/
└── algorithm_generated/
data/sbfl_matrixs/ is generated at runtime. It is not included as tracked repository data.
To run failure attribution manually:
python code/spectrum/failure_attribution.py -i [input_dir] -o [output_dir]Examples:
# build matrices first if `data/sbfl_matrixs/` does not exist yet
python code/spectrum/sbfl_martix.py
python code/spectrum/failure_attribution.py \
-i data/sbfl_matrixs/algorithm_generated \
-o output/results/algorithm_generated
python code/spectrum/failure_attribution.py \
-i data/sbfl_matrixs/hand_crafted \
-o output/results/hand_craftedThe default spectrum formula is configured in:
code/spectrum/config/formula.jsonCurrent default:
{
"name": "kulczynski2",
"use_lambda": true,
"use_beta": true,
"use_gamma": true,
"lambda_value": 0.9
}Supported formula names currently include:
ochiaitarantulajaccarddstar2kulczynski2
Fields:
name: suspiciousness formula nameuse_lambda: whether to use the lambda-weighted count variantuse_beta: whether to apply the beta adjustmentuse_gamma: whether to apply the gamma adjustmentlambda_value: lambda used in weighted counting
This config is read automatically by:
python code/spectrum/failure_attribution.py ...python code/run_full_pipeline.py ...python code/run_subsample_experiment.py ...
To compute action-level and agent-level rankings from localization results:
python code/evaluation/metric.py --fl_dir [fl_results_dir] --output_dir [output_dir]Examples:
python code/evaluation/metric.py \
--fl_dir output/results/hand_crafted \
--output_dir output/metric
python code/evaluation/metric.py \
--fl_dir output/results/ \
--output_dir output/metricRun the full spectrum-only pipeline for all benchmarks:
python code/run_full_pipeline.py --rebuild-matrixRun the same pipeline without overwriting existing outputs:
python code/run_full_pipeline.py \
--matrix_root tmp/sbfl_matrixs \
--results_root tmp/results \
--metrics_root tmp/metric \
--rebuild-matrixRun the k-trajectory subsampling experiment for t repeats:
python code/run_subsample_experiment.py --k 5 --times 20Example with temporary outputs:
python code/run_subsample_experiment.py \
--k 5 \
--times 20 \
--matrix_root tmp/sbfl_matrixs \
--output_root tmp/experiments/subsample_k5_t20This experiment samples k trajectories from the 20 rerun trajectories for each task, always keeps the original failed log, repeats the process t times, and reports min, max, and average metric totals across runs.