Complete guide to using sessions for stateful, multi-call interactions.
→ Sessions REST API — GET /sessions, keepalive, and DELETE /sessions/{id}
Quick Start
CLI
1# Start a new session2infsh app run my-app --session new --input '{"key": "value"}'3# Output includes session_id: sess_abc12345# Continue the session6infsh app run my-app --session sess_abc123 --input '{"key": "value2"}'78# End the session9infsh session end sess_abc123Python SDK
1from inferencesh import Inference23client = Inference(api_key="...")45# Start session6result = client.run({7 "app": "my-app@abc123",8 "input": {"action": "init"},9 "session": "new"10})11session_id = result["session_id"]1213# Continue session14result = client.run({15 "app": "my-app@abc123",16 "input": {"action": "process"},17 "session": session_id18})1920# End session21client.sessions.end(session_id)JavaScript SDK
1import { Inference } from '@anthropic/inference-sdk';23const client = new Inference({ apiKey: '...' });45// Start session6const result = await client.run({7 app: 'my-app@abc123',8 input: { action: 'init' },9 session: 'new'10});11const sessionId = result.session_id;1213// Continue session14await client.run({15 app: 'my-app@abc123',16 input: { action: 'process' },17 session: sessionId18});1920// End session21await client.sessions.end(sessionId);Session Parameters
The session and session_timeout parameters control session behavior:
session
| Value | Behavior |
|---|---|
"new" | Create a new session; returns session_id in response |
"sess_xxx" | Use existing session; must match app and version |
| omitted | Regular stateless call |
session_timeout
Custom idle timeout in seconds. Only valid when session: "new".
| Constraint | Value |
|---|---|
| Minimum | 1 second |
| Maximum | 3600 seconds (1 hour) |
| Default | 60 seconds |
1# Python: 5-minute session timeout2result = client.run({3 "app": "my-app",4 "input": {...},5 "session": "new",6 "session_timeout": 3007})1// JavaScript: 5-minute session timeout2const result = await client.run({3 app: 'my-app',4 input: {...},5 session: 'new',6 session_timeout: 3007});1# CLI: 5-minute session timeout2infsh app run my-app --session new --session-timeout 300 --input '{...}'Session Management
Get Session Info
1# Python2info = client.sessions.get(session_id)3print(info.status) # "active", "ended", or "expired"4print(info.expires_at) # When session will expire5print(info.call_count) # Number of calls made1// JavaScript2const info = await client.sessions.get(sessionId);3console.log(info.status); // "active", "ended", or "expired"4console.log(info.expiresAt); // When session will expire5console.log(info.callCount); // Number of calls madeList Sessions
1# Python2sessions = client.sessions.list()3for s in sessions:4 print(f"{s.id}: {s.status}")1// JavaScript2const sessions = await client.sessions.list();3sessions.forEach(s => console.log(`${s.id}: ${s.status}`));Keep Session Alive
Extend the expiration time without making a task call:
1# Python2info = client.sessions.keepalive(session_id)3print(info.expires_at) # Updated expiration1// JavaScript2const info = await client.sessions.keepalive(sessionId);3console.log(info.expiresAt); // Updated expirationEnd Session
Release the worker immediately:
1# Python2client.sessions.end(session_id)1// JavaScript2await client.sessions.end(sessionId);State Guarantees
What Persists
- In-memory state — Python objects, loaded models, variables
- File system changes — Files written to local storage
- Database connections — Open connections remain open
What Doesn't Persist
- Cross-session state — Each session starts fresh
- After expiration — State is lost when session ends
- Across restarts — Worker restarts clear all state
Example: Stateful App
1class App(BaseApp):2 def __init__(self):3 self.state = {} # Persists within session45 async def set_value(self, input: SetInput) -> SetOutput:6 self.state[input.key] = input.value7 return SetOutput(success=True)89 async def get_value(self, input: GetInput) -> GetOutput:10 value = self.state.get(input.key)11 return GetOutput(value=value, found=value is not None)Timeouts and Expiration
Default Timeout
Sessions expire after 60 seconds of idle time (no calls) by default.
Custom Timeout
Specify session_timeout when creating a session to customize the idle timeout:
1# Create session with 10-minute idle timeout2result = client.run({3 "app": "my-app",4 "input": {...},5 "session": "new",6 "session_timeout": 600 # 10 minutes7})| Timeout Range | Description |
|---|---|
| 1-59 seconds | Short-lived sessions for quick interactions |
| 60 seconds | Default timeout |
| 60-300 seconds | Standard interactive sessions |
| 300-3600 seconds | Long-running workflows, background processing |
Sliding Window
Each call resets the expiration timer to the session's configured timeout:
1# With default 60-second timeout:2Call 1 (t=0) → Expires at t=60s3Call 2 (t=30s) → Expires at t=90s4Call 3 (t=80s) → Expires at t=140s56# With custom 5-minute (300s) timeout:7Call 1 (t=0) → Expires at t=5min8Call 2 (t=2min) → Expires at t=7min9Call 3 (t=6min) → Expires at t=11minMaximum Timeout
The maximum allowed session timeout is 1 hour (3600 seconds).
Keepalive
Use keepalive to extend the session without making a task call. This resets the timer using the session's configured timeout:
1# Extend session periodically2while work_in_progress:3 client.sessions.keepalive(session_id)4 time.sleep(session_timeout * 0.8) # Keep alive at 80% of timeoutError Handling
Session Errors
| Error Code | HTTP Status | Description |
|---|---|---|
SESSION_NOT_FOUND | 404 | Session ID doesn't exist |
SESSION_EXPIRED | 410 | Session timed out |
SESSION_ENDED | 410 | Session was explicitly ended |
WORKER_LEASED | 409 | Worker assigned to different session |
APP_MISMATCH | 400 | Session belongs to different app |
VERSION_MISMATCH | 400 | Session belongs to different version |
Task failures (session scheduling)
Session tasks route to the worker leased for the session. If that worker is busy running another call, your new task waits in the queue. If the worker does not become idle within about 30 seconds, the task fails with status Failed and error session worker busy too long. Retry when the prior call finishes, or serialize session calls so only one runs at a time.
| Error | Cause | What to do |
|---|---|---|
session worker busy too long | Prior call on the session worker still running after ~30s | Wait and retry, or serialize session calls |
session worker offline | Leased worker disconnected or was removed | Create a new session ("session": "new") |
session expired or not found | Session ID invalid or idle timeout elapsed | Create a new session ("session": "new") |
Python Error Handling
1from inferencesh import (2 SessionNotFoundError,3 SessionExpiredError,4 SessionEndedError,5)67try:8 result = client.run({9 "app": "my-app",10 "input": {...},11 "session": session_id12 })13except SessionNotFoundError:14 # Session doesn't exist — create new one15 result = client.run({...}, session="new")16except SessionExpiredError:17 # Session timed out — create new one18 result = client.run({...}, session="new")19except SessionEndedError:20 # Session was ended — create new one21 result = client.run({...}, session="new")JavaScript Error Handling
1import {2 SessionNotFoundError,3 SessionExpiredError,4 SessionEndedError5} from '@anthropic/inference-sdk';67try {8 const result = await client.run({9 app: 'my-app',10 input: {...},11 session: sessionId12 });13} catch (error) {14 if (error instanceof SessionNotFoundError ||15 error instanceof SessionExpiredError ||16 error instanceof SessionEndedError) {17 // Create new session18 const result = await client.run({...}, { session: 'new' });19 }20 throw error;21}Best Practices
Always End Sessions
Release workers when done:
1try:2 # Use session3 result = client.run({..., "session": session_id})4finally:5 client.sessions.end(session_id)Handle Expiration Gracefully
Sessions can expire unexpectedly. Always handle SESSION_EXPIRED:
1def call_with_retry(client, params, session_id):2 try:3 return client.run({**params, "session": session_id})4 except SessionExpiredError:5 # Recreate session and retry6 result = client.run({**params, "session": "new"})7 return result, result["session_id"]Use Context Managers (Python)
1with client.session("my-app@abc123") as session:2 session.call({"action": "init"})3 session.call({"action": "process"})4 # Session automatically ended on exitPin Versions
Sessions are bound to a specific app version:
1# Good: Version pinned2client.run({"app": "my-app@abc123", "session": session_id, ...})34# Bad: Version might change5client.run({"app": "my-app", "session": session_id, ...})Next
- Sessions Concept — Overview and use cases
- Stateful Sessions Examples — Practical patterns
- Multi-Function Apps — Combine with multiple entry points