ag-ui-protocol / ag-ui-protocol/ag-ui

[Bug]: [ag-ui-langgraph] Time-travel is not triggered when regenerating the first assistant message

Open
#2,109 3 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Python
Stars
15.9k
Forks
1.4k
Avg merge
1d 17h
Merged PRs (30d)
163

Description

### Pre-flight Checklist

- [x] I have searched [existing issues](https://github.com/ag-ui-protocol/ag-ui/issues) and this hasn't been reported yet.
- [x] I am using the **latest** version AG-UI.

### Describe the Bug

Regenerating the first assistant response in a conversation never enters the time-travel path.
Instead, the request is treated as a continuation and prepare_regenerate_stream() is never called.

### Steps to Reproduce

1. Start a new conversation.

Frontend:

User(id=u1): "Hello"

2. The assistant responds.

Checkpoint:

User(id=u1)
Assistant(id=a1)

3. Click "Regenerate" on that first assistant response.

The frontend sends the conversation truncated to the last user message (or user + empty assistant placeholder).

4. Observe that the backend never enters prepare_regenerate_stream().

### Expected Behavior

The first assistant response should be regenerated by performing a time-travel from the user message.

### Environment

```text
ag-ui-langgraph 0.0.42
deepagents 0.6.3

python 3.11.0
```

### Screenshots

_No response_

### Logs & Errors

```shell

```

### Additional Context

In prepare_stream(), regenerate detection only starts when:

```
non_system_messages = [
msg for msg in langchain_messages
if not isinstance(msg, SystemMessage)
]

if len(agent_state.values.get("messages", [])) > len(non_system_messages):
```

Consider the first assistant response in a conversation.

The checkpoint contains:

Human(id=u1)
AI(id=a1)

so the checkpoint has 2 messages.

When the frontend triggers a regenerate request, it sends:

Human(id=u1)
AI(id="")

After converting to LangChain messages, this still results in:

Human
AI

which also contains 2 messages.

Therefore, the condition evaluates to:

2 > 2 // false

As a result, the regenerate detection logic is skipped entirely, and prepare_regenerate_stream() is never reached.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.