From 377c8a2ca5e9e222135100ba5a532e26c961d826 Mon Sep 17 00:00:00 2001 From: Richard McDaniel <1130888+rmcdaniel@users.noreply.github.com> Date: Fri, 13 Nov 2026 13:47:38 +0000 Subject: [PATCH] docs: explain query receipt return values --- docs/reference/client.md | 16 ++++++++++++++++ docs/sdk-reference.md | 6 ++++++ src/durable_workflow/client.py | 9 ++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/reference/client.md b/docs/reference/client.md index 7440843..b48c524 100644 --- a/docs/reference/client.md +++ b/docs/reference/client.md @@ -1,5 +1,21 @@ # Client +## Read a query result + +`Client.query_workflow()` returns the Server's receipt. Read its `result` +member for the decoded value returned by the query handler: + +```python +receipt = await client.query_workflow("approval-1", "status") +status = receipt["result"] +print(status["approved"]) +``` + +The receipt also identifies the workflow, run and query. A successful handler +may return `None`; that value appears in `receipt["result"]`. Query failures +raise `QueryFailed`. `WorkflowHandle.query()` and the synchronous client +return the same receipt shape. + ## Read an update outcome `Client.update_workflow()` returns a Server receipt. Its default wait stage is diff --git a/docs/sdk-reference.md b/docs/sdk-reference.md index 3d15019..c80ab55 100644 --- a/docs/sdk-reference.md +++ b/docs/sdk-reference.md @@ -607,6 +607,12 @@ after that discovery succeeds. `Client.query_workflow()` checks the same manifest before sending a query and raises `RuntimeCapabilityUnsupported` or `RuntimeDiscoveryUnavailable` with remediation when the route cannot be used. +`Client.query_workflow()` and `WorkflowHandle.query()` return the Server's +receipt. The decoded handler value is in `receipt["result"]`, including a +successful `None` result. See the [query result example](reference/client.md#read-a-query-result). +The synchronous client returns the same receipt shape. Query failures raise +`QueryFailed`. + Python workers advertise declared update validators and evaluate them on a dedicated synchronous validation task before the Server records an accepted update. Validation replays the authoritative workflow state without committing diff --git a/src/durable_workflow/client.py b/src/durable_workflow/client.py index 18e17e8..e2f33e1 100644 --- a/src/durable_workflow/client.py +++ b/src/durable_workflow/client.py @@ -4966,11 +4966,14 @@ async def append_message_stream( async def query_workflow( self, workflow_id: str, query_name: str, *, args: list[Any] | None = None ) -> Any: - """Execute a named read-only query against a workflow and return the result. + """Execute a named read-only query and return the Server's receipt. Queries are synchronous and non-mutating. The server runs the named - query handler inside the workflow process and returns the decoded - result. Raises :class:`~durable_workflow.errors.QueryFailed` if the + query handler inside the workflow process. The returned ``dict`` + includes workflow/run identities and ``query_name``; its ``result`` + member holds the decoded handler value, which may be ``None``. + Read ``receipt["result"]`` to obtain that value. + Raises :class:`~durable_workflow.errors.QueryFailed` if the query was rejected, the handler errored, or the original query timed out. A canonical query timeout is surfaced without automatically admitting another query.