API Reference

Conversational Agents

Conversational agents enable real-time conversations with your AI agents using Server-Sent Events (SSE) for streaming responses.

Chat API

POST/v1/chat

Initiate or continue a conversation with an agent. Returns streaming responses via SSE.

Request Headers

bash
X-API-Key: YOUR_API_KEY
X-Backend-Token: YOUR_BACKEND_TOKEN (optional)

Request Body

json
{
  "agentId": "agent_abc123",
  "environmentId": "env_xyz789",
  "messages": [
    {"content": "Hello, I need help with my account"}
  ],
  "threadId": "thread_def456",  // optional - continue existing conversation
  "customerId": "customer_ghi789",  // optional - user identifier for scoped memory
  "customInstructions": "The user is a premium customer",  // optional - additional context
  "uploadedFiles": {  // optional - file attachments
    "file1": {
      "url": "https://example.com/file.pdf",
      "name": "document.pdf",
      "type": "application/pdf"
    }
  },
  "screenState": {  // optional - UI context for Screen Observer
    "route": "/dashboard",
    "routeName": "Dashboard",
    "timestamp": "2025-01-15T12:00:00Z",
    "entities": {
      "user": {"id": "123", "name": "John Doe"}
    }
  },
  "logChannelId": "log_channel_abc",  // optional - real-time logging channel
  "logToolScore": true  // optional - enable tool execution scoring
}

Parameters

ParameterTypeRequiredDescription
agentIdstringYesID of the agent to chat with
environmentIdstringYesEnvironment ID for agent execution
messagesarrayYesArray of message objects with content field
threadIdstringNoContinue existing conversation (returned in complete event)
customerIdstringNoUser identifier for customer-scoped memory and tracking
customInstructionsstringNoAdditional context or instructions for this conversation
uploadedFilesobjectNoFile attachments with url, name, and type properties
screenStateobjectNoUI context (route, entities, observedElements) for Screen Observer
logChannelIdstringNoChannel ID for real-time logging and monitoring
logToolScorebooleanNoEnable tool execution scoring for analytics

Response (SSE Stream)

The chat endpoint returns Server-Sent Events (SSE) for real-time streaming. All events follow a wrapper structure with type, data/event, and isComplete fields.

meebly-event

Wrapper for AI agent stream events including text generation, tool calls, and approvals

json
data: {
  "type": "meebly-event",
  "event": {
    "type": "text-delta",
    "payload": {
      "text": "chunk of text"
    }
  },
  "isComplete": false
}

Event Subtypes:

  • text-delta - Incremental text chunks from the agent (append to build full message)
  • tool-call - Agent is calling a tool (contains toolCallId, toolName, args)
  • tool-result - Tool execution completed (contains toolCallId, result)
  • tool-call-approval - Tool requires human approval - (contains runId for approve/decline endpoints)
  • start - Agent execution started
  • finish - Agent execution finished
complete

Stream completed successfully - Contains full response, threadId, executedTools, successUrl, and traceId

json
data: {
  "type": "complete",
  "data": {
    "text": "Final response text",
    "toolCalls": [],
    "overallSuccess": true
  },
  "isComplete": true
}
error

An error occurred during streaming - Stream ends immediately

json
data: {
  "type": "error",
  "error": "Error message describing what went wrong",
  "isComplete": true
}
When tools require approval, look for meebly-event with type: "tool-call-approval". Extract the runId to approve or decline the tool execution. See the Tool Approval (HITL) section for details.

Example Implementation

javascript
const response = await fetch('https://api.meebly.ai/v1/chat', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    agentId: 'agent_abc123',
    environmentId: 'env_xyz789',
    messages: [{content: 'Hello, I need help'}],
    screenState: {
      route: '/dashboard',
      routeName: 'Dashboard',
      timestamp: new Date().toISOString()
    }
  })
});

// Handle Server-Sent Events stream
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let fullResponse = '';

while (true) {
  const {value, done} = await reader.read();
  if (done) break;

  buffer += decoder.decode(value, {stream: true});
  const lines = buffer.split('\n\n');
  buffer = lines.pop() || '';

  for (const line of lines) {
    if (line.startsWith('data: ')) {
      try {
        const event = JSON.parse(line.slice(6));

        if (event.type === 'meebly-event') {
          // Handle AI stream events
          if (event.event.type === 'text-delta') {
            fullResponse += event.event.payload.text;
            console.log('Text chunk:', event.event.payload.text);
          } else if (event.event.type === 'tool-call') {
            console.log('Tool called:', event.event.payload.toolName);
          } else if (event.event.type === 'tool-call-approval') {
            console.log('Approval needed, runId:', event.event.payload.runId);
            // Don't close connection - send approval via separate API call
          }
        } else if (event.type === 'complete') {
          console.log('Complete response:', event.data.text);
          console.log('Thread ID:', event.data.threadId);
          console.log('Trace ID:', event.data.traceId);
          // Save threadId for continuing conversation
        } else if (event.type === 'error') {
          console.error('Error:', event.error);
        }
      } catch (e) {
        // Handle parsing errors for incomplete chunks
      }
    }
  }
}
Save the threadId from the complete event to maintain conversation context in subsequent requests.
Last updated: March 2026Report an issue