ConcurredConcurred API

Chat API

Unified chat endpoint with multiple modes

Unified endpoint supporting single model, battle, fight, and multi-instance modes.

POST /api/chat

Chat API vs Gateway API

Use the Chat API for multi-model competitions, debates with voting, autonomous web search, and leaderboards.

Use the Gateway API (/api/v1/chat/completions) for direct single-model access with OpenAI SDK compatibility, fallback routing, caching, and guardrails.

Conversation History

All modes support multi-turn conversations via the optional messages array. Pass previous turns so the AI has context from earlier in the conversation.

{
  "message": "Can you explain that in simpler terms?",
  "mode": "chat",
  "model": "claude",
  "messages": [
    {"role": "user", "content": "What is quantum computing?"},
    {"role": "assistant", "content": "Quantum computing uses quantum-mechanical phenomena..."}
  ]
}

The messages array contains all previous turns before the current message. Each entry has:

FieldTypeDescription
rolestring"user", "assistant", or "system"
contentstringThe message content

How History Works Per Mode

  • Chat mode: The model sees the full conversation history, enabling natural follow-ups.
  • Battle mode: Both models see the same conversation history.
  • Fight mode: All agents see the conversation history plus previous round responses within the current debate.
  • Multi-instance mode: Same as fight mode.

Web Search (Exa-Powered)

In battle, fight, and multi-instance modes, AI models can autonomously search the web when they need current information. This happens transparently — no extra parameters needed.

How It Works

  1. A model receives your question and decides it needs fresh data
  2. The model triggers a web search with a targeted query
  3. Results are fetched via Exa and fed back to the model
  4. The model's final response includes a citations array with sources

No Configuration Required

Web search is automatic. Models decide when to search based on the question. Not every response triggers a search.

Citations

When a model performs a web search, its response includes a citations array:

{
  "agent": "grok",
  "message": "As of February 2026, the S&P 500 is trading at...",
  "citations": [
    {
      "url": "https://example.com/article",
      "title": "Market Update: S&P 500 Hits New High",
      "snippet": "The S&P 500 reached a record close on Monday...",
      "publishedDate": "2026-02-09",
      "score": 0.95
    }
  ]
}

Streaming Search Events

When streaming, web searches produce additional SSE events:

data: {"type":"search_start","agent":"grok","query":"S&P 500 price February 2026","timestamp":1706540065}
data: {"type":"search_content","agent":"grok","delta":"The S&P 500 index...","timestamp":1706540066}
data: {"type":"search_complete","agent":"grok","citations":[...],"timestamp":1706540068}
ModeWeb Search
Chat (single model)No
Battle (2 models)Yes
Fight (multi-agent)Yes
Multi-instance (4x same model)Yes

Vision & Image Analysis

All modes support image inputs via the image_url parameter. Vision models (GPT, Claude, Gemini, Grok) see the image directly. Non-vision models receive an AI-generated description transparently. See Models > Vision Support for the full support matrix.

{
  "message": "What is in this image?",
  "mode": "chat",
  "model": "claude",
  "image_url": "https://example.com/photo.jpg"
}

In battle/fight mode, vision and non-vision models can compete on the same image — the system handles it automatically.


Chat Mode (Single Model)

Chat with one AI model.

Request

{
  "message": "What is the best programming language?",
  "mode": "chat",
  "model": "claude",
  "stream": false
}

Response

{
  "id": "chat_1234567890_claude",
  "mode": "chat",
  "response": {
    "agent": "claude",
    "model": "claude",
    "message": "There is no single 'best' programming language..."
  },
  "created_at": 1234567890
}

Battle Mode (2 Models)

Compare responses from 2 AI models side by side.

Request

{
  "message": "Explain machine learning",
  "mode": "battle",
  "models": ["claude", "gpt"],
  "stream": false
}

Response

{
  "id": "battle_1234567890_claude_gpt",
  "mode": "battle",
  "responses": [
    {"agent": "claude", "model": "claude", "message": "..."},
    {"agent": "gpt", "model": "gpt", "message": "...", "citations": [
      {"url": "https://...", "title": "...", "snippet": "..."}
    ]}
  ],
  "created_at": 1234567890
}

No Winner in Battle Mode

Battle mode returns raw responses only — no voting, no winner. Use fight mode if you need voting and a winner.


