Prompt Progress
Interim progress of a prompt, for clients that stream the prompt api’s response.
A prompt can take a while: the LLM may call tools, plugins and MCP servers, and each tool call
adds another round trip to the LLM. A client that sends Accept: text/event-stream to a
LLMClient’s prompt api receives Server-Sent Events (SSE) while the prompt runs, followed by the
same JSON that a non-streaming client receives. See
smarter.apps.llmclient.api.v1.views.base.LLMClientApiBaseViewSet.
The prompt itself runs synchronously, in a worker thread, exactly as it does for a non-streaming
client. Its progress comes from the signals that the prompt already sends (chat_request,
llm_tool_requested, chat_plugin_called, mcpclient_tool_called, …). The receivers in
this module forward them to the sink of the prompt that sent them, which is held in a
contextvars.ContextVar, so that concurrent prompts never see each other’s events.
SSE payload format
retry: 3000is sent once, first.event: progresswithdata: {"type": ..., "message": ..., ...}for each step.: keepalivecomments while the prompt is idle, e.g. waiting on the LLM.event: resultwithdata: {"status": <http status>, "response": <the api's json>}, last.
- class smarter.apps.prompt.progress.PromptProgressEvents[source]
Bases:
objectThe
typeof each progress event.- LLM_REQUEST = 'llm_request'
- MCP_TOOL_CALLED = 'mcp_tool_called'
- MCP_TOOL_FAILED = 'mcp_tool_failed'
- MCP_TOOL_RESPONDED = 'mcp_tool_responded'
- PLUGIN_CALLED = 'plugin_called'
- TOOL_REQUESTED = 'tool_requested'
- TOOL_RESPONDED = 'tool_responded'
- smarter.apps.prompt.progress.emit(event_type, message, **detail)[source]
Send a progress event to the current prompt’s sink, if it has one.
A prompt without a streaming client has no sink, so this does nothing. A failing sink is logged, and never fails the prompt.
- Parameters:
event_type (
str) – One ofPromptProgressEvents.message (
str) – A short, human-readable description of the step.detail (
Any) – Other JSON-serializable fields of the event.
- Return type:
- smarter.apps.prompt.progress.progress_sink(sink)[source]
Send the progress events of the prompt that runs in this context to
sink.
- async smarter.apps.prompt.progress.prompt_event_stream(complete, on_error)[source]
Run a prompt in a worker thread, and yield its progress, then its result, as SSE frames.
- Parameters:
complete (
Callable[[],HttpResponse]) – Runs the prompt synchronously, and returns the prompt api’s JSON response.on_error (
Callable[[Exception],HttpResponse]) – Returns the prompt api’s JSON error response for an exception thatcompleteraised.
- Yields:
SSE frames: progress events and keepalives, then the result.
- Return type:
AsyncIterator[str]
- smarter.apps.prompt.progress.prompt_event_stream_response(complete, on_error)[source]
The prompt api’s response as Server-Sent Events.
- Parameters:
complete (
Callable[[],HttpResponse]) – Runs the prompt synchronously, and returns the prompt api’s JSON response.on_error (
Callable[[Exception],HttpResponse]) – Returns the prompt api’s JSON error response for an exception thatcompleteraised.
- Returns:
A streaming
text/event-streamresponse, whose http status is always 200. The prompt’s own status is in itsresultevent.- Return type:
- smarter.apps.prompt.progress.wants_event_stream(request)[source]
True if the client asked for the prompt api’s response as Server-Sent Events.
- Parameters:
request (
HttpRequest) – The prompt api’s request.- Returns:
True if the request’s Accept header includes
text/event-stream.- Return type: