GitHub user pltbkd added a comment to the discussion: [Feature] Sub-agent Resource for Flink Agents - Framework part
Hi @alnzng @weiqingy @ofekron @joeyutong I have created a PR for this framework: https://github.com/apache/flink-agents/pull/938. I think it will help us ground the design discussion in concrete code, and I can land any conclusions we reach directly on the PR. The recent discussion made me think through the interface design once more. I'd like to share the reasoning behind the current `asDurableCallable` interface and propose two alternatives for feedback. ## Background A key constraint is that `durableExecuteAsync` is inherently a combined "execute + yield" operation — it submits the callable for off-mailbox execution and suspends the current action until the callable completes. There is no "submit-only" mode that returns a pending handle without yielding. For external sub-agents, the actual request (e.g., an HTTP call) must reside inside `DurableCallable.call()` (and its `reconcile` path) so that the durable execution mechanism can record, checkpoint, and replay it for recovery. This means issuing the request requires invoking `durableExecuteAsync`, which in turn requires a yield. The consequence: if `submit` encompasses the full durable execution flow, the caller always suspends at that point — making it impossible to submit multiple requests before waiting, or to perform additional work between submit and result retrieval. This led to the current interface: `asDurableCallable` is an explicit declaration — "I only prepare the callable; I do not execute it." The actual execution (and yield) happens only when the caller passes it to `durableExecuteAsync` / `durableExecuteAllAsync`. This preserves access to parallel batch execution while guaranteeing durable execution is used. ## The concern I do find this interface unintuitive. Using `DurableCallable` as the caller-facing method forces callers to reason about the execution process (prepare → submit → yield) rather than focusing on their own semantics. A `submit` + `Future`/awaitable model would better match caller expectations. (This also echoes @weiqingy's point: "the public API could keep an invocation-oriented operation on the sub-agent surface, with DurableCallable staying the mechanism underneath.") ## Two alternatives ### Option A — `submit` = `durableExecuteAsync` (eager, serial) `submit()` internally calls `durableExecuteAsync(asDurableCallable(...))` and returns an already-completed result (or a `Future` that is resolved by the time the action resumes). Simple and straightforward, but the caller always yields at each call — only serial execution is possible. If a sub-agent implementation needs fire-and-forget parallelism, it would have to manage the lifecycle and reconciliation entirely on its own, outside the durable execution framework. ### Option B — `submit` records only; `get`/`await` triggers execution (lazy, parallel-capable) `submit()` only records the invocation parameters and returns an unresolved `Future`. The actual `durableExecuteAsync` is triggered on the first `get()`/`await`. A utility like `Futures.of(f1, f2).get()` maps to `durableExecuteAllAsync` for batch parallel execution. - **Pro:** supports parallel execution; guarantees durable execution; natural `submit` → `Future` mental model. - **Con:** lazy semantics — between `submit()` and `get()`, the request has not been sent; `isDone()` is always `false` until resolved. This may surprise callers who expect `submit` to have side effects. My POC originally implemented Option B. I moved away from it to the current `asDurableCallable` design because I was concerned the lazy semantics could confuse users. However, given the feedback that the current surface is not ideal, I'm reconsidering. ## Question Do you prefer Option A (simple, serial), Option B (lazy, parallel-capable), or keeping the current `asDurableCallable` interface? GitHub link: https://github.com/apache/flink-agents/discussions/909#discussioncomment-17871128 ---- This is an automatically sent email for [email protected]. To unsubscribe, please send an email to: [email protected]
