Skip to content

Chat & Agents Guide

Learn how to use Satori's AI agents for advanced interactions with your documents and knowledge bases.

Overview

Satori provides two types of AI agents:

  1. Knowledge Base Agents: Query documents in your enclaves
  2. Clinical Research Agents: Access research databases and medical literature

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 '{
    "threadId": "thread-123",
    "runId": "run-456",
    "messages": [...],
    "tools": [...],
    "context": [...]
  }'

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

from typing import List, Dict, Any

def create_agent_request(
    query: str,
    thread_id: str,
    run_id: str,
    tools: List[Dict[str, Any]] = None,
    context: List[Dict[str, Any]] = None
) -> Dict[str, Any]:
    return {
        "threadId": thread_id,
        "runId": run_id,
        "messages": [
            {
                "id": "msg-1",
                "role": "user",
                "content": query
            }
        ],
        "tools": tools or [],
        "context": context or [],
        "state": {},
        "forwardedProps": {}
    }

# Use the agent
request = create_agent_request(
    query="What are the key findings in the research papers?",
    thread_id="thread-123",
    run_id="run-456"
)

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

def query_clinical_agent(query: str, session_id: str = None):
    """Query the clinical research agent."""
    url = f"{BASE_URL}/api/tenants/{tenant_id}/chat/agent"

    # Configure agent for clinical research
    request = {
        "threadId": session_id or f"clinical-{uuid.uuid4()}",
        "runId": f"run-{uuid.uuid4()}",
        "messages": [
            {
                "id": "msg-1",
                "role": "user",
                "content": query
            }
        ],
        "tools": [],  # Agent will use built-in clinical tools
        "context": [
            {
                "description": "Clinical research query",
                "value": "medical"
            }
        ],
        "state": {},
        "forwardedProps": {}
    }

    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