Request-Header

Drei optionale Header, die das Gateway versteht: zwei tragen Ihren eigenen Trace-Kontext bis in unsere Logs, einer hält ein Gespräch auf demselben Upstream, damit Prompt Caching weiter greift. Ohne sie ändert sich nichts.

Header Was das Gateway tut Wofür
X-Trace-Id Wird in der Antwort zurückgegeben und am Aufruf gespeichert, der so mit den anderen Aufrufen der Trace gruppiert wird. Einen Aufruf Ihrem eigenen Tracing-System zuordnen.
X-Span-Id Wird in der Antwort zurückgegeben und am Aufruf gespeichert; er benennt den Aufruf im Wasserfalldiagramm der Trace. Einen einzelnen Span innerhalb dieses Traces kennzeichnen.
X-Session-Id Wird zurückgegeben und am Aufruf gespeichert. Aufeinanderfolgende Requests mit demselben Wert werden an denselben Kanal und denselben Upstream-Key gebunden. Prompt Caching über ein ganzes Gespräch hinweg warm halten.
X-Request-ID Wird nicht von Ihnen übernommen. Ihr Wert kommt als X-Client-Request-ID zurück; die X-Request-ID der Antwort ist immer die vom Gateway erzeugte UUIDv7. Die Gateway-seitige Identität des Aufrufs - im Support-Ticket angeben.

So senden Sie sie

curl https://synthorai.io/v1/chat/completions \
  -H "Authorization: Bearer $SYNTHORAI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Session-Id: conv-8f3a2b" \
  -H "X-Trace-Id: 7c1d9e40f2b84a17" \
  -H "X-Span-Id: 2f9b41c8" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [{"role": "user", "content": "Hello"}]
  }'

Header, die andere Tools schon senden

Trägt ein Aufruf keinen unserer drei Header, liest das Gateway den entsprechenden Header, den ein Coding-Agent, ein SDK oder ein Tracing-Standard ohnehin sendet. So werden diese Läufe in Traces gruppiert, ohne dass Sie etwas ändern.

Header Gelesen als Gesendet von
X-Claude-Code-Session-Id Session Claude Code
X-Litellm-Session-Id Session LiteLLM SDK, OpenHands
Session-Id Session OpenAI Codex CLI
Helicone-Session-Id Session Helicone
X-OpenWebUI-Chat-Id Session Open WebUI
X-Opencode-Session-Id Session OpenCode
baggage: session.id=… Session W3C Baggage (OpenTelemetry)
baggage: gen_ai.conversation.id=… Session W3C Baggage (OpenTelemetry)
baggage: langfuse_session_id=… Session Langfuse SDK
X-Session-Affinity Session OpenClaw, OpenCode, Kilo Code
X-Litellm-Trace-Id Trace LiteLLM SDK
X-Portkey-Trace-Id Trace Portkey
traceparent Trace; die Parent-ID gilt als Span W3C Trace Context (OpenTelemetry)
X-Claude-Code-Prompt-Id Trace Claude Code
X-Interaction-Id Trace GitHub Copilot
X-Codex-Turn-Metadata Trace OpenAI Codex CLI
baggage: langfuse_trace_id=… Trace Langfuse SDK
X-Portkey-Span-Id Span Portkey
X-OpenWebUI-User-Id Endnutzer (Label _user) Open WebUI
baggage: user.id=… Endnutzer (Label _user) W3C Baggage (OpenTelemetry)
baggage: langfuse_user_id=… Endnutzer (Label _user) Langfuse SDK

Sind beide vorhanden, gilt immer unser eigener Header. Session-Id und X-Codex-Turn-Metadata werden nur von der Codex CLI gelesen, X-Interaction-Id nur von GitHub Copilot, erkannt am User-Agent. Ein Aufruf ganz ohne Trace-ID bekommt die Request-ID des Gateways als X-Trace-Id zurück.

Bei /v1/chat/completions und /v1/responses kann die Sitzungs-ID auch im Body stehen, als session_id (mit dem OpenAI SDK in extra_body). Ein Header hat Vorrang, und das Feld wird entfernt, bevor die Anfrage an den Anbieter geht.

