Repository navigation
Description
🤖 written by Claude (start)
📋 Prerequisites
- I have searched the existing issues to avoid creating a duplicate
- By submitting this issue, you agree to follow our Code of Conduct
- I am using the latest version of the software (
mainat ab39f4d) - I can consistently reproduce this issue
🎯 Affected Service(s)
Controller Service (checkpoint service, A2A gateway), with the UI showing the symptoms.
🚦 Impact/Severity
High. A fork is unusable as a continuation of the source conversation: the agent has none of its memory, and the transcript reads out of order.
🐛 Bug Description
Forking landed in #2555 (feat: fork AgentInstances from checkpoints). CheckpointService.CreateCheckpoint followed by ForkAgentInstance produces an instance whose stored transcript is a copy of the source, but three things go wrong once you talk to it:
- The forked agent has no memory of the source conversation. Asked to repeat its previous answer, it replies "Need context to repeat answer." The task history was copied into PostgreSQL, but the runtime restored from the snapshot tag does not see it, so the model starts from a blank session.
- After a reload, the copied history sorts below the new turn. Live, the new turn renders under the copied messages. Re-read from the gateway, the order flips: the new question and answer come first, the copied source turn last. Copied task ids are minted as UUIDv5 (
newForkIDsingo/core/internal/database/client_postgres.go), so they no longer sort by time the way the original UUIDv7 ids did, which is what the transcript ordering leans on. - The fork comes back unnamed.
InsertForkedAgentInstancecopies labels and revision but notname, so every fork lands as "Untitled" until the caller renames it. Minor next to the two above, noted so one fix can cover all three.
🔄 Steps To Reproduce
Against a fresh kind cluster from ui/scripts/setup-cluster/setup-cluster.sh, with the bundled assistant agent:
- Start a conversation and ask: "In one sentence, what is a Kubernetes namespace?" Wait for the reply.
CreateCheckpointfor that instance, thenForkAgentInstancewith the returned checkpoint id. (The video does this from a "Fork chat" row action on a UI branch; the gRPC calls are the same two.)- Open the fork. The copied question and answer are there.
- Send: "Repeat your previous answer in exactly five words."
- Reload the fork's conversation.
🤔 Expected Behavior
- Step 4: the agent repeats the namespace answer, since the fork is meant to continue from the checkpoint.
- Step 5: the copied turn stays above the new one.
- The fork carries the source's name, or a derived one.
📱 Actual Behavior
- Step 4: "Need context to repeat answer."
- Step 5: the new turn is listed first, the copied source turn below it.
- The fork is unnamed.
Video of steps 1 to 5. Three chats, the oldest is forked from a "Fork chat" row action, the fork is asked to repeat its previous answer and cannot, then a reload shows the copied turn below the new one.
fork-context-loss.mp4
🖥️ Environment
- kagent
mainat ab39f4d, controller image built bysetup-cluster.sh(controller:dev) - kind on macOS, Substrate from the same script
- Agent:
kagent/assistanton harnesskagent/kagent, no tools
🤖 written by Claude (end)
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsBacklog
Activity
Rachael-Graham commentedon Sep 8, 2026
Independently reproduced this on
b8d53d39while checking documentation claims, and thesession-keying mechanism behind symptom 1 may be useful. It explains why the transcript is
physically present but invisible.
The session is keyed on the A2A context ID, and the context ID is always the
AgentInstance's own ID.
go/core/internal/a2agateway/gateway.go:463—req.Message.ContextID = instance.GetId()go/adk/pkg/a2a/executor.go:133—sessionID := reqCtx.ContextIDA fork mints a fresh instance ID and nothing re-keys the restored session.
Service.Fork(go/core/internal/service/checkpoint/service.go:266-310) generatesuuid.NewV7()at :294 and passes it toForkAgentInstance, then restores the Actor from thesnapshot tag.
grep -rn 'ContextID' go/core/internal/service/checkpoint/ go/core/internal/agentinstance/returns nothing, so no step carries the source's context ID onto the fork or re-keys the
restored session to the new instance ID.
Net effect: the restored
/data/sessions.dbholds the transcript under the sourceinstance's ID, while every request to the fork looks it up under the fork's ID. The
transcript is restored and unreachable, which matches "the runtime restored from the snapshot
tag does not see it" in the description.
A useful corollary for testing: a fork's
context_idcomes back equal to its own newinstance ID, which is a one-call way to confirm the behaviour without driving a conversation.
This also suggests why there is no session parameter on
invoke_agent_instance— theAgentInstance is the session — so a fix probably has to choose between carrying the source
context ID onto the fork and re-keying the restored session, rather than adding a session
selector.
fix: preserve conversation identity and history across forks (kagent-…
EItanya commentedon Sep 8, 2026
Did you retry this after the latest commit to main, it should fix this
Charlesthebird commentedon Sep 8, 2026
I verified this is fixed now - shown in the video here: #2747 (comment)
Rachael-Graham commentedon Sep 9, 2026
Edit: ^^ LIES i did not review this before claude apologized here 😂
Apologies for the noise — my comment above was written against
a06b8ccdand posted about25 minutes after
03fe32d3(#2754) had already landed and closed this. It describes theold behaviour.
Confirming the fix matches: #2754 separates routing authority from the public A2A context
and changes exactly the call site I cited,
instance.GetId()->instance.GetContextId()in
prepareSend,prepareReply, andListTasks. So the fork keeps the checkpoint's wirecontext while getting its own instance and history scope, which is the "carry the source
context ID onto the fork" branch of the two options.
One correction for anyone who finds this later: my closing corollary — that a fork's
context_idequals its own new instance ID — was a description of the bug and is no longertrue. Per
docs/architecture/persistence-checkpoints-and-forks.md, multiple forkauthorities now share one wire context, so that is exactly the invariant #2754 removed.