Comfy-Org / Comfy-Org/ComfyUI

[RFC] Add prompt queue and execution lifecycle hooks for Python extensions

Open
#15,341 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
Python
Stars
133k
Forks
15.7k
Avg merge
1d 7h
Merged PRs (30d)
158

Description

## Feature Idea

We run ComfyUI behind a service and need to follow a prompt from queue insertion to a final state. There is currently no supported Python extension API for doing that. Extensions have to poll history, interpret client-facing WebSocket messages, or patch `PromptQueue` and `prompt_worker()`.

Two open issues cover parts of this problem:

- #8029 asks for hooks around prompt queue operations.
- #11540 describes the gap between `execution_success` and the point where outputs are available in `PromptQueue.history`.

This RFC is narrower than #8029's combined backend/frontend request and does not change the timing of `execution_success` from #11540. It proposes a typed backend lifecycle API for V3 server extensions, including a completion boundary after `PromptQueue.task_done()` returns.

The proposed extension surface is:

```python
from comfy_api.latest import ComfyExtension, ExecutionLifecycle

class MyHandler(ExecutionLifecycle.Handler):
def on_succeeded(self, event):
print(event.prompt_id)

def on_failed(self, event):
print(event.prompt_id, event.exception_message)

class MyExtension(ComfyExtension):
async def on_load(self):
await ExecutionLifecycle().register(MyHandler())

async def get_node_list(self):
return []

async def comfy_entrypoint():
return MyExtension()
```

Handlers can override methods for six events:

```text
QueuedEvent
StartedEvent
SucceededEvent
FailedEvent
InterruptedEvent
CancelledEvent
```

The last four are mutually exclusive terminal events in the normal queue and worker flow. `SucceededEvent` is published only after `PromptQueue.task_done()` returns, so a server extension can treat it as a finalized in-memory history boundary without changing the existing WebSocket protocol.

The design keeps the integration deliberately narrow:

- handlers are registered while V3 extensions load, then routing is frozen;
- handler filtering and callbacks run on a dedicated in-process dispatcher thread;
- handler failures cannot affect prompt execution, history updates, other handlers, or later events;
- the six-element queue item and `PromptQueue.get() -> (item, item_id)` remain unchanged;
- existing HTTP, WebSocket, history, job, and workflow formats remain unchanged;
- core ComfyUI performs no external I/O for lifecycle events.

I have a detailed design and a tested draft implementation covering event fields, publication points, metadata isolation, terminal-state precedence, delivery boundaries, and regression tests.

The main questions for maintainers are:

1. Is `comfy_api.latest.ExecutionLifecycle` the right public surface for server extensions?
2. Do these six event boundaries match the lifecycle ComfyUI should expose?
3. Is a single in-process FIFO dispatcher an acceptable way to keep extension code off queue and worker threads?

I am willing to maintain the implementation, tests, generated API stubs, and any concise documentation requested for the public API.

## Existing Solutions

WebSocket events and history polling are useful client APIs, but they are not a Python extension callback contract. A workflow node also cannot observe queue insertion, removal before execution, or history finalization. Local monkeypatches can expose these points, but they are fragile and can conflict with other extensions.

## Other

This proposal does not add webhooks, Redis, Kafka, database writes, retries, durable delivery, or node-level progress events. Those remain extension responsibilities.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the proposed comfy_api.latest.ComfyExtension and ExecutionLifecycle surface, then trace PromptQueue, prompt_worker(), and the PromptQueue.task_done() boundary. Compare the six event boundaries and dispatcher constraints with the existing V3 extension loading and queue flow. Done means maintainers agree on the API and lifecycle semantics, with the implementation, regression tests, generated stubs, and concise documentation updated as requested.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.