AUTOMATIC1111/stable-diffusion-webui
Script callbacks
Active contributors: AUTOMATIC1111, Aarni Koskela, w-e-w, catboxanon
Purpose
A registry of named hooks that scripts and extensions can subscribe to. The script-callbacks API is the recommended way to extend the webui without subclassing Script — it's lighter, callable from anywhere, and orderable across extensions.
All callbacks live in modules/script_callbacks.py. The pattern is uniform: an on_<event>(callback) registration function, and a <event>_callback(...) dispatcher called by the core code.
How registration works
from modules import script_callbacks
def my_handler(demo, app):
print("the UI just started")
script_callbacks.on_app_started(my_handler)Internally, every on_* function appends to a list inside callback_map keyed on the event name. When the core code dispatches the event, it iterates the list (in user-defined order, taking metadata.ini [callbacks/...] ordering hints into account) and calls each callback. Exceptions are caught and reported via errors.report so a single broken extension doesn't crash the request.
Available callbacks
The full list at the time of writing — see the source for parameter signatures and any per-callback notes. Categories are informal but match the order in script_callbacks.py.
Lifecycle
| Callback | Fires when | Typical use |
|---|---|---|
on_before_ui |
Before the Gradio UI is built | Late initialisation that needs shared.opts |
on_app_started(demo, app) |
After Gradio launch, with the FastAPI app |
Register custom HTTP routes |
on_before_reload |
Before a UI reload | Save state, close handles |
on_script_unloaded |
When a script is being unloaded | Cleanup |
Model
| Callback | Fires when |
|---|---|
on_model_loaded(sd_model) |
After model_hijack.hijack(sd_model) |
on_list_unets(callback) |
When sd_unet enumerates available UNets |
UI construction
| Callback | Fires when |
|---|---|
on_ui_tabs() |
Returns extra tabs as [(component, label, elem_id), ...] |
on_ui_train_tabs(params) |
Adds tabs to the Train sub-tab |
on_ui_settings() |
Register settings via shared.options_templates.update(...) |
on_before_component(component, **kwargs) |
Before each Gradio component is created |
on_after_component(component, **kwargs) |
After each component is created — match by elem_id |
Image saving
| Callback | Fires when |
|---|---|
on_before_image_saved(params) |
Before save_image writes the file; params: ImageSaveParams |
on_image_saved(params) |
After the file is written |
on_image_grid(params) |
When a grid image is being assembled |
Generation
| Callback | Fires when |
|---|---|
on_extra_noise(params) |
Just before noise is added; params: ExtraNoiseParams carries noise, x, xi |
on_cfg_denoiser(params) |
At every sampler step, before inner_model runs; params: CFGDenoiserParams carries x, image_cond, sigma, sampling_step, total_sampling_steps, text_cond, text_uncond, denoiser |
on_cfg_denoised(params) |
After inner_model runs but before CFG is applied |
on_cfg_after_cfg(params) |
After CFG; lets you modify the predicted noise/x |
on_post_sample(params) |
After sampling but before postprocessing; params: PostSampleArgs |
Optimisations and infotext
| Callback | Fires when |
|---|---|
on_list_optimizers(callback) |
When attention optimisations are enumerated |
on_infotext_pasted(infotext, params) |
When the user pastes a generation parameters string |
on_before_token_counter(params) |
Before the prompt token-counter runs |
Parameter dataclasses
Several callbacks pass a dedicated parameter object. The most useful are:
class ImageSaveParams:
image: PIL.Image
p: StableDiffusionProcessing
filename: str
pnginfo: dict # mutate this to change PNG metadata
class CFGDenoiserParams:
x: torch.Tensor # latent being denoised
image_cond: torch.Tensor # for img2img / inpainting
sigma: torch.Tensor
sampling_step: int
total_sampling_steps: int
text_cond: torch.Tensor # positive prompt embedding
text_uncond: torch.Tensor # negative prompt embedding
denoiser: CFGDenoiser # access the wrapper itself
class ExtraNoiseParams:
noise: torch.Tensor
x: torch.Tensor
xi: torch.Tensor
class CFGDenoisedParams:
x: torch.Tensor
sampling_step: int
total_sampling_steps: int
inner_modelMutating these dataclasses in your callback feeds the modified value back into the pipeline.
Ordering
Two layers of ordering apply:
- Within a single callback list, registration order. Extensions registered later run later by default.
metadata.ini[callbacks/<name>]blocks let an extension declareBefore = ext1, ext2and/orAfter = ext3for a specific callback. The runner then does a topological sort.
script_callbacks.add_callback(...) and sort_callbacks(...) implement this. Most extension authors don't need to think about it; ControlNet+ADetailer is the canonical case where ordering matters.
Removing callbacks
Two helpers exist for testing and reload:
remove_current_script_callbacks()— removes every callback registered by the script that's currently being loaded. Used internally during the script-reload path.remove_callbacks_for_function(callback_func)— exact-function removal.
These are rarely useful in normal extension code; they exist for the UI-reload flow that closes and re-creates shared.demo.
Integration points
- The processing pipeline (processing.md) calls
cfg_*,extra_noise,before_image_saved,image_saved,image_griddirectly. - The UI builder (ui.md) calls
before_ui_callback,ui_tabs_callback,ui_settings_callback,before_component_callback,after_component_callback. - The model loader (models.md) calls
model_loaded_callbackandlist_unets_callback. - The reload loop in
webui.pycallsapp_reload_callbackandscript_unloaded_callback. - The infotext utilities call
infotext_pasted_callbackwhenever the "Read generation parameters" button fires.
Entry points for modification
- Add a new callback — declare a
callbacks_<name>list incallback_map, anon_<name>(callback)registration function, and a<name>_callback(...)dispatcher. Then call the dispatcher from the core code at the right point. Document the params object if you add one. - Modify an existing callback's signature — don't, unless you're adding optional kwargs at the end. Extensions in the wild rely on positional argument shapes.
- Debug callback failures —
errors.reportlogs the offending script's filename. Set--loglevel DEBUGfor the full traceback.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.
Previous
Scripts and extensions
Next
Extra networks