When you're chatting with an AI agent, two things go wrong most often: the model produced an answer you don't want, or the model stopped too early and you'd like it to keep going.
SolonCode's Web UI solves both problems with two small icons — Re-run and Continue — that sit next to every AI response bubble. They look alike (same toolbar, same spot) but do very different things under the hood.
This article walks through what each button does, what the code does when you click it, and when you should use one versus the other.
The two buttons at a glance
Every AI response row in SolonCode Web shows four action icons to its right:
- Copy — copies the final answer to the clipboard
- Re-run (循环箭头) — replays the last user message from scratch
- Continue (快进) — extends the last AI response without deleting anything
- Delete — removes the response and everything after it
The Re-run and Continue buttons are the focus here. Both send a command to the engine (/rerun and /continue), but the effect on the conversation is fundamentally different.
Re-run (重新运行): replay the turn, delete the old answer
What you see
You type "Refactor OrderRepository to use Solon Data" and the agent returns a response with code changes. You open the result and decide the approach is wrong — maybe it touched too many files, or used the wrong pattern. You click the Re-run icon on that AI response.
The old AI bubble vanishes. A new one appears in its place, and the agent starts thinking again.
What the code does
The RerunCommand (org.noear.solon.codecli.command.builtin.RerunCommand) implements the command:
- Walk backwards through the session message list until it finds a
UserMessage. - Strip that user message and everything after it from the session (
session.removeLatestMessage(1)in a loop). - Call
ctx.runAgentTask(lastUserInput, null)— the same input, a clean slate.
// RerunCommand.java (simplified)
List<ChatMessage> messageList = session.getMessages();
String lastUserInput = null;
while (!messageList.isEmpty()) {
ChatMessage msg = messageList.get(messageList.size() - 1);
if (msg instanceof UserMessage) {
lastUserInput = msg.getContent();
session.removeLatestMessage(1);
break;
}
session.removeLatestMessage(1); // strip AI messages too
}
ctx.runAgentTask(lastUserInput, null);
The Web UI mirrors this by removing every DOM element with the same data-run-id — the AI bubble, any tool cards, thinking blocks, everything from that turn — so the new response renders in a clean bubble.
When to use Re-run
- The agent's last answer is wrong and you want to try again with the same prompt
- The agent took a wrong turn mid-response and you want it to pick a different path
- You want to test whether a different model or a different system prompt would give a better result on the same input
Key property: Re-run preserves your conversation history up to the last user message, then replays that message. Everything after the user message is discarded.
Continue (继续运行): extend the response, keep what's there
What you see
The agent responded with a partial refactor — it changed OrderRepository but stopped mid-way through PaymentService. You click Continue and the same bubble stays; new content simply flows into it, like the agent kept typing.
What the code does
ContinueCommand (org.noear.solon.codecli.command.builtin.ContinueCommand) takes a different approach. Instead of discarding the last turn, it manipulates the agent's internal execution trace:
- Look up the
ReActTracestored in the session context under"__main". - If the trace's current route is
Agent.ID_END(meaning the agent has already reached its final answer node), reset the route back toReActAgent.ID_REASON— putting the agent back in "thinking" mode. - Clear the final answer from the trace (
trace.setFinalAnswer(null, false)). - Remove the last assistant message from working memory and from the session (so it will be regenerated).
- Call
ctx.runAgentTask(null, null)— the agent picks up from where it left off.
// ContinueCommand.java (simplified)
ReActTrace trace = session.getContext().getAs("__main");
if (trace != null) {
if (Agent.ID_END.equals(trace.getRoute())) {
trace.setRoute(ReActAgent.ID_REASON); // go back to thinking
trace.setFinalAnswer(null, false); // clear the old answer
ChatMessage workMessage = trace.getWorkingMemory().getLastMessage();
if (workMessage instanceof AssistantMessage) {
trace.getWorkingMemory().removeLastMessage();
}
List<ChatMessage> messageList = session.getMessages();
if (Assert.isNotEmpty(messageList)
&& messageList.get(messageList.size() - 1) instanceof AssistantMessage) {
session.removeLatestMessage(1); // remove the completed reply
}
}
}
ctx.runAgentTask(null, null); // continue from current state
Because the trace is reset to the reasoning step, the agent doesn't start a new conversation — it continues the same reasoning chain, appending to the existing response.
On the Web UI side, the Continue button sends /continue with removeRow=false, so the existing bubble stays visible and new content simply appends to it.
When to use Continue
- The agent stopped mid-task (e.g., refactored 3 of 12 files) and you want it to keep going
- The agent's last answer was mostly right but incomplete
- You want the response to feel like a natural extension, not a re-do
Key property: Continue does not discard anything. It preserves the conversation history and the agent's reasoning state, then asks the agent to pick up where it stopped.
Side-by-side comparison
| Re-run | Continue | |
|---|---|---|
| Command | /rerun |
/continue |
| Deletes old response? | Yes — removes the entire run | No — appends to the same bubble |
| Strips history? | Yes — removes everything after the last user message | No — preserves all history |
| Resets agent state? | Yes — starts fresh with the same prompt | Partially — resets trace to reasoning step, keeps context |
| Preserves tools/skills? | Yes — same session, same tools | Yes — same session, same tools |
| Best for | "That answer was wrong, try again" | "That answer was incomplete, keep going" |
| Web UI icon | Loop arrow (循环箭头) | Fast-forward (快进) |
| i18n key | msg.rerun |
msg.continue |
| Chinese label | 重新运行 | 继续运行 |
A concrete example
Imagine you ask SolonCode: "Migrate the UserService from Spring Data JPA to Solon Data."
Scenario A — the agent got the migration wrong
The agent produced a response that uses the wrong Solon Data API. You click Re-run. The old response disappears, the agent thinks again, and this time produces a correct migration. Your history now has the corrected response in place of the old one.
Scenario B — the agent stopped halfway
The agent migrated findUserById but stopped before findByEmail. You click Continue. The same bubble stays, and the agent keeps typing — now adding findByEmail to the response. Nothing is deleted.
Scenario C — the agent hallucinated a dependency
The agent's response included a @Component on a class that shouldn't have one. You click Re-run. The agent re-thinks and this time produces a cleaner response. Then you realize the response is still missing deleteById, so you click Continue to add it.
How the commands are exposed
Both /rerun and /continue are registered as built-in commands (since v2026.4.28):
-
CLI: type
/rerunor/continuedirectly in the terminal - Web UI: click the icon on any AI response bubble
-
IM channels (飞书/钉钉/微信): send
/rerunor/continuein chat — the IM bot forwards the same command to the engine
In the Web UI, RerunCommand and ContinueCommand are not marked cliOnly(), so they appear in the /web/chat/hints endpoint and are available from any channel.
Under the hood: the runId linkage
One detail worth understanding is how the Web UI knows which elements belong to a single "run."
Every message element — the AI bubble, tool cards, thinking blocks — is stamped with data-run-id (the same ID assigned to the current ReActTrace). When you click Re-run, the UI removes all elements with that runId from the DOM before the new response arrives. This is why the entire turn vanishes atomically, not just the text bubble.
Continue doesn't touch the DOM at all — it just sends the command and lets the stream append to the existing bubble.
Summary
Re-run and Continue are two sides of the same coin: Re-run is about correctness (throw away a bad answer and try again), while Continue is about completeness (keep a partial answer and finish it).
Both operate at the session level — they don't create new sessions, they don't change tools or models, and they don't affect other conversations. The only difference is whether the old response gets discarded (rerun) or preserved (continue).
Next time you're chatting with SolonCode and the agent's answer isn't quite right, reach for the icon that matches your intent:
- Wrong? → Re-run
- Incomplete? → Continue
Both are available in the Web UI, CLI, and IM channels — pick the one that fits your workflow.
SolonCode is an open-source coding agent built on Solon AI and Java. It supports CLI, Web, Desktop, and ACP interaction modes. Open source under Apache 2.0 / MIT.
Top comments (0)