Messages (Anthropic)
Senast uppdaterad:
På denna sida
POST https://api.staik.se/v1/messagesAnthropic Messages API-kompatibel endpoint — Claude Code, Anthropic SDK och andra
verktyg som pratar Anthropic-protokollet fungerar direkt. Autentisera med
x-api-key eller Authorization: Bearer (samma nyckel).
import anthropic
client = anthropic.Anthropic(
base_url="https://api.staik.se",
api_key="sk-st-your-key",
)
message = client.messages.create(
model="qwen3.6:35b-a3b",
max_tokens=1024,
messages=[{"role": "user", "content": "Förklara hur en transformer fungerar."}],
)
print(message.content[0].text)Modellmappning
Skicka antingen staik-modellnamn eller Claude-modellnamn — Claude-namn mappas automatiskt (främst för sömlös Claude Code-integration):
| Skickat modellnamn | Mappas till |
|---|---|
claude-sonnet-4-6 | qwen3.6:35b-a3b |
claude-opus-4-6 | qwen3.6:35b-a3b |
claude-haiku-4-5-20251001 | qwen3.5:9b |
Prompt caching
cache_control-breakpoints stöds (max 4 per request, som hos Anthropic).
Markerad kontext cachas och återanvänds — den cachade delen billas som
rabatterad cache_read i stället för fullpris varje tur. TTL är 5 minuter,
eller 1 timme med ttl: "1h". Cache-träffarna syns i svarets usage-fält.
{
"system": [
{
"type": "text",
"text": "...stor systemprompt eller kontext...",
"cache_control": {"type": "ephemeral"}
}
]
}Funktioner som stöds
- Streaming i Anthropic-format. Händelserna är
message_start,content_block_start,content_block_delta,content_block_stop,message_deltaochmessage_stop. - Tool calling:
tools,tool_useochtool_resultöversätts automatiskt. - System prompt som sträng eller content blocks.
- Kvoter och köer är desamma som för OpenAI-endpointen.
Verktygsval (tool_choice)
tool_choice stöds med alla fyra typerna. disable_parallel_tool_use: true ger
högst ett verktygsanrop per svar.
tool_choice | Betydelse |
|---|---|
{"type": "auto"} | Modellen väljer själv (standard) |
{"type": "any"} | Modellen måste anropa något av verktygen |
{"type": "tool", "name": "extract_invoice"} | Modellen måste anropa just det verktyget |
{"type": "none"} | Modellen får inte anropa verktyg |
Ett tvingat verktyg är det säkra sättet att få strukturerad data ur en modell:
message = client.messages.create(
model="qwen3.6:35b-a3b",
max_tokens=1024,
tools=[{
"name": "extract_invoice",
"description": "Fält från en faktura",
"input_schema": {
"type": "object",
"properties": {"total": {"type": "number"}, "due_date": {"type": "string"}},
"required": ["total"],
},
}],
tool_choice={"type": "tool", "name": "extract_invoice"},
messages=[{"role": "user", "content": "Fakturan: totalt 1 234,50 kr, förfaller 30/11."}],
)
print(message.content[0].input) # {"total": 1234.5, "due_date": "..."}tool_choice utan tools ignoreras. Ett name som inte finns bland tools ger 400.
Modellerna på staiks GPU:er följer valet. Egna GPU-noder med Ollama följer ett tvingat
verktyg (tool och any) men inte auto med strict.
Argumenten följer input_schema
När modellen tvingas anropa ett verktyg ({"type": "tool"}, eller {"type": "any"})
begränsas genereringen till verktygets input_schema, både med och utan streaming. Det är
samma mekanism som response_format med json_schema (strict) i
chat completions. Svaret är ett tool_use-block med
stop_reason: "tool_use". Med any och flera verktyg väljer modellen ett av dem, och
argumenten följer just det verktygets schema.
"strict": true på ett verktyg begränsar argumenten även när modellen själv väljer att
anropa det (auto). Det fungerar på qwen3.6:35b-a3b och qwen3.5:9b, men inte på
gemma4:31b.
För verktyg med schema rekommenderar vi qwen3.6:35b-a3b. gemma4:31b rekommenderas inte:
den kan fastna i blanktecken tills max_tokens även när argumenten begränsas, och den
begränsar inte strict med auto.
tools=[{"name": "extract_invoice", "strict": True, "input_schema": {...}}]Svarshuvudet x-staik-tool-schema-enforced finns när anropet har ett tvingat verktyg
eller ett strict-verktyg:
| Värde | Betydelse |
|---|---|
true | Argumenten är begränsade till hela schemat |
false | Inte hela schemat kunde begränsas: schemat har nyckelord som inte stöds, eller modellen kan inte begränsa strict med auto. Validera argumenten själv |
Ett svar som kapas av max_tokens (stop_reason: "max_tokens") kan ha ofullständiga
argument även när huvudet är true.
JSON Schema-nyckelord som begränsas: type (även listor som ["string", "null"]),
properties, required, additionalProperties, items, prefixItems, enum, const,
anyOf, oneOf, $ref (lokala, #/$defs/...), $defs, definitions, minLength,
maxLength, pattern, format (date, date-time, time, duration, email,
hostname, ipv4, ipv6, uri, uri-reference, uri-template, uuid,
json-pointer, relative-json-pointer), minimum, maximum, exclusiveMinimum,
exclusiveMaximum, multipleOf, minItems, maxItems och patternProperties.
Beskrivande fält som title, description, default och examples påverkar inte.
Stöds inte: allOf, not, if/then/else, dependentRequired,
dependentSchemas, unevaluatedProperties, unevaluatedItems, propertyNames,
uniqueItems, contains, minContains, maxContains, minProperties,
maxProperties, externa $ref och andra format. De tas bort ur begränsningen, resten
av schemat begränsas och huvudet blir false.
Fält som kan saknas
Ett obligatoriskt fält av typen string måste alltid fyllas i. Saknas uppgiften i
underlaget skriver modellen något, till exempel en tom sträng. Ge fältet typen
["string", "null"] om det får saknas, så kan modellen svara null.
PDF och dokument
document-block stöds. En PDF skickas som base64, och staik läser den som Claude gör:
för varje sida får modellen sidans textlager och en bild av sidan, i sidordning och
med rubriken "Sida 3 av 7". Blockets title och context följer med.
import base64
pdf = base64.standard_b64encode(open("faktura.pdf", "rb").read()).decode()
message = client.messages.create(
model="qwen3.6:35b-a3b",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{
"type": "document",
"title": "faktura.pdf",
"source": {"type": "base64", "media_type": "application/pdf", "data": pdf},
},
{"type": "text", "text": "Vilket är totalbeloppet?"},
],
}],
)source.type | Hur det läses |
|---|---|
base64 (application/pdf) | Textlager och sidbild per sida |
text | Texten som den är |
content | Blocken i content (text och base64-bilder) |
url, file | 400. staik hämtar inga URL:er eller filer, skicka base64 |
Dokument fungerar i user-meddelanden, i tool_result och i system.
Gränser:
- högst 20 sidor per PDF och 40 sidor per anrop
- hela anropet får vara högst 20 MB, så en PDF kan vara ungefär 15 MB (base64 gör den en tredjedel större)
- PDF:er med lösenord och trasiga filer ger 400
Över gränsen svarar API:t med 400 i stället för att korta dokumentet.
Kostnad: varje sidbild räknas som en bild i usage.input_tokens, plus textlagret.
En A4-sida blir ungefär 2 100 bildtokens på Qwen-modellerna och ungefär 420 på
gemma4:31b.
Skannade PDF:er har inget textlager och kan bara läsas som bild, så de kräver en modell med vision. En modell utan vision får bara textlagret, och en sida utan text ger då 400.
Fel
Fel kommer i Anthropics format, så Anthropic-SDK:n visar meddelandet direkt:
{
"type": "error",
"error": {"type": "invalid_request_error", "message": "PDF:en har 25 sidor; max är 20 per dokument. ..."}
}Begränsningar
- Extended thinking:
thinking-parametern ignoreras och svaret kommer utan resonemang.-thinking-alias räknas som okänd modell och besvaras av standardmodellen. Thinking finns via chat completions. - Bilder skickas som base64-bildblock (samma modeller och regler som chat completions). Bilder via URL ger 400.
Claude Code
Två miljövariabler räcker: ANTHROPIC_BASE_URL=https://api.staik.se och
ANTHROPIC_API_KEY=sk-st-.... Full guide under
Claude Code.