Session Basics#
The first questions in an agent Workflow are where state lives, where tools run, and how history is tracked. Session keeps those concerns in one object: chunk_table stores context, the Backend target decides where tools execute, and lineage fields record where the Session came from.
Coverage#
Topic |
Result |
|---|---|
Create agent/user Sessions |
System prompts and user messages become different chunk types. |
Read the chunk table |
|
Use fork and detach |
Both copy the transcript, but they create different graph relationships. |
Set the Backend target |
|
Understand handle lifecycle |
After the context manager exits, the current handle is closed. |
Step 1: Create Agent and User Sessions#
Start with two Sessions: one for the agent system prompt and one for the user input.
from rath.session import Session
agent = Session.from_agent_prompt("You are a concise assistant.")
user = Session.from_user_message("List files in the sandbox.")
print(agent.chunk_table.rows[-1].kind)
print(user.chunk_table.rows[-1].kind)
print(user.chunk_table.rows[-1].payload["content"])
Key lines:
Code |
Purpose |
|---|---|
|
Creates a Session containing a |
|
Creates a Session containing a |
|
Reads the latest chunk. |
Expected output:
system
user
List files in the sandbox.
At this point neither Session has a sandbox target. They only store the transcript.
Step 2: Understand the Chunk Table#
Session does not store context as one large string. It stores a time-ordered table instead, so assistant tool calls and tool results keep their structure.
for index, row in enumerate(user.chunk_table.rows):
print(index, row.kind, row.payload)
For the newly created user Session, the output has one row:
0 user {'content': 'List files in the sandbox.'}
Later, run_session_loop(...) appends assistant rows and tool result rows to this table. Each agent action becomes part of the Session history.
Step 3: Preserve Origin with Fork#
fork() is useful when you want to branch from the current state. It copies chunk rows and records the source Session as the parent.
forked = user.fork()
print(forked.chunk_table.rows == user.chunk_table.rows)
print(forked.parent_session_ids == (user.id,))
print(forked.lineage_operator)
Expected output:
True
True
Session.fork
Key points:
Field |
Meaning after fork |
|---|---|
|
Same content as the source Session. |
|
Points to the source Session. |
|
The current implementation records |
Fork is commonly used for branching exploration. For example, the same user request can be sent to two Workflows, and the graph later shows that both came from the same input.
Step 4: Create a New Starting Point with Detach#
detach() also copies the transcript, but it makes the new Session a new lineage root.
detached = forked.detach()
print(detached.chunk_table.rows == forked.chunk_table.rows)
print(detached.parent_session_ids)
print(detached.lineage_operator)
Expected output:
True
()
Session.detach
Detach is useful when an intermediate state should become the entry point for a new task. The content is preserved, and graph parents are cleared.
Step 5: Set the Local Backend Target#
to("local") sets which Backend this Session will use later. It returns the same Session, so it can be chained.
user.to("local")
print(user.sandbox_backend)
print(user.sandbox is None)
Expected output:
local
True
to("local") sets the Backend target. It does not open a sandbox handle immediately. The handle opens on demand through require_sandbox() or with session:.
Step 6: Open and Close the Sandbox Handle#
Use the context manager to open the sandbox when entering the block and close the current handle when leaving it.
with user:
sandbox = user.require_sandbox()
print(sandbox.backend.name)
print(user.sandbox is sandbox)
print(sandbox.closed)
print(user.sandbox is None)
print(sandbox.closed)
Expected output:
local
True
False
True
True
Key lines:
Code |
Purpose |
|---|---|
|
Calls |
|
Returns the current handle; if no handle exists but a Backend target is set, it opens one lazily. |
|
Marked as closed after the local Backend closes it. |
Troubleshooting#
Symptom |
Cause |
Check |
|---|---|---|
|
The Session has no Backend target and no handle. |
Call |
|
The Session is bound to a closed handle. |
Call |
Local workspace disappeared |
|
Do not use important, non-reproducible directories as a local sandbox workspace. |
Branches unexpectedly share files |
The current design shares an already-open sandbox handle. |
Retarget branches with |
Exercises#
Change
user.to("local")touser.to("local", spec=".")and observe which directory the sandbox handle points to.Call
fork()twice on the sameuser, then print each fork’sparent_session_ids.Write a file inside
with user:, exit the context, and observe what happens to the workspace after the local Backend closes.
Summary#
Sessioncarries the transcript, Backend target, and lineage.chunk_tableis a structured context table; later tool calls and tool results are appended to it.fork()copies content and preserves the parent;detach()copies content and creates a new graph root; both share an open sandbox handle when one exists.to(...)sets the execution location; the sandbox handle opens on demand.run_session_loop(...)shares the input user Session’s sandbox with the output Session. Later tutorials cover that behavior.