OpenClaw sendet traceparent bei jedem Modellaufruf, seine Läufe werden also ohne Einstellung zu Traces gruppiert; für Sitzungen aktivieren Sie compat.sendSessionAffinityHeaders am Modell. Open WebUI sendet Chat-ID und Nutzer-ID, sobald ENABLE_FORWARD_USER_INFO_HEADERS gesetzt ist; die mitgesendeten Header für Name und E-Mail werden nicht gelesen. Ein Agent, der nichts davon sendet (Cursor, Aider, Cline, Continue und die meisten Agenten-Frameworks), braucht X-Session-Id in seinen eigenen Headern.

W3C Trace Context und Baggage

traceparent liefert den Trace und mit seiner Parent-ID den Span; eine OpenTelemetry-HTTP-Instrumentierung setzt ihn von selbst. Alles Weitere steht in baggage, unter den Namen von OpenTelemetry: session.id oder gen_ai.conversation.id für die Sitzung, gen_ai.agent.id und gen_ai.agent.name für den Agenten, user.id für den Endnutzer. Ihr Code muss sie dort eintragen: Ein OpenTelemetry-SDK kopiert Span-Attribute nicht ins Baggage. Der Name eines Agenten wird als dessen Typ gespeichert und darf Buchstaben, Ziffern, ., _ und - enthalten. tracestate wird nicht gelesen.

Agents innerhalb einer Sitzung

Ein Coding-Agent, der Sub-Agents startet, gibt bei jedem Aufruf an, welcher Agent ihn gemacht hat. Das Gateway speichert das zusammen mit dem Aufruf: Eine Sitzung zeigt so ihre Kosten je Agent, und ein Trace zeigt, welche Aufrufe Komprimierungen oder Nebenaufrufe waren und welche Tools zwischen zwei Aufrufen liefen. Keiner dieser Header ändert das Routing: Ein Sub-Agent bleibt auf dem Upstream seiner Sitzung.

Header Gelesen als Gesendet von
X-Agent-Id Agent Synthorai
X-Parent-Agent-Id Der Agent oder die Sitzung, die ihn gestartet hat Synthorai
X-Claude-Code-Agent-Id Agent Claude Code
X-Claude-Code-Parent-Agent-Id Der Agent oder die Sitzung, die ihn gestartet hat Claude Code
Thread-Id Agent OpenAI Codex CLI
X-Codex-Parent-Thread-Id Der Agent oder die Sitzung, die ihn gestartet hat OpenAI Codex CLI
baggage: gen_ai.agent.id=… Agent W3C Baggage (OpenTelemetry)
X-Parent-Session-Id Der Agent oder die Sitzung, die ihn gestartet hat OpenCode, Kilo Code
X-Opencode-Parent-Session-Id Der Agent oder die Sitzung, die ihn gestartet hat OpenCode
X-Claude-Code-Request-Class Art des Aufrufs Claude Code
X-Claude-Code-Agent-Type Art des Aufrufs Claude Code
X-Claude-Code-Compaction Art des Aufrufs Claude Code
X-Claude-Code-Context-Compacted Art des Aufrufs Claude Code
X-Openai-Subagent Art des Aufrufs OpenAI Codex CLI
baggage: gen_ai.agent.name=… Art des Aufrufs W3C Baggage (OpenTelemetry)
X-Claude-Code-Prev-Tool-Durations Laufzeiten der Tools Claude Code

Claude Code sendet die Agent-IDs standardmäßig. Die Art des Aufrufs und die Laufzeiten der Tools sendet es nur, wenn dort, wo es läuft, CLAUDE_CODE_GATEWAY_HINT_HEADERS=1 gesetzt ist.

Gespeichert: die IDs, der Typ eines Agents, die Art des Aufrufs sowie Tool-Namen mit ihren Laufzeiten in Millisekunden. Nicht gespeichert: der Name, den Sie einem Agent gegeben haben, und alles, was ein Tool gelesen oder geschrieben hat.

Eine Anfrage mit Labels versehen

Senden Sie X-Synthorai-Metadata mit einem JSON-Objekt aus Strings, um anzugeben, wofür eine Anfrage gedacht war: ein Feature, eine Umgebung, einer Ihrer Nutzer. Die Labels stehen bei der Anfrage in den Logs, filtern Logs, Traces und Sessions (metadata.feature = checkout), werden unter Analytics, Breakdown summiert und gehen mit Ihren Exporten hinaus.

