Chat & Agents Guide
Learn how to use Satori's AI agents for advanced interactions with your documents and knowledge bases.
Overview
Satori provides multiple ways to interact with your documents via AI. Choose the right approach based on your needs:
| Feature | Simple Chat | Agent Chat | Query |
|---|---|---|---|
| Endpoint | /enclaves/{id}/chat/ |
/chat/agent |
/enclaves/{id}/query |
| Response | Streaming text | Streaming JSON events | JSON |
| History | Session-based | Thread-based | None |
| Use case | Basic Q&A | Advanced tools/conversation | One-shot questions |
When to Use Each
- Simple Chat: Quick questions about documents with streaming responses
- Agent Chat: Complex multi-turn conversations with tool use capabilities
- Query: Programmatic one-shot questions returning structured JSON
Knowledge Base Chat
The simplest way to interact with your documents is through the enclave chat endpoint.
Basic Chat
curl -X POST "__API_HOST__/api/tenants/{tenant_id}/enclaves/{enclave_id}/chat/" \
-H "Authorization: Bearer <YOUR_JWT_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"query": "What are the key findings?",
"user_id": "user-123",
"session_id": "session-abc"
}'
Response: Streaming text via Server-Sent Events
Python Example
import requests
def chat_with_enclave(enclave_id, query, session_id=None, user_id=None):
url = f"{BASE_URL}/api/tenants/{tenant_id}/enclaves/{enclave_id}/chat/"
headers = {
"Authorization": f"Bearer {JWT_TOKEN}",
"Content-Type": "application/json"
}
data = {
"query": query,
"session_id": session_id or f"session-{uuid.uuid4()}",
"user_id": user_id
}
response = requests.post(url, headers=headers, json=data, stream=True)
full_response = ""
for line in response.iter_lines():
if line:
text = line.decode('utf-8')
if text.startswith('data: '):
content = text[6:]
if content == '[DONE]':
break
full_response += content
print(content, end='', flush=True)
return full_response
Session Management
Sessions maintain conversation history for context:
session_id = "my-session-123"
# First message
response1 = chat_with_enclave(enclave_id, "What is this document about?", session_id)
# Follow-up (uses previous context)
response2 = chat_with_enclave(enclave_id, "Tell me more about that", session_id)
Retrieving Session History
curl -X GET "__API_HOST__/api/tenants/{tenant_id}/enclaves/{enclave_id}/chat/{session_id}/messages" \
-H "Authorization: Bearer <YOUR_JWT_TOKEN>"
Response:
{
"messages": [
{
"role": "user",
"content": "What are the primary endpoints?",
"timestamp": "2025-01-15T10:30:00Z"
},
{
"role": "assistant",
"content": "The primary endpoints are...",
"timestamp": "2025-01-15T10:30:05Z",
"sources": [
{
"file_name": "protocol.pdf",
"chunk_id": "node_abc123",
"page": 12
}
]
}
],
"session_id": "my-session-123",
"message_count": 2
}
Advanced Agents
Satori supports advanced AI agents with tool calling capabilities.
Agent Chat Endpoint
curl -X POST "__API_HOST__/api/tenants/{tenant_id}/chat/agent" \
-H "Authorization: Bearer <YOUR_JWT_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "What are the key findings?"}],
"thread_id": "user-123",
"run_id": "session-456",
"forwarded_props": {
"enclave_id": "750e8400-e29b-41d4-a716-446655440000",
"file_id": "850e8400-e29b-41d4-a716-446655440000"
}
}'
Key Fields:
- messages: Conversation history (required)
- thread_id: User identifier for maintaining conversation state
- run_id: Session identifier for grouping related queries
- forwarded_props: Metadata passed to agent
enclave_id: Target enclave (required for document queries)file_id: Optional specific file to query
Agent Architecture
Agents use a message-based system:
- User Messages: Questions and instructions
- System Messages: Configuration and context
- Assistant Messages: Agent responses
- Tool Messages: Results from tool executions
- Developer Messages: System instructions
Example Agent Interaction
import requests
from typing import List, Dict, Any
def create_agent_request(
query: str,
thread_id: str,
run_id: str,
enclave_id: str = None,
file_id: str = None
) -> Dict[str, Any]:
request = {
"thread_id": thread_id,
"run_id": run_id,
"messages": [
{"role": "user", "content": query}
]
}
if enclave_id:
request["forwarded_props"] = {"enclave_id": enclave_id}
if file_id:
request["forwarded_props"]["file_id"] = file_id
return request
# Query documents in an enclave
request = create_agent_request(
query="What are the key findings in the research papers?",
thread_id="user-123",
run_id="session-456",
enclave_id="750e8400-e29b-41d4-a716-446655440000"
)
response = requests.post(
f"{BASE_URL}/api/tenants/{tenant_id}/chat/agent",
headers={"Authorization": f"Bearer {JWT_TOKEN}"},
json=request,
stream=True
)
Clinical Research Agents
Clinical research agents have access to medical literature and research databases.
Clinical Agent Features
- Access to medical research databases
- Clinical trial information
- Medical literature search
- Evidence-based answers
Using Clinical Agents
import uuid
def query_clinical_agent(query: str, session_id: str = None):
"""Query the clinical research agent (without specifying an enclave)."""
url = f"{BASE_URL}/api/tenants/{tenant_id}/chat/agent"
request = {
"thread_id": session_id or f"clinical-{uuid.uuid4()}",
"run_id": f"run-{uuid.uuid4()}",
"messages": [
{"role": "user", "content": query}
]
# No forwarded_props means agent uses clinical research capabilities
}
response = requests.post(
url,
headers={"Authorization": f"Bearer {JWT_TOKEN}"},
json=request,
stream=True
)
return response
Tool Calling
Agents can use tools to perform actions:
Available Tools
- Document Search: Search within enclave documents
- Web Search: Search the web for information
- Database Queries: Query structured data
- Custom Tools: Define your own tools
Tool Definition
tool = {
"name": "search_documents",
"description": "Search for information in uploaded documents",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query"
},
"limit": {
"type": "integer",
"description": "Maximum number of results"
}
},
"required": ["query"]
}
}
Agent with Tools
def agent_with_tools(query: str, enclave_id: str):
tools = [
{
"name": "search_enclave",
"description": f"Search documents in enclave {enclave_id}",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"},
"limit": {"type": "integer", "default": 5}
}
}
}
]
request = create_agent_request(
query=query,
thread_id=f"thread-{uuid.uuid4()}",
run_id=f"run-{uuid.uuid4()}",
tools=tools
)
response = requests.post(
f"{BASE_URL}/api/tenants/{tenant_id}/chat/agent",
headers={"Authorization": f"Bearer {JWT_TOKEN}"},
json=request,
stream=True
)
return response
Streaming Responses
All chat endpoints support streaming for real-time responses.
Handling Streams
def process_stream(response):
"""Process streaming response from agent."""
full_text = ""
for line in response.iter_lines():
if line:
text = line.decode('utf-8')
# Handle Server-Sent Events format
if text.startswith('data: '):
content = text[6:]
if content == '[DONE]':
break
full_text += content
yield content
return full_text
JavaScript Streaming
async function* streamAgentResponse(response: Response) {
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split("\n");
for (const line of lines) {
if (line.startsWith("data: ")) {
const text = line.slice(6);
if (text === "[DONE]") return;
yield text;
}
}
}
}
Best Practices
✅ DO:
- Use sessions for conversational context
- Provide clear, specific queries
- Handle streaming responses properly
- Review source citations
- Use appropriate agent types for your use case
❌ DON'T:
- Mix different conversation topics in the same session
- Ignore source citations
- Make too many concurrent agent requests
- Use agents for simple queries (use direct query endpoint instead)
Error Handling
Common Errors
404 Not Found
- Enclave doesn't exist
- Session not found
- Solution: Verify IDs and create resources first
500 Internal Server Error
- Agent execution error
- Tool execution failed
- Solution: Check query format and tool definitions
Error Handling Example
def safe_agent_query(query: str, enclave_id: str):
try:
response = agent_with_tools(query, enclave_id)
return process_stream(response)
except requests.HTTPError as e:
if e.response.status_code == 404:
raise ValueError("Enclave or session not found")
elif e.response.status_code == 500:
raise ValueError("Agent execution error")
else:
raise
Next Steps
- Querying Documents Guide - Direct document queries
- Text Processing Guide - Text processing tools
- Best Practices Guide - General usage best practices
- API Reference - Full API documentation