Format anthropique
POST /v1/messages prend une requête au format Anthropic Messages et répond dans le même format, en streaming ou non. Utilisez-le avec le SDK Anthropic et avec les outils construits dessus, comme Claude Code : définissez l'URL de base, utilisez votre clé API Shannon et indiquez un id de modèle Shannon.
POST https://api.shannon-ai.com/v1/messages
Pointez le SDK Anthropic vers l'URL de base de Shannon. Le SDK ajoute /v1/messages et envoie votre clé dans l'en-tête x-api-key.
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com",
)
message = client.messages.create(
model="shannon-3",
max_tokens=1024,
messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
for block in message.content:
if block.type == "text":
print(block.text) import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com",
});
const message = await client.messages.create({
model: "shannon-3",
max_tokens: 1024,
messages: [{ role: "user", content: "Say hello in one sentence." }],
});
for (const block of message.content) {
if (block.type === "text") console.log(block.text);
} curl https://api.shannon-ai.com/v1/messages \
-H "x-api-key: YOUR_API_KEY" \
-H "content-type: application/json" \
-d '{
"model": "shannon-3",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Say hello in one sentence."}]
}' La réponse est un message dont content est une liste de blocs. Repérez les blocs par leur type : quand le modèle a raisonné, le premier bloc est thinking et le texte vient après.
{
"id": "msg_5f0c1e7a9b3d4c62a8e1f07d2b46c9a3",
"type": "message",
"role": "assistant",
"model": "shannon-3",
"content": [
{
"type": "thinking",
"thinking": "The user wants a greeting in one sentence. Keep it short and friendly."
},
{
"type": "text",
"text": "Hello, it is good to meet you."
}
],
"stop_reason": "end_turn",
"usage": {
"input_tokens": 1184,
"output_tokens": 46
}
} En-têtes
| En-tête | Valeur | Description |
|---|---|---|
x-api-key | YOUR_API_KEY | Votre clé API. Authorization: Bearer YOUR_API_KEY est accepté à sa place. |
content-type | application/json | Obligatoire. |
anthropic-version | 2023-06-01 | Accepté, non obligatoire. Le SDK Anthropic envoie 2023-06-01 ; la réponse a le même format quelle que soit la valeur. |
anthropic-beta | Accepté, non obligatoire. | |
x-request-id | Facultatif. Votre propre id pour la requête. Il revient inchangé dans la réponse ; sans lui, la réponse porte un id de 12 caractères hexadécimaux. |
Champs de requête
Seul messages est obligatoire. La colonne Appliqué par nomme les modèles sur lesquels un champ modifie la réponse. Les modèles open-weight hébergés sont les douze ids de la liste des modèles ; la famille Shannon 3 comprend shannon-3, shannon-3-pro, shannon-3.1 et shannon-3.1-pro. Modèles et tarifs
| Champ | Type | Par défaut | Description | Appliqué par |
|---|---|---|---|---|
model | string | shannon-1.6-lite | Un id de modèle Shannon de la liste des modèles. Envoyez-le avec chaque requête. La correspondance ne tient pas compte de la casse. Tout autre nom renvoie 400 unknown model ; un outil qui envoie ses propres noms de modèle doit donc être réglé sur un id Shannon. | Tous les modèles |
messages | array | Obligatoire. La conversation, message le plus ancien en premier, avec les rôles user et assistant. Voir Messages et blocs de contenu ci-dessous. | Tous les modèles | |
system | string | array | Instructions pour le modèle : une chaîne ou un tableau de blocs de texte. Voir Prompt système ci-dessous. | Modèles open-weight hébergés, shannon-1.6-*, shannon-2-*, shannon-coder-1 | |
max_tokens | integer | 4096 | Limite supérieure de la réponse, en tokens. Facultatif sur ce point de terminaison ; le SDK Anthropic l'envoie toujours. Une valeur hors de 1 à 65,536 est ramenée dans cette plage. C'est aussi le montant réservé sur votre solde pendant l'exécution de la requête. | Modèles open-weight hébergés, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 |
stream | boolean | false | true envoie la réponse sous forme de server-sent events. Voir Streaming ci-dessous. | Tous les modèles |
temperature | number | Température d'échantillonnage. Sur les modèles open-weight hébergés, les valeurs sont maintenues entre 0 et 2. | Modèles open-weight hébergés, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 | |
top_p | number | Échantillonnage par noyau (nucleus sampling). | Modèles open-weight hébergés | |
stop_sequences | array | Jusqu'à 4 chaînes. La réponse s'arrête avant la première qui apparaît. stop_reason reste end_turn. | Modèles open-weight hébergés | |
tools | array | Les outils que le modèle peut appeler, chacun sous la forme {"name", "description", "input_schema"}. Voir Outils ci-dessous. | Tous les modèles | |
tool_choice | object | {"type": "auto"} laisse le modèle décider, {"type": "any"} l'oblige à appeler un outil, {"type": "tool", "name": "…"} l'oblige à appeler cet outil. | Modèles open-weight hébergés | |
thinking | object | Combien le modèle raisonne avant de répondre. Voir Réflexion ci-dessous. | Modèles open-weight hébergés | |
web_search | boolean | false | Un ajout de Shannon au format : true permet au modèle de chercher sur le web avant de répondre. | shannon-1.6-*, shannon-2-*, famille Shannon 3 |
Sans max_tokens, la valeur est 4,096, et 65,536 sur shannon-coder-1.
Les marqueurs metadata, top_k, service_tier et cache_control sur les blocs sont acceptés pour que le code client existant fonctionne sans changement. Ils ne modifient pas la réponse ; la mise en cache du prompt sur les modèles open-weight hébergés est automatique.
Une réponse JSON conforme à un schéma se demande avec response_format sur Chat Completions et avec text.format sur Responses. Résultats structurés
Une requête avec un prompt système et la réflexion
Cette requête envoie un prompt système, un budget de réflexion, une température et une séquence d'arrêt. Elle utilise un modèle open-weight hébergé, qui les applique tous.
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com",
)
message = client.messages.create(
model="DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
max_tokens=4096,
system="You are a physics teacher. Answer in two sentences.",
thinking={"type": "enabled", "budget_tokens": 2048},
temperature=0.3,
stop_sequences=["\n\n"],
messages=[{"role": "user", "content": "Why is the sky blue?"}],
)
for block in message.content:
if block.type == "thinking":
print("reasoning:", block.thinking)
elif block.type == "text":
print("answer:", block.text)
print(message.usage) import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com",
});
const message = await client.messages.create({
model: "DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
max_tokens: 4096,
system: "You are a physics teacher. Answer in two sentences.",
thinking: { type: "enabled", budget_tokens: 2048 },
temperature: 0.3,
stop_sequences: ["\n\n"],
messages: [{ role: "user", content: "Why is the sky blue?" }],
});
for (const block of message.content) {
if (block.type === "thinking") console.log("reasoning:", block.thinking);
if (block.type === "text") console.log("answer:", block.text);
}
console.log(message.usage); curl https://api.shannon-ai.com/v1/messages \
-H "x-api-key: YOUR_API_KEY" \
-H "content-type: application/json" \
-d '{
"model": "DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
"max_tokens": 4096,
"system": "You are a physics teacher. Answer in two sentences.",
"thinking": {"type": "enabled", "budget_tokens": 2048},
"temperature": 0.3,
"stop_sequences": ["\n\n"],
"messages": [{"role": "user", "content": "Why is the sky blue?"}]
}' Sur les modèles open-weight hébergés, usage rapporte les tokens lus dans le cache du prompt séparément des autres tokens d'entrée.
{
"usage": {
"input_tokens": 31,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0,
"output_tokens": 62
}
} Prompt système
system est une chaîne, ou un tableau de blocs de texte de la forme [{"type": "text", "text": "…"}]. Les textes des blocs sont joints par un saut de ligne.
Il est appliqué par les modèles open-weight hébergés, shannon-1.6-lite, shannon-1.6-pro, shannon-2-lite, shannon-2-pro et shannon-coder-1. Avec un id de la famille Shannon 3, placez les instructions qui doivent être respectées dans le message utilisateur.
Messages et blocs de contenu
Un message a un role, user ou assistant, et un content. content est une chaîne ou un tableau de blocs.
| Bloc | Description | Disponible sur |
|---|---|---|
{"type": "text", "text": "…"} | Texte. | Tous les modèles |
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": "…"}}{"type": "image", "source": {"type": "url", "url": "…"}} | Une image dans un message user, en base64 ou par URL. | Famille Shannon 3, shannon-1.6-lite, shannon-1.6-pro, et les modèles open-weight hébergés qui acceptent les images en entrée |
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": "…"}} | Un document (PDF, Word, PowerPoint ou Excel) dans un message user, en base64 ou par URL. | Famille Shannon 3 |
{"type": "tool_use", "id": "toolu_…", "name": "…", "input": {…}} | Dans un message assistant : un appel d'outil fait par le modèle dans une réponse précédente. | Tous les modèles |
{"type": "tool_result", "tool_use_id": "toolu_…", "content": "…"} | Dans un message user : le résultat de cet appel. content est une chaîne ou une liste de blocs de texte. | Tous les modèles |
Vous pouvez renvoyer tel quel le content d'une réponse précédente : les blocs text et tool_use sont lus, les blocs thinking sont ignorés.
Sur les niveaux Shannon, les images et les documents sont lus dans le dernier message user. Les tailles et les limites ont leur propre page. Images et fichiers
Réflexion
Les modèles open-weight hébergés font correspondre thinking à un effort de raisonnement. Sans ce champ, l'effort est élevé.
| Forme | budget_tokens | Effet |
|---|---|---|
{"type": "disabled"} | Pas de raisonnement. La réponse n'a pas de bloc thinking. | |
{"type": "enabled", "budget_tokens": 2048} | ≤ 2,048 | Effort faible. |
{"type": "enabled", "budget_tokens": 8192} | ≤ 8,192 | Effort moyen. |
{"type": "enabled", "budget_tokens": 16000} | > 8,192 | Effort élevé. |
Un modèle qui raisonne renvoie son raisonnement sous forme de bloc {"type": "thinking", "thinking": "…"} avant le texte. Les niveaux Shannon qui raisonnent l'envoient aussi.
Les efforts sont décrits sur leur propre page. Effort de raisonnement
Outils
Un outil est une fonction exécutée par votre code. Décrivez chacun avec un name, une description et un input_schema. Quand le modèle veut un outil, la réponse contient un bloc tool_use et stop_reason vaut tool_use.
Une définition d'outil dans tools :
[
{
"name": "get_weather",
"description": "Current weather for a city.",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string"
}
},
"required": [
"city"
]
}
}
] Le content d'une réponse qui l'appelle :
[
{
"type": "text",
"text": ""
},
{
"type": "tool_use",
"id": "toolu_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"name": "get_weather",
"input": {
"city": "Paris"
}
}
] Exécutez l'outil, puis renvoyez la requête avec l'appel et un bloc tool_result ajoutés à messages :
[
{
"role": "user",
"content": "What is the weather in Paris?"
},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"name": "get_weather",
"input": {
"city": "Paris"
}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_3d9a7c1e5b2f4a60c8e1d7f09b24a6c5",
"content": "{\"temperature_c\": 18, \"sky\": \"cloudy\"}"
}
]
}
] tool_choice
| Forme | Effet | Appliqué par |
|---|---|---|
{"type": "auto"} | Le modèle décide s'il appelle un outil. C'est la valeur par défaut. | Tous les modèles |
{"type": "any"} | Le modèle doit appeler l'un des outils. | Modèles open-weight hébergés |
{"type": "tool", "name": "…"} | Le modèle doit appeler l'outil nommé. | Modèles open-weight hébergés |
Seuls les outils avec un input_schema sont lus. La recherche web n'est pas un outil sur ce point de terminaison : utilisez le champ web_search.
La boucle d'outils est décrite en détail sur sa propre page. Appel de fonction
La réponse
| Champ | Type | Description | Envoyé par |
|---|---|---|---|
id | string | msg_ suivi de 32 caractères hexadécimaux. | Tous les modèles |
type | string | Toujours message. | Tous les modèles |
role | string | Toujours assistant. | Tous les modèles |
model | string | L'id canonique du modèle qui a répondu. | Tous les modèles |
content | array | Les blocs de la réponse, dans cet ordre : thinking quand le modèle a raisonné, text, puis un tool_use par appel d'outil. | Tous les modèles |
stop_reason | string | Pourquoi la réponse s'est terminée. Voir les valeurs ci-dessous. | Tous les modèles |
usage | object | input_tokens et output_tokens. | Tous les modèles |
sources | array | Seulement sur une requête avec web_search: true dont la recherche a trouvé quelque chose : les résultats remis au modèle, chacun avec index, title et url. [1] dans la réponse est l'entrée dont index vaut 1. Dans un flux, il arrive avec l'événement message_delta. | shannon-1.6-*, shannon-2-*, famille Shannon 3 |
usage.cache_read_input_tokens | integer | cache_read_input_tokens est la partie du prompt lue dans le cache ; input_tokens est le reste. cache_creation_input_tokens vaut toujours 0. | Modèles open-weight hébergés |
Blocs de la réponse
| Bloc | Description |
|---|---|
{"type": "thinking", "thinking": "…"} | Le raisonnement du modèle. Il n'y a pas de membre signature. |
{"type": "text", "text": "…"} | Le texte de la réponse. Il peut être vide quand la réponse est un appel d'outil. |
{"type": "tool_use", "id": "toolu_…", "name": "…", "input": {…}} | Un appel d'outil. input est un objet JSON. Renvoyez le résultat avec le même id. |
stop_reason
| stop_reason | Description | Envoyé par |
|---|---|---|
end_turn | Le modèle a terminé sa réponse, ou l'une de vos stop_sequences est apparue. | Tous les modèles |
tool_use | La réponse contient un ou plusieurs appels d'outil. | Tous les modèles |
max_tokens | La réponse a été coupée à la limite de sortie. | Famille Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1, dans les flux |
Streaming
Mettez stream à true pour recevoir des server-sent events. Chaque trame a une ligne event: avec le nom de l'événement et une ligne data: avec un objet JSON qui répète le nom dans type. Les aides de streaming du SDK Anthropic lisent ces événements pour vous :
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com",
)
with client.messages.stream(
model="shannon-3",
max_tokens=1024,
messages=[{"role": "user", "content": "Explain server-sent events in three sentences."}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
message = stream.get_final_message()
print()
print(message.stop_reason, message.usage) import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com",
});
const stream = client.messages.stream({
model: "shannon-3",
max_tokens: 1024,
messages: [{ role: "user", content: "Explain server-sent events in three sentences." }],
});
stream.on("text", (text) => process.stdout.write(text));
const message = await stream.finalMessage();
console.log("\n", message.stop_reason, message.usage); curl -N https://api.shannon-ai.com/v1/messages \
-H "x-api-key: YOUR_API_KEY" \
-H "content-type: application/json" \
-d '{
"model": "shannon-3",
"max_tokens": 1024,
"stream": true,
"messages": [{"role": "user", "content": "Explain server-sent events in three sentences."}]
}' Les événements, dans l'ordre où ils arrivent :
| Événement | Données | Quand |
|---|---|---|
message_start | message | Toujours en premier. message contient l'id, le rôle, le modèle, un content vide et un usage qui part de zéro. |
content_block_start | index, content_block | Un bloc s'ouvre. content_block est un bloc text ou thinking vide, ou un bloc tool_use avec son id et son name. |
content_block_delta | index, delta {"type": "thinking_delta", "thinking"} | Un morceau du raisonnement, pour un bloc thinking. |
content_block_delta | index, delta {"type": "text_delta", "text"} | Un morceau de la réponse, pour un bloc text. |
content_block_delta | index, delta {"type": "input_json_delta", "partial_json"} | Les arguments d'un appel d'outil, complets en un seul delta, pour un bloc tool_use. |
content_block_stop | index | Le bloc portant cet index est terminé. |
message_delta | delta {stop_reason, stop_sequence}, usage | La fin de la réponse : delta.stop_reason, et l'usage de la requête. |
message_stop | Toujours en dernier. |
Les blocs sont numérotés par index dans l'ordre de leur ouverture, et un bloc est terminé avant que le suivant s'ouvre. Lisez chaque bloc selon son type, pas selon son numéro : un flux peut d'abord ouvrir un bloc text vide, puis le bloc thinking, et livrer la réponse dans un bloc text ultérieur.
event: message_start
data: {"type":"message_start","message":{"id":"msg_5f0c…","type":"message","role":"assistant","model":"shannon-3","content":[],"usage":{"input_tokens":0,"output_tokens":0}}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"thinking","thinking":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"thinking_delta","thinking":"Three sentences: what it is, how it is framed, why it is used."}}
event: ping
data: {"type": "ping"}
event: content_block_stop
data: {"type":"content_block_stop","index":1}
event: content_block_start
data: {"type":"content_block_start","index":2,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":2,"delta":{"type":"text_delta","text":"Server-sent events let a server push text over one HTTP reply."}}
event: content_block_stop
data: {"type":"content_block_stop","index":2}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":1190,"output_tokens":84}}
event: message_stop
data: {"type":"message_stop"} Keep-alive
| Envoyé par | Description |
|---|---|
Famille Shannon 3, shannon-1.6-lite, shannon-1.6-pro, shannon-coder-1 | Un événement ping avec les données {"type": "ping"}, toutes les 15 secondes. |
| Modèles open-weight hébergés | Une ligne de commentaire : keepalive, toutes les 15 secondes pendant que le modèle travaille. |
Un flux qui échoue
Un échec après le début du flux est un événement error avec le même corps qu'une réponse d'erreur : {"type": "error", "error": {"type", "message"}}. Les événements de clôture, message_delta et message_stop, suivent quand même. Considérez la réponse comme échouée et renvoyez la requête.
Erreurs
Les erreurs utilisent le corps d'erreur Anthropic : type vaut error, et l'objet error contient un type et un message. Le tableau liste ce que ce point de terminaison renvoie le plus souvent. La liste complète, avec ce qu'il faut réessayer, a sa propre page. Gestion des erreurs
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} | Statut | Type | Message | Quand |
|---|---|---|---|
401 | authentication_error | Missing authenticationInvalid API key | Aucune clé API n'a été envoyée, ou la clé est inconnue ou révoquée. |
400 | invalid_request_error | unknown model: <id> | model n'est pas un id de modèle Shannon. |
400 | invalid_request_error | No user message provided | Niveaux Shannon : la requête n'a ni texte utilisateur ni tools. |
400 | invalid_request_error | <id> does not accept image input | Une image a été envoyée à un modèle open-weight hébergé sans entrée image. |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | messages est absent, ou un champ a un mauvais type JSON. |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | max_tokens est supérieur à ce qui reste de votre solde. |
429 | rate_limit_error | Too many requests. Retry in <n>s. | Protection anti-flood : plus de 120 requêtes en une minute sur votre compte. |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | shannon-coder-1 : les appels Shannon Coder de votre forfait pour la fenêtre actuelle de 4 heures sont épuisés. |
500 | server_error | The model backend failed to answer. Please retry. | Le modèle n'a pas produit de réponse. Renvoyez la requête. |
502 | api_error | The model backend failed to answer. Please retry. | Le modèle n'a pas produit de réponse. Renvoyez la requête. |
Comptage de tokens
POST /v1/messages/count_tokens prend le même corps qu'une requête de message (model, system, messages, tools) et renvoie {"input_tokens": n} : le nombre de tokens d'entrée qui seraient facturés pour la requête. Il compte pour les modèles open-weight hébergés, il est gratuit et il n'est pas comptabilisé par la protection anti-flood.
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com",
)
count = client.messages.count_tokens(
model="DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
system="You are a physics teacher. Answer in two sentences.",
messages=[{"role": "user", "content": "Why is the sky blue?"}],
)
print(count.input_tokens) import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com",
});
const count = await client.messages.countTokens({
model: "DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
system: "You are a physics teacher. Answer in two sentences.",
messages: [{ role: "user", content: "Why is the sky blue?" }],
});
console.log(count.input_tokens); curl https://api.shannon-ai.com/v1/messages/count_tokens \
-H "x-api-key: YOUR_API_KEY" \
-H "content-type: application/json" \
-d '{
"model": "DeepSeek-V4-Flash-0731-W4A16-AUTOROUND-REAP",
"system": "You are a physics teacher. Answer in two sentences.",
"messages": [{"role": "user", "content": "Why is the sky blue?"}]
}'
# {"input_tokens": 31} Le comptage a sa propre page, avec le point de terminaison en texte brut et les limites. Décompte de tokens