Tema
Chat completions
POST /v1/chat/completions
Envia uma mensagem da pessoa para o agente e devolve a resposta. O formato lembra o de chat completions de outras APIs, com diferenças importantes: o histórico fica na Cavori, e cada chamada envia só a mensagem nova.
Exige o cabeçalho Idempotency-Key, de 8 a 200 caracteres.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
model | string | sim | Agente da conversa, agent:<id>. Diferente do agente com que a conversa foi aberta, responde 409 conflict. |
conversation_id | string | sim | Id devolvido por POST /v1/conversations. |
messages | array | sim | Exatamente uma mensagem, { "role": "user", "content": "..." }, com 1 a 32.000 caracteres. |
stream | boolean | não | true para receber a resposta aos poucos. Padrão: false. |
O que não é aceito
- mais de uma mensagem, ou papel diferente de
user; - prompt de sistema, histórico enviado de fora, ferramentas e anexos;
- qualquer campo que não esteja na tabela (
temperature,max_tokensetc.).
O contexto da conversa é o histórico guardado na Cavori. Esses casos respondem 400 invalid_request.
Resposta em JSON
bash
curl https://api.cavori.com.br/v1/chat/completions \
-H "Authorization: Bearer $CAVORI_API_KEY" \
-H "Idempotency-Key: usuario-123-turno-1" \
-H "Content-Type: application/json" \
-d '{
"model": "agent:cm9x0example0001",
"conversation_id": "cm9x0conversa0001",
"messages": [{ "role": "user", "content": "Olá, vocês abrem no sábado?" }]
}'Exemplo de resposta:
json
{
"id": "cm9x0execucao0001",
"object": "chat.completion",
"conversation_id": "cm9x0conversa0001",
"message_id": "cm9x0mensagem0002",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "Abrimos sim, das 9h às 13h." },
"finish_reason": "stop"
}
]
}| Campo | Descrição |
|---|---|
id | Id da execução. Use em GET /v1/requests/:id. |
message_id | Id da mensagem do agente, o mesmo de GET /v1/conversations/:id/messages. |
choices[0].message.content | Texto da resposta. |
choices[0].finish_reason | stop, ou content_filter quando uma proteção do agente interrompeu a resposta. |
Resposta em streaming
Com "stream": true, a resposta é text/event-stream (SSE, UTF-8). Cada evento é uma linha data: com um JSON, seguida de uma linha em branco. O texto vem em choices[0].delta.content, sempre com finish_reason: null:
text
data: {"id":"cm9x0execucao0001","conversation_id":"cm9x0conversa0001","message_id":"cm9x0mensagem0002","choices":[{"index":0,"delta":{"content":"Abrimos "},"finish_reason":null}]}
data: {"id":"cm9x0execucao0001","conversation_id":"cm9x0conversa0001","message_id":"cm9x0mensagem0002","choices":[{"index":0,"delta":{"content":"sim, das 9h às 13h."},"finish_reason":null}]}
data: {"id":"cm9x0execucao0001","conversation_id":"cm9x0conversa0001","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]- Concatene os
delta.contentna ordem para montar a resposta. - O último evento com JSON traz
deltavazio e ofinish_reasonfinal. Depois dele vemdata: [DONE], e a conexão fecha. - Se a geração falhar depois de o texto começar a sair, o último evento traz
finish_reason: "error", e o texto que já saiu fica gravado na conversa. Se falhar antes de qualquer texto, a resposta é um erro comum em JSON (veja Erros e limites). - Se você fechar a conexão antes do fim, a geração é cancelada.
- Quando uma pessoa já assumiu a conversa, a resposta é o
202em JSON descrito abaixo, e não um stream.
Exemplo com curl (-N desliga o buffer):
bash
curl -N https://api.cavori.com.br/v1/chat/completions \
-H "Authorization: Bearer $CAVORI_API_KEY" \
-H "Idempotency-Key: usuario-123-turno-2" \
-H "Content-Type: application/json" \
-d '{
"model": "agent:cm9x0example0001",
"conversation_id": "cm9x0conversa0001",
"messages": [{ "role": "user", "content": "E no domingo?" }],
"stream": true
}'Quando uma pessoa assumiu
Se a conversa está em HUMAN ou HUMAN_REQUESTED, a mensagem é gravada, o agente não responde e a resposta é 202:
json
{ "id": "cm9x0execucao0002", "conversation_id": "cm9x0conversa0001", "status": "WAITING_HUMAN" }A resposta humana chega por webhook ou por GET /v1/conversations/:id/messages.
Idempotência e conflitos
- Mesma
Idempotency-Keycom o mesmo corpo: devolve a execução já feita, sem gerar outra resposta, sempre em JSON, mesmo que a primeira chamada tenha sido em streaming. Se ela ainda estava em andamento, ou terminou emFAILEDouPARTIAL, a resposta é o estado dela, com status200e no formato de Execuções. Se uma pessoa tinha assumido (WAITING_HUMAN), a resposta é202, também no formato de Execuções. - Mesma
Idempotency-Keycom outro corpo:409 conflict. - Já existe uma resposta sendo gerada para essa conversa:
409 conflict. Aguarde terminar antes de enviar a próxima mensagem. - Mais execuções simultâneas do que o permitido:
429 rate_limit. Os limites estão em Erros e limites.
