Document Gateway trace context and baggage forwarding

JI
7h ago
+163-1

Summary

Documents the behavior added to the AI Gateway. The Gateway continues the caller's trace from traceparent, and copies baggage entries onto the span it records in the project.

  • New page docs/reference/advanced/gateway/telemetry.md, "See Gateway requests in your app's trace". It covers prerequisites, a Pydantic AI setup and an OpenAI SDK setup, a verify step with a SQL query, what the Gateway does with each header, and troubleshooting.
  • gateway/index.md: the ### Telemetry section now names the Include messages setting as the UI shows it and links to the new page.
  • navigation.yml: adds the page to the AI Gateway section after "Send Your First Request".
  • baggage.md: one sentence that links to the new page.

The page is a new how-to rather than a longer Telemetry section, so the overview stays short and each page does one job.

Validation

  • uv run pytest tests/test_docs.py tests/test_docs_serve.py: 269 passed. Both Python examples are tagged skip-run with external-connection, as the other Gateway examples are. Two runs reported 2 failures that did not reproduce in five reruns, and I did not capture which tests they were.
  • prek run on the changed files passes.
  • End-to-end run. I ran the two code blocks from this page, extracted from the Markdown, against a local Gateway with a fake OpenAI upstream and a local collector standing in for Logfire. Results:
    • Pydantic AI: the Gateway span is a child of the chat gpt-5.2 span, in the same trace. user_tier, experiment, and Pydantic AI's own gen_ai.agent.name, gen_ai.agent.call.id and gen_ai.conversation.id appear as attributes on the Gateway span. This works without instrument_httpx, because Pydantic AI's gateway/ provider sends the headers itself.
    • OpenAI SDK with instrument_httpx: the Gateway span is a child of the POST span. Without instrument_httpx it starts a trace of its own.
    • The fake upstream received exactly one traceparent carrying the client's trace id, and no baggage header.
    • With Include messages off, a baggage entry named gen_ai.input.messages is not copied as an attribute. The whole header is still recorded as http.request.header.baggage, and the page says so.