curl https://synthorai.io/v1/chat/completions \
  -H "Authorization: Bearer $SYNTHORAI_API_KEY" \
  -H 'X-Synthorai-Metadata: {"feature":"checkout","env":"prod","_user":"u_123"}' \
  -d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"Hi"}]}'

Bis zu 10 Labels. Ein Schlüssel besteht aus 1 bis 32 Zeichen aus a-z 0-9 _ . -; ein Wert ist ein String von höchstens 128 Bytes. _user benennt den Endnutzer, für den die Anfrage gestellt wurde; jeder andere Schlüssel, der mit einem Unterstrich beginnt, ist reserviert. Ein Label, das eine Regel verletzt, wird verworfen, die Anfrage läuft trotzdem: Die Antwort nennt die verworfenen Schlüssel in X-Synthorai-Metadata-Dropped.

Labels werden mit der Anfrage so lange aufbewahrt wie das Anfrageprotokoll; das Filtern nach Labels umfasst die letzten 90 Tage. Schreiben Sie keine Prompt-Texte, personenbezogenen Daten oder Geheimnisse hinein; ein Wert, der wie ein Zugangsdatum aussieht, wird als [redacted] gespeichert. An den Anbieter werden sie nie gesendet.

Session-Affinität

Ein Cache-Eintrag liegt auf genau einem API-Key beim Anbieter. Ein Kanal kann mehrere Keys halten, und ohne Hinweis verteilt das Gateway die Aufrufe darauf - der zweite Zug eines Gesprächs landet dann womöglich auf einem Key, der Ihr Präfix nie gesehen hat, und zahlt die Schreibkosten erneut.

Senden Sie bei jedem Aufruf eines Gesprächs denselben Wert und für ein anderes Gespräch einen anderen. Serverseitig wird nichts gespeichert und nichts läuft ab: Der Wert wird gehasht, um Kanal und Key zu wählen - derselbe Wert führt also immer zum selben Ziel.

An den beiden OpenAI-kompatiblen Endpunkten - /v1/chat/completions und /v1/responses - können Sie den Header ganz weglassen: Enthält der Request-Body prompt_cache_key, nutzt das Gateway diesen als Affinitäts-Key. An /v1/messages und den Gemini-Endpunkten senden Sie den Header.

Affinität ist Best Effort: Sie entscheidet nur, welcher Kanal unter gleichrangigen Kandidaten gewählt wird. Failover, Rate-Limit-Cooldown, Retries und eine explizite Routing-Vorgabe gehen ihr immer vor. Der Listenpreis eines Modells ist auf jedem Kanal gleich, den wir wählen können.

Grenzen

  • Je 128 Byte. Längere Werte werden abgeschnitten. Ein Wert mit Steuerzeichen oder Zeichen außerhalb des druckbaren ASCII wird komplett verworfen - weder zurückgegeben noch geloggt. Diese Werte landen in einem Response-Header und einer Logzeile; das hält Header- und Log-Injection draußen.
  • Sie enden am Gateway. Keiner der drei wird an den Modellanbieter weitergereicht - der ausgehende Request trägt nur Authentifizierung, Content-Type und anbieterspezifische Header.
  • Keiner davon identifiziert einen Aufruf für die Abrechnung. Abrechnung, Deduplizierung und Abgleich hängen alle an der gateway-eigenen X-Request-ID, nie an einem Wert, den Sie kontrollieren.

Wenn etwas schiefgeht

  • Nennen Sie die gesendete X-Trace-Id oder die X-Request-ID aus der Antwort - mit beidem finden wir genau diesen Aufruf.
  • Ihre Trace-ID steht am Aufruf in den Protokollen und unter Traces, so finden Sie ihn selbst, bevor Sie ein Ticket eröffnen.
  • Um die Affinität zu prüfen, senden Sie denselben langen Präfix mehrfach mit einer X-Session-Id und sehen Sie sich die Cache-Spalten in den Protokollen an: Der erste Aufruf schreibt in den Cache, die folgenden sollten daraus lesen. Ändern Sie den Wert, sollte der Schreibvorgang wieder auftauchen.

Siehe auch: Prompt Caching · Traces und Sessions