Repository navigation
Feedback - Examples section #609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| --- | ||
| title: Agent Substrate | ||
| description: Watch an agent's Actor suspend between turns and pin its state with a checkpoint. | ||
| description: Watch an agent's Actor suspend between turns, pin its state with a checkpoint, and fork that checkpoint into a second Session. | ||
| weight: 10 | ||
| author: kagent.dev | ||
| --- | ||
|
|
@@ -96,7 +96,7 @@ The Session stays `READY` throughout all steps. A suspended agent remains listed | |
|
|
||
| Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent Substrate is free to collect that snapshot once a newer one supersedes it. A {{< gloss "Checkpoint" >}}checkpoint{{< /gloss >}} pins a snapshot so that you can come back to it. | ||
|
|
||
| 1. Create a checkpoint. The checkpoint records the snapshot that it pinned and how far the {{< gloss "Transcript" >}}transcript{{< /gloss >}} had advanced. `expectedHeadTaskId` names the terminal task to pin, so the call fails rather than pinning the wrong turn when the conversation has advanced. The `requestId` field is a required idempotency key of 1 to 128 characters, so reusing it returns the same checkpoint rather than creating a second one. | ||
| 1. Create a checkpoint. A checkpoint keeps the conversation through the turn that you name. `expectedHeadTaskId` names the finished turn to pin. When the conversation has advanced past that task, the call fails rather than pinning the wrong turn. `requestId` is a required idempotency key of 1 to 128 characters. Repeating a `requestId` returns the checkpoint that the earlier call created rather than pinning a second one. | ||
| ```bash | ||
| grpcurl -plaintext \ | ||
| -d '{"sessionId":"'"$SESSION_ID"'","expectedHeadTaskId":"'"$TASK_ID"'","requestId":"'"$(uuidgen)"'"}' \ | ||
|
|
@@ -119,7 +119,11 @@ Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent | |
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > A checkpoint captures a turn boundary, so the named task must be terminal and its snapshot must be written. A newer turn that has already started fails the call with `conversation advanced beyond the expected task`, and a snapshot that is still being written fails it with `snapshot for the expected task is not ready`. The second is safe to retry with the same values; the first needs a newer task ID. | ||
| > A checkpoint captures a turn boundary. The call succeeds only once every turn on the Session has reached a final state, meaning `TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, or `TASK_STATE_REJECTED`. | ||
| > | ||
| > * When a turn on the Session is still running, the call fails with `checkpoint requires all tasks to be terminal`. Wait for the turn to finish, then send the request again. | ||
| > * When a newer turn has already started, the call fails with `conversation advanced beyond the expected task`. Name the current task ID and send the request again. | ||
| > * When Agent Substrate is still writing the snapshot, the call fails with `snapshot for the expected task is not ready`. Send the same request again. | ||
|
|
||
| 2. Save the checkpoint's `id` so that you can delete it during cleanup. | ||
| ```bash | ||
|
|
@@ -135,15 +139,64 @@ Each suspend writes a {{< gloss "Snapshot" >}}snapshot{{< /gloss >}}, and Agent | |
|
|
||
| Underneath, the checkpoint attaches a {{< gloss "Tag" >}}Tag{{< /gloss >}} named `checkpoint-<checkpoint-id>` to the snapshot, and Agent Substrate does not collect a snapshot while a tag names it. You can see the tag by running `kubectl ate get tags --atespace kagent`. | ||
|
|
||
| ## Forking is temporarily unavailable | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocking: kagent#3165, which moves suspension to DATA snapshots and makes forking possible, merged to Removing this section also breaks the
Can we either keep these notes until the next kagent release, or update all of those places in this PR? If forking is in scope now, a fork step could replace this section. The same applies to the two removals in |
||
| ## Fork the checkpoint into a second Session | ||
|
|
||
| Forking creates a second Session from a checkpoint only when the pinned snapshot contains durable data without process memory. In the current kagent release, suspended Actors use `Full` snapshots so that their process memory survives suspend and resume. A `ForkSession` request for these checkpoints is rejected with `FAILED_PRECONDITION`, because a restored Actor would resume processes that still hold the source Session's identifiers. | ||
| A fork starts a new Session from a checkpoint. The new Session replays the conversation through the pinned turn and then continues on its own. You can therefore take a conversation in a second direction without disturbing the first. | ||
|
|
||
| Checkpoint creation is still useful without forking. A checkpoint pins the snapshot for retention, gives the turn boundary a stable record, and keeps the checkpoint visible in the API while the original Session continues. | ||
| 1. Fork the checkpoint. `requestId` is an idempotency key of 1 to 128 characters. Repeating a `requestId` returns the Session that the earlier call created rather than forking a second one. | ||
| ```bash | ||
| grpcurl -plaintext \ | ||
| -d '{"checkpointId":"'"$CHECKPOINT_ID"'","requestId":"'"$(uuidgen)"'"}' \ | ||
| localhost:8083 kagent.api.v1alpha1.CheckpointService/ForkSession | ||
| ``` | ||
|
|
||
| The fork takes the checkpoint's name, and runs the revision that the source Session was created on. Example output: | ||
| ```json | ||
| { | ||
| "session": { | ||
| "id": "0198c3f1-2d7a-7c48-9e03-4b1f6a8d2c95", | ||
| "creator": "admin@kagent.dev", | ||
| "agent": { | ||
| "namespace": "kagent", | ||
| "name": "my-first-agent" | ||
| }, | ||
| "state": "RUNTIME_STATE_READY", | ||
| "createdAt": "2026-08-31T15:19:02Z", | ||
| "name": "my-first-agent turn 4", | ||
| "contextId": "0198c3f1-2d7a-7c48-9e03-4b1f6a8d2c95" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| > [!NOTE] | ||
| > The fork receives its own conversation ID and its own task IDs, so `contextId` is the fork's own ID rather than the source Session's. The replayed turns keep the timestamps they had on the source Session. Agent Substrate measures the fork's idle lifetime from its creation time instead, so a fork of an old conversation is not collected as idle. | ||
|
|
||
| 2. Save the forked Session's ID. | ||
| ```bash | ||
| export FORK_SESSION_ID=<your-forked-session-id> | ||
| ``` | ||
|
|
||
| 3. Ask the fork about the replayed conversation. The agent answers from the turns that the checkpoint pinned, which is what makes the fork a continuation rather than a new conversation. | ||
| ```bash | ||
| kagent agent invoke --session $FORK_SESSION_ID --task "What did I ask you first?" | ||
| ``` | ||
|
|
||
| 4. Confirm that the two Sessions are now independent. Send the source Session a message, and note that the fork's transcript does not change. | ||
| ```bash | ||
| kagent agent invoke --session $SESSION_ID --task "Remember the number 7." | ||
| kagent agent invoke --session $FORK_SESSION_ID --task "What number did I ask you to remember?" | ||
| ``` | ||
|
|
||
| The fork does not know the number, because the two conversations diverged at the checkpoint. | ||
|
|
||
| ## Clean up | ||
|
|
||
| 1. Delete the checkpoint. Deleting removes the Tag and releases the pin, and Agent Substrate can collect the snapshot whenever no tag names it. | ||
| 1. Delete the forked Session. | ||
| ```bash | ||
| kagent agent session delete $FORK_SESSION_ID | ||
| ``` | ||
|
|
||
| 2. Delete the checkpoint. Deleting removes the Tag and releases the pin, and Agent Substrate can collect the snapshot whenever no tag names it. | ||
| ```bash | ||
| grpcurl -plaintext \ | ||
| -d '{"checkpointId":"'"$CHECKPOINT_ID"'"}' \ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, optional: as a bare paragraph between the table and the
contextIdparagraph, this sentence reads as part of the addressing rules. It was easier to scan as the> [!NOTE]it replaced. Feel free to ignore.