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]

Reply via email to