Puck async methods / promises (post-V1.0) GitHub issue

vibecode
{"vibecode": {
    "doc":                  "puck_async_methods",
    "role":                 "deferred design note for asynchronous method dispatch in the Puck protocol — methods that return a promise-shaped handle instead of a materialized value, so the caller can fire many calls in parallel without blocking. Not in V1.0; the V1 definition models synchronous request-response only.",
    "status":               "post-V1.0 — deferred",
    "v1_alternative":       "every method call is a synchronous blocking HTTP request; for parallelism, fork or thread on the client side and run multiple synchronous calls in separate workers",
    "use_cases_blocked":    ["fire_many_remote_calls_concurrently_without_blocking",
                             "compose_async_workflows_with_await",
                             "non_blocking_call_in_event_loop_clients_node_or_browser"],
    "protocol_layers_needed": ["promise_handle_class_at_protocol_layer",
                              "client_side_async_iteration_or_await_model",
                              "cancellation_semantics_what_happens_if_caller_aborts"],
    "related": ["puck/class-definition.md", "puck/protocol.md", "puck/streaming-returns.md"]
}}

Post-V1.0. Puck V1's method dispatch is synchronous and blocking: a client calls a method, the HTTP request goes out, the client thread waits for the response, the method returns when the response arrives. No promise, no future, no await.

This matches Caspian's single-threaded, sync-blocking model and works fine for the overwhelming majority of scripts (sequential request → use the response). But it doesn't fit naturally into event-loop clients (Node.js, browsers) or workflows that want to fire many calls concurrently.

What V1 does instead GitHub issue

A client that needs parallelism uses host-language concurrency primitives outside Puck:

Workable but verbose. Each client has to invent its own pattern.

What async-methods design would need GitHub issue

When this lands post-V1.0:

  1. Protocol-level promise. A method declared async returns a puck.uno/promise (or similar) Puck class instance immediately, before the server has completed the work. The client can call .await() on it to block until the value arrives, or attach callbacks.
  2. Class-definition grammar. A field marking a method as async:
    json
    "weather": {
    "params":      {},
    "returns":     {"class": "https://puck.uno/geo/weather"},
    "async":       true,
    "description": "..."
    }
    
    Or wrap the return type:
    json
    "returns": {"class": "promise", "of": {"class": "https://puck.uno/geo/weather"}}
    
  3. Cancellation. What happens if the caller drops the promise without awaiting? Server-side work should ideally be cancelled. Standard HTTP request cancellation works for the request-out half; canceling server-side computation already in flight is harder.
  4. Client-side ergonomics. Each client picks the idiomatic async pattern for the host language — Python async/await, JS Promises, Caspian (TBD — Caspian has no async story today).
  5. Composition with streaming. Async + streaming together (an async iterator of streamed values) is a richer case; might want to spec independently or together.

Why deferred GitHub issue

When this might land GitHub issue


© 2026 Puck.uno