# Sessions and Chat

> Build multi-turn conversational experiences with chat sessions, message history, and WebSocket support.

Source: https://0.0.0.0:8080/docs/sessions-and-chat

PromptRails provides a session-based chat system for building multi-turn conversational experiences. Sessions maintain conversation context, message history, and metadata across multiple interactions with an agent.

## Chat Sessions Overview

A chat session represents an ongoing conversation between a user and an agent. It maintains:

- **Conversation history** -- All messages exchanged in the session
- **Agent binding** -- The session is linked to a specific agent
- **User binding** -- Optionally linked to an authenticated user
- **Metadata** -- Custom metadata for tracking and filtering
- **Title** -- Display name for the session

## Creating Sessions

**Python SDK**

```python
session = client.chat.create_session(
    agent_id="your-agent-id",
    title="Support Conversation",
    metadata={
        "channel": "web",
        "user_id": "external-user-123"
    }
)

session_id = session.id
print(f"Session created: {session_id}")
```

**JavaScript SDK**

```typescript
const session = await client.chat.createSession({
  agentId: 'your-agent-id',
  title: 'Support Conversation',
  metadata: {
    channel: 'web',
    user_id: 'external-user-123',
  },
})

const sessionId = session.id
```

## Sending Messages

Send a message to a chat session and receive the agent's response:

**Python SDK**

```python
response = client.chat.send_message(
    session_id,
    content="Hi, I need help with my account."
)

print(response.content)
```

**JavaScript SDK**

```typescript
const response = await client.chat.sendMessage(sessionId, {
  content: 'Hi, I need help with my account.',
})

console.log(response.content)
```

Each message sent to the chat API:

1. Loads the conversation history from the session
2. Constructs a prompt including the history and the new message
3. Executes the linked agent
4. Stores the user message and assistant response in the session
5. Returns the response

## Message History

Retrieve the full message history for a session:

```python
messages = client.chat.list_messages(session_id)

for message in messages.data:
    print(f"[{message.role}]: {message.content}")
```

## Multi-Turn Conversations

Sessions automatically manage conversation context. Each new message includes the full conversation history, enabling the agent to reference previous exchanges:

```python
# First message
client.chat.send_message(session_id, content="What is machine learning?")

# Follow-up (agent has context from the first message)
client.chat.send_message(session_id, content="Can you give me a specific example?")

# Another follow-up
client.chat.send_message(session_id, content="How does that compare to deep learning?")
```

The agent receives the full conversation history with each request, so it can maintain coherent, contextual responses throughout the conversation.

## Streaming Responses (SSE)

For real-time chat — token-by-token output, visible tool calls, and
intermediate reasoning — post a message to the streaming endpoint. It
returns a Server-Sent Events stream on the same HTTP connection.

```
POST /api/v1/chat/sessions/{session_id}/messages/stream
Content-Type: application/json
Accept: text/event-stream

{ "content": "Hello!" }
```

### Event schema

| Event        | Data                                | Meaning                                                       |
| ------------ | ----------------------------------- | ------------------------------------------------------------- |
| `execution`  | `{ execution_id, user_message_id }` | Emitted first. Correlate with executions / traces.            |
| `thinking`   | `{ content }`                       | Intermediate reasoning text between tool rounds.              |
| `tool_start` | `{ id, name }`                      | The agent is about to execute a tool call.                    |
| `tool_end`   | `{ id, name, summary }`             | A tool call finished. `summary` is a short display string.    |
| `content`    | `{ content }`                       | Delta of the final assistant response.                        |
| `done`       | `{ output, token_usage, time }`     | Terminal event. Carries the full output and token accounting. |
| `error`      | `{ message }`                       | Terminal error.                                               |

A typical stream emits `execution` first, zero or more `thinking` /
`tool_start` / `tool_end` / `content` frames, then exactly one `done` or
`error`.

### Consume it from an SDK

```typescript
// JavaScript / TypeScript — @promptrails/sdk >= 0.3.1
for await (const event of client.chat.sendMessageStream(session.id, {
  content: 'Hello!',
})) {
  if (event.type === 'content') process.stdout.write(event.content)
  if (event.type === 'done') break
}
```

```python
# Python — promptrails >= 0.3.0
from promptrails import ContentEvent, DoneEvent

for event in client.chat.send_message_stream(session_id, content="Hello!"):
    if isinstance(event, ContentEvent):
        print(event.content, end="", flush=True)
    elif isinstance(event, DoneEvent):
        break
```

```go
// Go — github.com/promptrails/go-sdk >= v0.3.1
stream, _ := client.Chat.SendMessageStream(ctx, sessionID, &promptrails.SendMessageParams{
    Content: "Hello!",
})
defer stream.Close()
for stream.Next() {
    if e, ok := stream.Event().(*promptrails.ContentEvent); ok {
        fmt.Print(e.Content)
    }
}
```

See each SDK's docs ([JavaScript](/docs/javascript-sdk),
[Python](/docs/python-sdk), [Go](/docs/go-sdk)) for the full
event-handling pattern, and [Executions](/docs/executions) for the
related `GET /executions/:id/stream` endpoint when you want to
subscribe to a run started outside of chat.

## Session Management

### List Sessions

```python
sessions = client.chat.list_sessions(page=1, limit=20)

for session in sessions.data:
    print(f"{session.title} - {session.created_at}")
```

### Get Session Details

```python
session = client.chat.get_session("session-id")
messages = client.chat.list_messages("session-id", page=1, limit=100)

print(f"Title: {session.title}")
print(f"Messages: {len(messages.data)}")
```

### Delete a Session

```python
client.chat.delete_session("session-id")
```

## Session Fields

| Field          | Type      | Description                 |
| -------------- | --------- | --------------------------- |
| `id`           | KSUID     | Unique session identifier   |
| `workspace_id` | KSUID     | Workspace scope             |
| `agent_id`     | KSUID     | The agent for this session  |
| `user_id`      | KSUID     | Optional authenticated user |
| `title`        | string    | Display title               |
| `metadata`     | JSON      | Custom metadata             |
| `created_at`   | timestamp | Session creation time       |
| `updated_at`   | timestamp | Last activity time          |

## Best Practices

- **Set meaningful titles** -- Helps users find and resume conversations
- **Use metadata** -- Track channel, user, experiment, or any context needed for analytics
- **Clean up old sessions** -- Delete sessions that are no longer needed to manage storage
- **Handle context limits** -- For very long conversations, be aware that conversation history may exceed the model's context window. Consider using summarization or memory for extended sessions.

## Related Topics

- [Agents](/docs/agents) -- The agents that power chat sessions
- [Memory](/docs/memory) -- Persistent memory across sessions
- [Executions](/docs/executions) -- Each chat message creates an execution
- [Tracing](/docs/tracing) -- Traces for individual chat messages