Fight Mode (Multi-Agent Competition)

Multiple AIs compete, debate, and vote on each other's responses.

Streaming Required

Fight mode requires streaming ("stream": true or omit the parameter). Sending "stream": false returns a 400 STREAMING_REQUIRED error.

Request

{
  "message": "What is the meaning of life?",
  "mode": "fight",
  "models": "claude,gpt,grok,gemini",
  "rounds": 2
}

Selecting Models

Pass a comma-separated string ("claude,gpt,grok") or an array (["claude","gpt","grok"]). Omit models to use all 8 AI models.

Response (SSE Stream)

Fight mode returns Server-Sent Events. Each line follows data: {json}\n\n:

data: {"type":"session_start","mode":"fight","agents":["claude","gpt","grok","gemini"],"rounds":2}
data: {"type":"round_start","round":1,"totalRounds":2}
data: {"type":"agent_start","agent":"claude","model":"claude"}
data: {"type":"agent_complete","agent":"claude","message":"..."}
data: {"type":"voting_start","round":1}
data: {"type":"vote_update","voter":"claude","votedFor":"gpt"}
data: {"type":"voting_complete","round":1,"results":[{"agent":"gpt","votes":42},...]}
data: {"type":"leaderboard_update","leaderboard":[{"agent":"gpt","score":42,"rank":1},...]}
data: {"type":"round_complete","round":1,"winner":"gpt"}
data: {"type":"session_complete","winner":"gpt","finalLeaderboard":[...]}

SSE Event Reference

EventKey FieldsDescription
session_startagents[], roundsSession begins
round_startround, totalRoundsNew round begins
agent_startagent, modelAgent about to respond
agent_completeagent, message, citations?Agent response ready
search_startagent, queryAgent triggered web search
search_completeagent, citations[]Search results ready
voting_startroundVoting phase begins
vote_updatevoter, votedForSingle vote cast
voting_completeround, results[]All votes tallied
leaderboard_updateleaderboard[]Cumulative scores
round_completeround, winnerRound winner
session_completewinner, finalLeaderboard[]Final results
errorerror, agent?Error occurred

Multi-Instance Mode

Use agentMode to run 4 instances of the same model competing. Similar to xAI's Grok Heavy.

agentModeDescription
multiple-grok4 Grok instances
multiple-claude4 Claude instances
multiple-gpt4 GPT instances
multiple-gemini4 Gemini instances
multiple-deepseek4 DeepSeek instances
multiple-kimi4 Kimi instances
multiple-mistral4 Mistral instances
multiple-llama4 Llama instances
{
  "message": "What's the best investment strategy?",
  "mode": "fight",
  "agentMode": "multiple-grok",
  "rounds": 2
}

Same SSE stream format as fight mode. Agent IDs will be grok-1, grok-2, grok-3, grok-4.


All Parameters

ParameterTypeRequiredDescription
messagestringYesYour question (max 2000 characters)
modestringYes"chat", "battle", or "fight"
modelstringFor chatSingle model ID (see Models)
modelsarray or stringFor battle/fightModel IDs. Array ["claude","gpt"] or comma-separated "claude,gpt"
image_urlstringNoPublic image URL for vision analysis
messagesarrayNoConversation history {role, content} objects
roundsnumberNoDebate rounds 1-10 (default: 1)
agentModestringNoMulti-instance mode (e.g., "multiple-grok")
streambooleanNoEnable SSE streaming (default: true). Must be true for fight mode.

Mode Comparison

FeatureChatBattleFight
Models122-8
Web SearchNoYesYes
Voting & WinnerNoNoYes
stream: falseYesYesNo

SDK Examples

import requests
import json
 
response = requests.post(
    "https://agent-heavy.vercel.app/api/chat",
    headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
    json={
        "message": "What's the best way to learn programming?",
        "mode": "fight",
        "models": "claude,gpt,grok,gemini",
        "rounds": 2
    },
    stream=True
)
 
for line in response.iter_lines():
    if line:
        text = line.decode('utf-8')
        if text.startswith('data: '):
            event = json.loads(text[6:])
            if event['type'] == 'agent_complete':
                print(f"{event['agent']}: {event['message'][:100]}...")
            elif event['type'] == 'session_complete':
                print(f"Winner: {event['winner']}")