***
title: Sessions
description: The runtime universe for your agent.
-------------------------------------------------
The **Session** (`AgentSession`) is the container that holds your active conversation. It creates a sandbox for every user connection, managing state, resources, and the event loop.
**One Session = One User**
Every time a user connects via WebSocket (or phone), a new `AgentSession` instance is spawned. This ensures total isolation—variables set in one session never leak to another.
***
## Core Capabilities
The Session is your primary interface for controlling the agent's environment.
### 1. Graph Construction
You don't just add nodes; you build a graph. The session provides methods to define exactly how events flow.
```python
async def on_start(session: AgentSession):
# Add nodes to the sandbox
session.add_node(agent)
session.add_node(logger)
# Define custom flow: Logger -> Agent
session.add_edge(logger, agent)
await session.start()
```
### 2. Event Hooks
**Power Feature:** You can listen to events globally!
Use the `@session.on_event` decorator to inject logic without creating a dedicated node. This is perfect for simple side-effects like logging analytics or sending welcome messages.
```python
@session.on_event("system.user_joined")
async def welcome(session, event):
print(f"User {event.session_id} connected!")
@session.on_event("agent.speak")
async def track_speech(session, event):
metrics.increment("agent_speech_count")
```
### 3. Automatic Plumbing
The session automatically manages the entry and exit points of your graph.
* **Root Node**: Automatically created. Receives events from the client and forwards them to your nodes.
* **Sink Node**: Automatically created. Catches events from your nodes and sends them back to the client.
***
## SDK Reference
| Method | Description |
| :-------------------------------- | :--------------------------------------------------------------------- |
| `session.add_node(node)` | Registers a node in the graph. |
| `session.add_edge(parent, child)` | Connect two nodes explicitly. |
| `session.start()` | Locks the graph, validates no cycles exist, and starts the event loop. |
| `session.wait_until_complete()` | Keeps the process alive until the WebSocket disconnects. |
| `session.context` | A dict-like object for storing session-scoped state. |
**Cycle Detection**
When you call `start()`, the session runs a validation algorithm. If your graph contains a cycle (A → B → A), it will raise a `ValueError` immediately to prevent infinite loops.
***
## Example: Complete Setup
A full example showing graph building, hooks, and lifecycle management.
```python
from smallestai.atoms.agent.session import AgentSession
from smallestai.atoms.agent.server import AtomsApp
async def setup(session: AgentSession):
# 1. Initialize Nodes
agent = SalesAgent()
tracker = StatsTracker()
# 2. Build Graph
session.add_node(tracker)
session.add_node(agent)
session.add_edge(tracker, agent) # Events go Tracker -> Agent
# 3. Register Hooks
@session.on_event("system.control.interrupt")
async def on_interrupt(session, event):
print("User interrupted the agent!")
# 4. Launch
await session.start()
await session.wait_until_complete()
if __name__ == "__main__":
app = AtomsApp(setup_handler=setup)
app.run()
```