Skip to main content

Chat API

The Chat API allows you to have real-time streaming conversations with an agent's configured LLM. All messages are proxied through the agent controller, which enforces policies and logs sessions.

Send a chat message

POST /api/chat

Auth: Required. The user must have a capability grant (or be an admin) to interact with the target agent.

Returns a text/event-stream (Server-Sent Events) response.

Request body

{
"agentDid": "did:vaultys:z6Mkf9x3TQ...",
"messages": [
{
"role": "user",
"content": "Summarise the key trends in Q1 2026 for the EMEA region."
}
],
"sessionId": "sess_01HZ..."
}
FieldTypeRequiredDescription
agentDidstringYesThe agent to chat with
messagesarrayYesConversation history (OpenAI-compatible format)
sessionIdstringNoResume an existing session. Omit to create a new one.

Message format

interface ChatMessageEntry {
role: "system" | "user" | "assistant" | "tool";
content: string | ContentBlock[];
name?: string; // For tool messages
tool_calls?: any[]; // For assistant messages with tool use
}

Response: Server-Sent Events stream

The response is a streaming text/event-stream. Each event contains a chunk of the LLM's response:

data: {"chunk": "The key trends"}

data: {"chunk": " in Q1 2026 for"}

data: {"chunk": " the EMEA region are:"}

data: {"chunk": "\n\n1. **Rising adoption"}

data: [DONE]

The stream ends with the literal data: [DONE] event.

Consuming the stream (JavaScript)

const response = await fetch("/api/chat", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
agentDid: "did:vaultys:z6Mkf9x3TQ...",
messages: [{ role: "user", content: "Hello!" }],
}),
});

const reader = response.body!.getReader();
const decoder = new TextDecoder();
let full = "";

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

const text = decoder.decode(value);
for (const line of text.split("\n")) {
if (line.startsWith("data: ")) {
const payload = line.slice(6);
if (payload === "[DONE]") break;
const { chunk } = JSON.parse(payload);
full += chunk;
// Update your UI with `chunk`
}
}
}

Consuming the stream (Python)

import requests, json

res = requests.post(
"https://vaultysclaw.acme.com/api/chat",
json={
"agentDid": "did:vaultys:z6Mkf9x3TQ...",
"messages": [{"role": "user", "content": "Hello!"}],
},
cookies={"next-auth.session-token": "..."},
stream=True,
)

for line in res.iter_lines():
if line.startswith(b"data: "):
payload = line[6:]
if payload == b"[DONE]":
break
chunk = json.loads(payload)["chunk"]
print(chunk, end="", flush=True)

Chat sessions

Chat history is stored per session. Sessions are created automatically when you omit sessionId.

List sessions for an agent

GET /api/chat/sessions?agentDid=did:vaultys:z6Mkf9...
{
"sessions": [
{
"id": "sess_01HZ...",
"title": "Q1 EMEA analysis",
"createdAt": "2026-05-15T09:00:00Z",
"updatedAt": "2026-05-15T09:12:00Z",
"messageCount": 6
}
]
}

Get session messages

GET /api/chat/sessions/:sessionId/messages
{
"messages": [
{ "role": "user", "content": "Summarise Q1 trends...", "createdAt": "..." },
{ "role": "assistant", "content": "The key trends...", "createdAt": "..." }
]
}