Antonnia Docs

Mensagens de Entrada

Recebendo mensagens do seu canal e encaminhando para a Antonnia

Mensagens de entrada fluem dos usuários finais do seu canal para a Antonnia. Sua integração recebe a mensagem da API do canal, cria na Antonnia e dispara uma resposta da IA.

Criando uma mensagem

curl -X POST https://services.antonnia.com/conversations/v2/api/v1/sessions/sess_abc123/messages \
  -H "Authorization: Bearer sk_live_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": { "type": "text", "text": "I need help with my order" },
    "role": "user",
    "provider_message_id": "channel_msg_001"
  }'
response = httpx.post(
    f"{BASE_URL}/sessions/{session_id}/messages",
    headers=HEADERS,
    json={
        "content": {"type": "text", "text": "I need help with my order"},
        "role": "user",
        "provider_message_id": "channel_msg_001",
    },
)
message = response.json()

Campos obrigatórios

FieldDescrição
contentObjeto de conteúdo da mensagem com type e campos específicos do tipo
roleSempre "user" para mensagens de entrada

Campos opcionais

FieldDescrição
provider_message_idID da mensagem no seu canal — permite rastreamento de entrega e encadeamento de respostas
replied_provider_message_idO provider_message_id da mensagem sendo respondida (para respostas encadeadas)

Sempre defina provider_message_id quando disponível. Ele vincula a mensagem da Antonnia à mensagem do seu canal, o que é necessário para rastreamento de status de entrega e encadeamento de respostas.

Lidando com diferentes tipos de conteúdo

Mapeie os formatos de mensagem do seu canal para os tipos de conteúdo da Antonnia:

def build_content(channel_message: dict) -> dict:
    msg_type = channel_message["type"]

    if msg_type == "text":
        return {"type": "text", "text": channel_message["body"]}

    elif msg_type == "image":
        url = download_and_host(channel_message["media_url"])
        return {"type": "image", "url": url}

    elif msg_type == "audio":
        url = download_and_host(channel_message["media_url"])
        return {"type": "audio", "url": url}

    elif msg_type == "video":
        url = download_and_host(channel_message["media_url"])
        return {"type": "video", "url": url}

    elif msg_type == "document":
        url = download_and_host(channel_message["media_url"])
        return {
            "type": "file",
            "url": url,
            "mime_type": channel_message.get("mime_type", "application/octet-stream"),
            "name": channel_message.get("filename", "document"),
        }

    else:
        # Fallback: convert unsupported types to text
        return {"type": "text", "text": f"[{msg_type} message]"}

As URLs de mídia devem ser acessíveis publicamente. Se o seu canal fornece URLs privadas/assinadas, baixe a mídia e hospede novamente em uma URL pública antes de criar a mensagem.

Disparando respostas da IA

Após criar uma mensagem de usuário, dispare o agente de IA para responder:

curl -X POST https://services.antonnia.com/conversations/v2/api/v1/sessions/sess_abc123/reply \
  -H "Authorization: Bearer sk_live_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "debounce_time": 5 }'
if session["agent"] and session["agent"]["type"] == "ai":
    httpx.post(
        f"{BASE_URL}/sessions/{session_id}/reply",
        headers=HEADERS,
        json={"debounce_time": 5},
    )

Debounce

O parâmetro debounce_time (0 a 60 segundos, padrão: 3) atrasa a resposta da IA para agrupar mensagens sequenciais rápidas. Por exemplo, se um usuário envia três mensagens em 2 segundos com debounce_time: 5, a IA espera até 5 segundos após a última mensagem antes de responder.

Valores recomendados:

  • Canais de chat (WhatsApp, chat ao vivo): 3 a 5 segundos
  • Canais assíncronos (e-mail, tickets): 0 segundos (responder imediatamente)

Quando disparar

Só dispare respostas quando a sessão tiver um agente de IA:

if session.get("agent") and session["agent"]["type"] == "ai":
    # Trigger AI reply

Sessões com agentes humanos ou sem agente não devem disparar respostas automáticas.

Condições de corrida e locking

Quando múltiplas mensagens chegam simultaneamente para o mesmo contato, há risco de criar sessões duplicadas. Use um lock distribuído:

async with redis_lock(f"lock:mychannel:{contact_id}:{instance_id}", timeout=30):
    session = await get_or_create_session(contact_id, instance_id)
    await create_message(session["id"], content, provider_msg_id)
    await trigger_reply(session)

Veja o Guia de Integração de Canal para o padrão completo de locking.

On this page