Open-Source Wikis

/

ComfyUI

/

Packages

/

comfy_execution/

comfyanonymous/ComfyUI

comfy_execution/

The execution engine. Small (2,037 lines, 8 files) but central — every prompt the server queues runs through these modules. comfy_execution/ is invoked by the top-level execution.py (PromptExecutor) and consumed by all nodes via the comfy_api.

Layout

comfy_execution/
├── graph.py            # DynamicPrompt, ExecutionList, ExecutionBlocker, get_input_info
├── graph_utils.py      # GraphBuilder, is_link
├── caching.py          # CacheKeySet, BasicCache, HierarchicalCache, LRUCache, RAMPressureCache, NullCache
├── cache_provider.py   # External cache provider hooks (custom nodes can plug in)
├── jobs.py             # Job objects and lifecycle
├── progress.py         # Progress state, WebUIProgressHandler, PreviewImageTuple
├── utils.py            # CurrentNodeContext, get_executing_context
└── validation.py       # validate_node_input

Key abstractions

Type / function File Description
DynamicPrompt comfy_execution/graph.py Mutable view over a prompt; supports node expansion via add_ephemeral_node
ExecutionList comfy_execution/graph.py DAG traversal with topology + caching
ExecutionBlocker comfy_execution/graph_utils.py Sentinel that short-circuits a branch
GraphBuilder comfy_execution/graph_utils.py Helper for nodes that build subgraphs at runtime
CacheKeySetID, CacheKeySetInputSignature comfy_execution/caching.py Two key derivation strategies — by node ID and by input-signature hash
HierarchicalCache comfy_execution/caching.py The default cache; nests by subcache key for subgraph isolation
LRUCache comfy_execution/caching.py Bounded by entry count
RAMPressureCache comfy_execution/caching.py Drops large entries when free RAM falls below the configured headroom
NullCache comfy_execution/caching.py Disables caching (--cache-none)
register_cache_provider, _get_cache_providers comfy_execution/cache_provider.py External cache plugin API (used by comfy_api.latest.Caching)
Job, JobStatus, get_job, get_all_jobs comfy_execution/jobs.py Job records the executor reads/writes during a prompt
get_progress_state, WebUIProgressHandler, PreviewImageTuple comfy_execution/progress.py Progress fan-out to the WebSocket
CurrentNodeContext, get_executing_context comfy_execution/utils.py Async-context-friendly "what node am I in right now"
validate_node_input comfy_execution/validation.py Pre-execution input validation

How it fits together

graph LR
    Prompt[/prompt JSON/] --> DP[DynamicPrompt]
    DP --> EL[ExecutionList]
    EL -->|next ready node| Exec[execution.PromptExecutor]
    Exec -->|key| Caches{CacheSet}
    Caches -->|hit| Reuse[reuse outputs]
    Caches -->|miss| Run[run node FUNCTION]
    Run --> Outputs[node outputs]
    Outputs --> Caches
    Run -->|node expansion| GB[GraphBuilder] -->|new ephemeral nodes| DP
    Run --> Progress[get_progress_state]
    Progress --> WS[WebUIProgressHandler]

DynamicPrompt is what makes node expansion work. A node can return {"expand": GraphBuilder().build(), "result": (...)}; the executor splices the new nodes into the graph as ephemeral nodes and continues. This is how features like recursive samplers and "Custom Sampler" composition work.

HierarchicalCache indexes by both subcache key (which subgraph context you're in) and data key (the actual input signature). When an ephemeral subgraph runs, its cache lives in a sub-namespace so it doesn't pollute the parent.

Cache modes (CLI mapping)

Flag Cache type Behavior
--cache-classic HierarchicalCache (CLASSIC) Aggressive — drop output ASAP. The historical default
--cache-lru N LRUCache Keep up to N node results, evict by LRU
--cache-ram [G] RAMPressureCache Keep results until free RAM drops below G GB; auto-tune by default
--cache-none NullCache No caching

Selection happens in prompt_worker in main.py; the chosen CacheType flows into execution.PromptExecutor.

External cache providers

Custom nodes can register a cache provider via comfy_api.latest.Caching.register_provider(...). The implementation routes through comfy_execution/cache_provider.py's register_cache_provider. Providers are called in registration order to look up and store cache entries — this is what would let you persist node outputs across processes or share them across machines.

Progress and previews

get_progress_state() is a global progress accumulator. Inside a node, set_progress(value, max_value, preview_image=...) (the V3 API surface) reports back. WebUIProgressHandler formats and pushes events to the WebSocket. Sampling preview images come through here as PreviewImageTuples of (format, PIL.Image, max_size).

Integration points

  • Imported by the top-level execution.py.
  • Imported by server.py for JobStatus, get_job, get_all_jobs.
  • Exposed to custom nodes via comfy_api.latest.Caching and comfy_api.latest.Execution.

Where to start a change

  • Adding a new cache mode: subclass BasicCache in caching.py, expose a CacheType enum entry in execution.py, wire the flag in comfy/cli_args.py, and select it in prompt_worker in main.py.
  • Tweaking node expansion: changes go in graph.py's DynamicPrompt and ExecutionList. Add tests-unit/execution_test/ cases.
  • New progress event types: extend PreviewImageTuple and WebUIProgressHandler in progress.py. Don't forget the protocol bytes in protocol.py.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

comfy_execution/ – ComfyUI wiki | Factory