Sessions & Observability
Group related API requests into sessions for easier analysis and conversation tracking.
Sessions & Observability
Sessions group related API requests together, making it easy to track multi-turn conversations and analyze user behavior patterns in the Observe dashboard.
Sessions are automatically created based on end-user identity, but you can override this with explicit session IDs for precise conversation grouping.
How Sessions Work
Bastio supports two methods for session management:
1. Auto-Sessions (Default)
Sessions are automatically created and managed based on the end-user identity:
- Grouping: Requests are grouped by
end_user_id(or device fingerprint if no user ID is provided) - Timeout: 30-minute inactivity window - after 30 minutes without requests, a new session is created
- Zero configuration: Works out of the box with no additional headers required
Request 1 (user_123, 10:00) → Session A
Request 2 (user_123, 10:05) → Session A (same session)
Request 3 (user_123, 10:50) → Session B (new session - 30+ min gap)2. Explicit Sessions
Override auto-sessions by providing your own session ID via the X-Session-ID header:
- Priority: Explicit session IDs take precedence over auto-sessions
- Custom grouping: Perfect for multi-turn conversations or workflow tracking
- Consistent: Same session ID always groups requests together, regardless of timing
Using Sessions
Explicit Session ID
Pass the X-Session-ID header to group requests into a specific session:
import openai
client = openai.OpenAI(
api_key="bastio_sk_your_key_here",
base_url="https://api.bastio.com/v1"
)
# Group all messages in this conversation under one session
session_id = "conversation_abc123"
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": "Hello, I need help with my order"}
],
extra_headers={
"X-Session-ID": session_id
}
)
# Follow-up message in the same session
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": "Hello, I need help with my order"},
{"role": "assistant", "content": response.choices[0].message.content},
{"role": "user", "content": "Can you check order #12345?"}
],
extra_headers={
"X-Session-ID": session_id # Same session
}
)import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'bastio_sk_your_key_here',
baseURL: 'https://api.bastio.com/v1'
});
const sessionId = 'conversation_abc123';
// First message
const response1 = await client.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'user', content: 'Hello, I need help with my order' }
]
}, {
headers: {
'X-Session-ID': sessionId
}
});
// Follow-up in same session
const response2 = await client.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'user', content: 'Hello, I need help with my order' },
{ role: 'assistant', content: response1.choices[0].message.content },
{ role: 'user', content: 'Can you check order #12345?' }
]
}, {
headers: {
'X-Session-ID': sessionId
}
});# First message in conversation
curl -X POST https://api.bastio.com/v1/chat/completions \
-H "Authorization: Bearer bastio_sk_your_key_here" \
-H "Content-Type: application/json" \
-H "X-Session-ID: conversation_abc123" \
-d '{
"model": "gpt-4",
"messages": [{"role": "user", "content": "Hello!"}]
}'
# Follow-up (same session ID)
curl -X POST https://api.bastio.com/v1/chat/completions \
-H "Authorization: Bearer bastio_sk_your_key_here" \
-H "Content-Type: application/json" \
-H "X-Session-ID: conversation_abc123" \
-d '{
"model": "gpt-4",
"messages": [
{"role": "user", "content": "Hello!"},
{"role": "assistant", "content": "Hi there!"},
{"role": "user", "content": "What is 2+2?"}
]
}'package main
import (
"context"
"net/http"
openai "github.com/sashabaranov/go-openai"
)
func main() {
config := openai.DefaultConfig("bastio_sk_your_key_here")
config.BaseURL = "https://api.bastio.com/v1"
// Add custom header for session ID
config.HTTPClient = &http.Client{
Transport: &sessionTransport{
sessionID: "conversation_abc123",
base: http.DefaultTransport,
},
}
client := openai.NewClientWithConfig(config)
resp, _ := client.CreateChatCompletion(
context.Background(),
openai.ChatCompletionRequest{
Model: openai.GPT4,
Messages: []openai.ChatCompletionMessage{
{Role: openai.ChatMessageRoleUser, Content: "Hello!"},
},
},
)
}
type sessionTransport struct {
sessionID string
base http.RoundTripper
}
func (t *sessionTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("X-Session-ID", t.sessionID)
return t.base.RoundTrip(req)
}End User Identification
For auto-sessions to work effectively, provide user identification:
# Option 1: Using the 'user' field (recommended)
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}],
user="user_12345" # Your internal user ID
)
# Option 2: Using X-End-User-ID header
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}],
extra_headers={
"X-End-User-ID": "user_12345"
}
)// Option 1: Using the 'user' field (recommended)
const response = await client.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello' }],
user: 'user_12345'
});
// Option 2: Using X-End-User-ID header
const response = await client.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello' }]
}, {
headers: {
'X-End-User-ID': 'user_12345'
}
});When no user ID is provided, Bastio generates a device fingerprint based on IP address and user agent. This allows session grouping even for anonymous users.
Session Headers Reference
| Header | Description | Example |
|---|---|---|
X-Session-ID | Explicit session identifier | conversation_abc123 |
X-End-User-ID | End user identifier for auto-sessions | user_12345 |
X-Environment | Environment tag for filtering | production, staging |
Viewing Sessions in Dashboard
Sessions are visible in Observe > Sessions in your Bastio dashboard:
Session List View
- Session ID: Unique identifier (auto-generated or your custom ID)
- End User: The user associated with the session
- Trace Count: Number of API requests in the session
- Duration: Time span from first to last request
- Status: Active or completed based on inactivity timeout
Session Detail View
Click on a session to see:
- Timeline: All traces in chronological order
- Metrics: Total tokens, cost, and latency
- Security Events: Any threats or blocks during the session
- Conversation Flow: Full request/response history
Best Practices
Use Meaningful Session IDs
# Good - descriptive and traceable
session_id = f"support_ticket_{ticket_id}"
session_id = f"checkout_{cart_id}"
session_id = f"chat_{user_id}_{timestamp}"
# Avoid - generic or non-unique
session_id = "session1"
session_id = str(uuid.uuid4()) # Hard to correlate laterSession Lifecycle Management
import time
class ConversationSession:
def __init__(self, user_id: str):
self.session_id = f"conv_{user_id}_{int(time.time())}"
self.messages = []
def add_message(self, role: str, content: str):
self.messages.append({"role": role, "content": content})
def send(self, client, model="gpt-4"):
return client.chat.completions.create(
model=model,
messages=self.messages,
extra_headers={"X-Session-ID": self.session_id}
)
# Usage
session = ConversationSession("user_123")
session.add_message("user", "Hello!")
response = session.send(client)
session.add_message("assistant", response.choices[0].message.content)
session.add_message("user", "Tell me more")
response = session.send(client) # Same session, full contextWhen to Use Explicit vs Auto Sessions
| Scenario | Recommendation |
|---|---|
| Multi-turn chat conversations | Explicit X-Session-ID |
| Single-request APIs | Auto-sessions (default) |
| User support tickets | Explicit with ticket ID |
| Anonymous/guest users | Auto-sessions with fingerprint |
| Workflow tracking | Explicit with workflow ID |
Troubleshooting
Next Steps
- API Reference - Complete API documentation
- Streaming Responses - Real-time response streaming
- Security Features - Threat detection and protection