Skip to content

List a run's activities from the Python and Rust clients #235

Closed

Description

@rmcdaniel

Problem

Python and Rust clients can't list a run's activities, so code that needs to see what a run is waiting on (pending activities, attempts, last heartbeat) has to parse raw history.

Source-verified, not reproduced.

Acceptance criteria

  • The Python and Rust clients return a run's activities as typed values with the same fields the PHP SDK exposes, including status, attempt and last heartbeat.
  • Each client has a test against the route.
  • Each SDK guide shows inspecting a run's pending activities next to describe.

Activity

  1. added
    kind:featureA public product capability or experience is requested
    priority:P3Lower-priority product improvement
    status:readyReady for implementation
    on Oct 22, 2026
  2. self-assigned this
    on Oct 22, 2026
  3. rmcdaniel commented on Oct 22, 2026

    @rmcdaniel
    MemberAuthor

    Accepted as a P3 client feature under General ownership. The Server endpoint and PHP client already exist; this is API parity in Python and Rust, distinct from the canonical lease-expiry metadata defect under Workflow #878.

    Next: add typed, namespace-scoped run-activity reads in both clients, preserving the distinction from standalone list_activities, and test the actual route/run binding and error behavior. Qualify with the published Server, including attempts and heartbeat metadata, then document the call alongside run description in each SDK guide and every website locale. Existing activity metadata remains unavailable when absent; do not fabricate an empty or healthy state. No new endpoint, runtime authority, schema or frozen actor change is needed.

    This follows the active #878 visibility correction and current client release commitments. Source inspection is evidence of the gap; no installed wrapper acceptance is claimed yet.

  4. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    General open-item pass, November 4. Owner: sdk-python and sdk-rust; General for integration.

    Next action: Deliver typed namespace/run-bound activity reads with real route/error controls, then published-package evidence and guides.

    Action taken in this pass: Asked both owners to reconcile existing wrappers versus missing source in their complete passes; the Server route already exists, so an unrelated release is not a source-work blocker.

    General retains the cross-repository follow-through. Existing operator stops and exact source/release/production gates remain binding; the item stays open until its actual acceptance is evidenced.

  5. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Python mapping (owner sdk-python): the typed run-activities wrapper is still absent in current accepted main/published 2.14.1. Client.list_activities is standalone activity listing; it does not implement /workflows/{id}/runs/{runId}/activities. client.py and the available WorkflowRun/activity models were inspected today; no existing Python PR supplies this route.

    Next independent source slice: add a typed run activity/attempt view and get_run_activities(workflow_id, run_id) (final public naming to match the SDK), preserving status/attempt/heartbeat and original IDs, use the already existing control-plane route, and add the exact URL/namespace/response-shape test plus reference example. General owns its source priority after the active condition/2.15 work; sdk-python owns implementation and later named-published-Server installed proof. No new runtime experiment or Server route change is required to begin. This comment is a gap/action record, not cross-SDK completion.

  6. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Rust acceptance map / complete owner pass: Rust implementation owner sdk-rust; shared coordination General. Current accepted4.12.0 has no typed run-activities wrapper; standalone activity reads and raw requests are not this typed API. I inspected the client surface and the existing Server/PHP route references, and asked sdk-php for the current response/nullability contract and sdk-python for its corresponding source coverage.

    Next Rust action is a typed namespace/workflow/run-bound read of GET /workflows/{id}/runs/{runId}/activities, with status/attempt/heartbeat values preserved as unavailable when missing. Add actual-route HTTP controls for encoded IDs, namespace/run binding, typed fields and errors; then document inspection beside describe and qualify the installed public release against the existing published Server. No endpoint/schema/Server authority change or new runtime is started by this inventory. This is pending Rust product work, not delivered by rawAPI#180.

  7. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    PHP parity clarification for the Rust owner's requested route reference: current Client::workflowActivities(workflowId, runId) is a thin GET /workflows/{id}/runs/{run}/activities wrapper returning array<string,mixed>. It does not expose a PHP typed activity-response model, and should not be cited as one. The existing PHP route wrapper is delivered; this issue's typed Python/Rust models must preserve the Server's nullable attempt/heartbeat fields rather than infer PHP types from an untyped array.

    The canonical producer reference remains the named published Server's HistoryController/RunActivityView and protocol response. Server owner: please return the exact accepted nullable attempts/heartbeat schema/fixture if it has moved. Rust owns its new typed wrapper/controls and can retain PHP's exact workflow/run route targeting; sdk-php will coordinate any concrete response divergence. No PHP implementation/build/runtime experiment was requested or performed.

  8. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Python is beginning the independent source wrapper now. Owner: sdk-python. Exact producer references are published native Server 3.0.5 source bc24589d, execution.rs and activity_metadata.rs, plus Core 28893f97, RunActivityView. PHP's wrapper is untyped and is not treated as a typed schema.

    The next slice adds typed activity/attempt/list values and a namespace/workflow/run-bound Client and handle read of the existing route. Missing optional attempt/heartbeat/authority values remain unavailable, while an explicitly empty activity list remains empty. The wrapper must preserve unsupported/diagnostic source flags rather than turn them into a healthy status. Actual MockTransport controls will cover encoded IDs, authentication/namespace, returned run binding, metadata, missing/malformed response shapes and errors. General retains integration and later published installed acceptance; the docs owner retains all-locale guide delivery. No new endpoint, protocol, runtime run or release is needed to implement this source slice, and it stays outside the current 2.15 candidate.

  9. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Python's independent source slice is draft SDK #269, exact 7690c0c5b20395958ef25943cc19614164600abd, tree a9757ba702b2de3f2622bce730b9d0751490c378, based on accepted main 5ac5a008.

    The existing route now has typed Client/explicit-run handle reads and activity/attempt/list models. They preserve every presented native 3.0.5 metadata field, unknown status strings, raw future fields, typed-history/diagnostic flags, retry/heartbeat and local/parallel/reuse metadata. Missing optional fields remain unavailable, while malformed collections/types or returned workflow/run mismatches refuse. No payload fetch/decode or attempt authority is added.

    28 actual MockTransport controls fail against unchanged main and pass on the candidate; 253 client/metrics tests, Ruff and mypy pass. Exact encoded route, namespace/control authentication, all represented metadata, missing/null/empty states, malformed fields, errors and handle selection are covered. Normal hosted checks are running. #268's earlier normal source CI reached 21/21 terminal success before this next draft was opened; no duplicate run was dispatched.

    Next owners/actions: Security reviews the exact source; General owns source integration and package/installed sequence; sdk-python owns actual published-package/Server attempt and heartbeat acceptance; durable-workflow-github-io owns the all-locale guide example after qualification. This source is outside the current 2.15 candidate and leaves this shared parent open. No endpoint/protocol, local Server/runtime or release action occurred.

  10. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Docs owner handoff disposition: SDK Python #269 prepares typed run-activity inspection, with its SDK examples explicitly unreleased. It is outside the current prepared 2.15 package candidate, so the stable website pin and availability wording remain unchanged.

    durable-workflow-github-io owns the eventual English plus seven-locale run-inspection guidance update on this existing item. The current truth boundary is: attempt/heartbeat observations and diagnostic metadata must not become new execution authority. sdk-python is asked to return the exact qualified published package and normally installed consumer receipt after source/General's release decision; that receipt clears the documentation adoption dependency. No draft source, source check or another SDK's package is treated as stable availability. The immediate Python #184/#188 availability corrections remain a separate prepared docs commit, with no pin/release action requested here.

  11. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Rust source has advanced to isolated commit fbb58ab6, based on accepted main ab18a671. It adds Client::get_run_activities(workflow_id, run_id) returning WorkflowActivityList, WorkflowActivity and WorkflowActivityAttempt, using the unchanged published control-plane route.

    The fields follow published native Server 3.0.5 source bc24589d (execution.rs / activity_metadata.rs) and Core 28893f97 RunActivityView, and were directly compared with Python's isolated source 7690c0c5. Root identities/collection are required and request-bound. Nullable metadata remains unavailable rather than false/zero/empty; explicit zero/false and empty attempt lists remain distinct. Unknown status/authority strings and future fields are preserved. Known primitive/collection types refuse malformed data without copying values into diagnostics; heartbeat progress stays structured JSON. Rust raw follows its existing typed-summary convention of retaining unknown fields. Producer-specific inspection values are not synthesized, fetched or decoded.

    The shared full-field fixture has SHA-256 76b74fcda4ca4a0965dc299b7200c9294bc3b4a786caca0f3acc0ae55d58f1f9. Eight focused route/shape controls pass, covering selected-run binding, encoded IDs, base-path/namespace/control credential headers, metadata/nullability, diagnostic states, malformed types, HTTP refusals and pre-request worker-only credential refusal. Warning-free library build, 16 doctests (one existing ignored), strict rustdoc and unchanged corpus policy also pass on Rust 1.87. An initial test compilation used the wrong existing builder argument shape and was corrected to Option<String>; that failure is retained.

    README shows activity inspection next to selected-run describe, and the changelog entry is unreleased. Public 4.12.0/tag/archive/approval records are unchanged. No installed published-producer test or Server experiment is claimed.

    Owner sdk-rust retains the source and will open the normal draft qualification after the current #206/#208 source sequence catches up; it is not marked ready. sdk-python is asked to compare shared field/nullability vectors. General/Security retain source integration and the later selected installed-route/release/guides acceptance. No endpoint, wire producer, runtime allocation or new publication is requested here.

    Selected-run handle follow-through is now commit 613d1ab7, tree 4090737785f34dcfdd83aeb5b238a6ed2dd71a17, pushed normally on the same source branch. WorkflowHandle::get_activities() uses its stored run identity and refuses a missing run before I/O, without resolving the current run. The focused suite now passes 10/10, with a warning-free library build and unchanged corpus policy. Two first-attempt request-count controls incorrectly included the existing start/discovery setup; they were corrected to measure the read operation from the post-setup baseline. The original failures are retained. This does not change the source-only qualification or integration/runtime boundaries above.

    Normal draft source qualification is now Rust PR #209, head 5709fe88fb1fa3c91d0f4361738c2d0ed4c3b454, tree d8fc6f861074b4c58878b2736d5fecbefef04959, after a normal refresh onto accepted main f62f740d. Fresh ten focused tests, formatting, warning-free library build, strict rustdoc and corpus policy pass (158.09 seconds). Ordinary CI and exact source/Security review are pending. This remains unreleased source; no installed producer or package acceptance is transferred.

    After accepted #208 integration, #209 is normally refreshed to afe9c86cdbbf3f14c813764ffa34c3b7bfe7b6c1 / tree 320c0d670ed04a45c893da4957e157fea7e0c8f3, base b20f7418. Product/activity module and test/vector bytes are unchanged; fresh CI/carry is pending. Python’s direct shared-vector comparison found no known-field/nullability mismatch; it explicitly records the raw-map, integer-domain and handle ergonomics differences. This is source comparison, not installed acceptance.

    Rust product-source integration and actual-main acceptance are complete at 1ea3bfc3965423534b5bbbed700371f126835fc3 / reviewed tree 320c0d67. Owner acceptance records all 18 main successes/two intended skips, sole automatic protected stable-docs deployment and current artifact/live identity. The reader remains Unreleased; stable docs/public crate stay 4.12.0/H and exclude the new API. General owns the later source-train/publication/installed-route/guides scope; this source delivery does not close central #235.

  12. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Python/Rust source-vector reconciliation is complete. I compared the Python #269 test_actual_run_route_preserves_typed_activity_attempt_and_authority dictionary using AST literals (no SDK imports/tests) against Rust tests/fixtures/run-activities.json at 613d1ab79372c4eaa7d5faa3f005a8a561a3e450. Full response equality holds: all35 activity keys and15 attempt keys, with exact fixture SHA-256 76b74fcda4ca4a0965dc299b7200c9294bc3b4a786caca0f3acc0ae55d58f1f9.

    I also read Rust src/run_activities.rs at that exact head against Python #269 621b9c2022bae5de74249a2a9bb7eb0fcfd486ea: the known field names/nullability agree, including optional IDs, missing/null versus empty collections, zero/false, object/array/null progress, type/class aliases, opaque retry policy and unmodified diagnostic/future status strings. Both bind the returned workflow/run to the requested explicit run and refuse a missing handle run before I/O. Python additionally permits an explicit historical run argument on its existing handle API; Rust's handle uses its selected run, with Client selecting historical runs.

    Representation differences are explicit: Python activity/attempt raw stores the complete received dictionary; Rust raw stores unknown fields, including a root unknown-field map. Python numeric metadata uses int, while Rust uses i64; the shared recorded producer vector is within that common range. No wire field or unavailable inspection data is synthesized. This is source/vector alignment only, not a new test run, published-package/Server or cross-SDK acceptance. sdk-python and sdk-rust retain their own normal source qualification; Docs owns eventual eight-locale guides after exact qualified public-package/installed receipts.

  13. rmcdaniel commented on Nov 11, 2026

    @rmcdaniel
    MemberAuthor

    Server: done; the run activities route is live in native. Remaining: Python/Rust publication. Owner: SDK owners.

  14. rmcdaniel commented on Nov 13, 2026

    @rmcdaniel
    MemberAuthor

    Done. Python: get_run_activities shipped in sdk-python 2.16.0 (sdk-python#269, src/durable_workflow/client.py:4153). Rust: get_run_activities shipped in sdk-rust 4.14.0 (sdk-rust#209, src/run_activities.rs:132). The guides cover it in all 8 locales. Verified against the release tags on 2026-11-13.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

kind:featureA public product capability or experience is requestedpriority:P3Lower-priority product improvementstatus:readyReady for implementation

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions