Replies: 1 comment 1 reply
|
Thanks for putting this together. Savepoint-based replay seems like a promising direction, and Flink already provides a consistent snapshot of the agent’s keyed state. After looking through the current runtime, I wonder if a few recovery and isolation details need to be defined more precisely. How would the agent state map to the replay topology after replacing the live source? Flink restores state by operator ID, but the current How would a savepoint identify the exact starting point in the captured input? Flink’s exactly-once state guarantee relies on restoring both operator state and the matching source position. Since I also wonder whether an ordinary savepoint contains too much execution state for this use case. Flink Agents checkpoints pending How should the external action-state store be handled? Restoring the savepoint rebuilds action state from the configured Kafka topic or Fluss table, while new replay actions write back to that same store. Because the store keys include the business key and sequence number but no replay namespace, could running production and replay together create divergent recovery records? Would replay need a separate store with restored recovery markers removed or rewritten? Long-term memory has a similar question. The restored job identifier points to the production Mem0 namespace. A new identifier would isolate replay writes, but it would no longer expose the production long-term memory being evaluated. Would a read-only snapshot or fork of that namespace be needed? Finally, can an Action-level Perhaps a focused first version could combine stable operator IDs, a savepoint-linked input manifest, replay-safe state projection, isolated external state, and replay-aware resource proxies. Would that give the feature a safer and more testable starting point? |
Uh oh!
There was an error while loading. Please reload this page.
Following up on #1066 since @wenjin272 asked for a concrete design before this goes anywhere. Putting a rough shape here to argue about, not committing to build it myself.
The gap
Right now the only way to know how a change to an agent (new prompt, different model, tweaked parameters, changed Action logic) will actually behave is to ship it and watch. There's no way to run it against state the agent has already built up and see what happens first.
This is a decent fit for Flink Agents specifically because agent state is already durable and keyed, so a savepoint is a real, consistent snapshot to replay against - not something that needs to be built from scratch for this.
Rough shape
The core idea: a replay job is a regular Flink Agents job started from a savepoint, but reading from a recorded input stream instead of live traffic, with external side effects intercepted instead of fired.
That breaks down into three parts.
Capturing the input. An opt-in sink attached to the existing input stream that records the keyed events in order (event time, key, payload) so there's something deterministic to play back later. Doesn't touch runtime state - it just sits next to the existing pipeline.
Running the replay. Flink already lets you start a job from a savepoint (
bin/flink run -s :savepointPath). Point that at aReplaySourcereading the recorded stream instead of the real source, keeping per-key ordering and event-time so watermarks and keyed state behave the same as the original run.Containing side effects. This is the part I'd want the most pushback on. Actions that call out to a ChatModel or a tool need to behave differently in replay - either the call gets redirected somewhere inspectable instead of firing, or (if the whole point is testing a new prompt against real state) the call is allowed but anything not explicitly marked safe to repeat gets blocked. My instinct is a
ReplayContextreachable fromRunnerContext, defaulting to "don't execute, just record what would have happened" unless an Action opts in as idempotent/read-only.What it shouldn't need
No changes to checkpoint or recovery semantics - from Flink's point of view a replay job is a normal job, just pointed at a different source. No new keyed state either; the capture sink and the savepoint restore both reuse what already exists.
Where I'm not sure
No illusions about timing given the 0.4 freeze on Sept 15 - just want the shape settled for whenever it does get picked up.
All reactions