Skip to content

Session Control

This guide explains how to manage sessions (conversation threads) programmatically, including explicit closing, limits, and lifecycle management.

Overview

Sessions manage conversation context in Ag2Trust. Each unique thread_id creates a session that remains active for 15 minutes after the last activity. Sessions are used for conversation continuity, while billing is based on agent-hours.

Concept Description
Session An active conversation identified by thread_id
TTL 15 minutes from last activity
Purpose Maintain conversation context across messages
Close Explicitly end a session before TTL expires

Session Lifecycle

┌─────────────────────────────────────────────────────────────────────────┐
│                         SESSION LIFECYCLE                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  First Request    Activity    Activity    Close/TTL Expiry              │
│       │              │           │              │                       │
│       ▼              ▼           ▼              ▼                       │
│   ────●──────────────●───────────●──────────────●────────────────────   │
│       │                                         │                       │
│   started_at                               closed_at                    │
│                                                                         │
│   Session is "active" ──────────────────────────►                       │
│                                                                         │
│   Counted toward concurrent sessions                                    │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

State Transitions

Event Result
First request with thread_id New session created
Subsequent request within 15 min Session extended
Request after 15 min New session created
Explicit close Session ends immediately
No activity for 15 min Session expires (cleanup job)
Request to closed session Error returned

Closing Sessions

Close sessions explicitly to: - Free up concurrent session capacity immediately - Prevent further use of the thread - Clean up resources

Close Endpoint

POST /api/v1/sessions/{thread_id}/close
Authorization: Bearer YOUR_API_KEY

Response (200 OK):

{
  "thread_id": "thread_abc123",
  "closed_at": "2025-12-27T14:30:00Z",
  "duration_seconds": 542
}

Field Description
thread_id The closed thread identifier
closed_at When the session was closed
duration_seconds Total session duration

Response Codes

Code Description
200 Session closed successfully
404 Session not found (or belongs to different customer)
429 Rate limit exceeded (60 req/min)

Idempotency

Closing an already-closed session returns 200 with the original closed_at timestamp. This makes the endpoint safe to retry.

# First close
POST /api/v1/sessions/thread_abc123/close
 200 {"closed_at": "2025-12-27T14:30:00Z", ...}

# Retry (idempotent)
POST /api/v1/sessions/thread_abc123/close
 200 {"closed_at": "2025-12-27T14:30:00Z", ...}  # Same timestamp

Using Closed Threads

Attempting to send a message to a closed session returns an error:

POST /api/v1/agents/pool/ask
{
  "content": "Hello",
  "thread_id": "thread_abc123"  # Already closed
}

 410 Gone
{
  "error": "session_closed",
  "message": "Session 'thread_abc123' has been closed and cannot accept new messages",
  "closed_at": "2025-12-27T14:30:00Z",
  "duration_seconds": 542
}

To continue the conversation, use a new thread_id.

Session Limits

Each tier has a maximum concurrent session limit:

Tier Max Concurrent Sessions
Free 1
Pro 50
Enterprise Custom

Limit Enforcement

When you exceed your session limit, new sessions are rejected:

POST /api/v1/agents/pool/ask
{
  "content": "Hello",
  "thread_id": "new_thread"  # Would create 51st session
}

 429 Too Many Requests
{
  "error": "session_limit_exceeded",
  "message": "Session limit exceeded: 50/50",
  "current_sessions": 50,
  "session_limit": 50
}

Solutions: 1. Close existing sessions explicitly 2. Wait for sessions to expire (15 min TTL) 3. Upgrade to a higher tier

Checking Active Sessions

Currently active session count is not exposed via API. Monitor your usage through: - Dashboard billing page - Usage analytics endpoints

Session Cleanup

A background job runs every 5 minutes to close abandoned sessions:

  • Sets closed_at = last_activity_at + 15 minutes
  • Preserves accurate session end time for billing
  • Keeps data clean for analytics

Session Cleanup

Sessions are automatically cleaned up after TTL expiry. Explicit closing is optional but recommended when conversations are complete.

Best Practices

1. Close Sessions When Done

If you know a conversation is complete, close the session:

# After final message exchange
response = client.agents.ask(
    content="Goodbye!",
    thread_id="thread_abc123"
)

# Explicitly close
client.sessions.close("thread_abc123")

2. Use Thread IDs Strategically

# Per-user sessions (long-running)
thread_id = f"user_{user_id}"

# Per-conversation sessions (close after each)
thread_id = f"conv_{uuid4()}"

3. Handle Closed Session Errors

try:
    response = client.agents.ask(content="Hello", thread_id=thread_id)
except SessionClosedError as e:
    # Start new conversation
    new_thread_id = generate_new_thread_id()
    response = client.agents.ask(content="Hello", thread_id=new_thread_id)

4. Monitor Session Capacity

For Pro tier with 50 sessions:

# Rough estimation
active_conversations = count_active_conversations()
if active_conversations > 40:  # 80% threshold
    alert_capacity_warning()

5. Don't Close Prematurely

If the conversation might continue within 15 minutes, let TTL handle expiry automatically.

Example: Chat Application

import uuid
from datetime import datetime, timedelta

class ChatSession:
    def __init__(self, client, user_id):
        self.client = client
        self.user_id = user_id
        self.thread_id = f"chat_{user_id}_{uuid.uuid4().hex[:8]}"
        self.last_activity = datetime.utcnow()

    def send_message(self, content):
        response = self.client.agents.ask(
            content=content,
            thread_id=self.thread_id
        )
        self.last_activity = datetime.utcnow()
        return response

    def close(self):
        """Explicitly close when user ends chat."""
        result = self.client.sessions.close(self.thread_id)
        return result

    def is_expired(self):
        """Check if session has expired (15 min TTL)."""
        return datetime.utcnow() - self.last_activity > timedelta(minutes=15)


# Usage
session = ChatSession(client, user_id="user_123")

# Chat interaction
response = session.send_message("Hello!")
response = session.send_message("How can you help?")

# User clicks "End Chat"
session.close()  # Free up session capacity immediately

API Reference

Close Session

Method Endpoint Description
POST /api/v1/sessions/{thread_id}/close Close a session

Headers:

Authorization: Bearer YOUR_API_KEY

Response Schema:

{
  "thread_id": "string",
  "closed_at": "datetime",
  "duration_seconds": "integer",
  "billable": "boolean"
}

Rate Limit: 60 requests per minute per API key

Next Steps