Skip to main content
Callbacks hook into the optimization loop for logging, visualization, and control. This guide shows you how to create your own.

The Callback base class

All callbacks inherit from Callback (defined in bagel/callbacks.py). The base class provides three hook methods, all with default no-op implementations — override only the ones you need:

Available hooks

on_optimization_start(context)

Called once before the first optimization step. Use this to:
  • Initialize logging files or connections
  • Record initial system state
  • Set up resources needed during optimization

on_step_end(context)

Called after every optimization step. This is the main hook for:
  • Logging metrics and progress
  • Saving checkpoints
  • Triggering early stopping (set self._should_stop = True)
  • Monitoring convergence
All registered callbacks execute even if one triggers early stopping, so logging callbacks can always complete their work.

on_optimization_end(context)

Called once after the loop finishes (or after early stopping). Use this to:
  • Write final summaries
  • Close file handles or connections
  • Generate final reports

Accessing context

Every hook receives a CallbackContext dataclass with these fields: The metrics dictionary includes:
  • "system_energy" — total energy of the current system
  • "best_system_energy" — total energy of the best system
  • "{state_name}/{energy_name}" — individual energy term values
  • "{state_name}/state_energy" — total energy per state

Example: a custom callback

Here is a callback that saves checkpoint structures every N steps:
Usage:
BAGEL also ships with built-in callbacks:
  • DefaultLogger — writes energies, sequences, and masks to CSV/FASTA files
  • FoldingLogger — saves CIF structures and oracle attributes (pLDDT, PAE arrays)
  • EarlyStopping — monitors a metric and stops when it plateaus
  • WandBLogger — logs metrics to Weights & Biases for experiment tracking