Skip to main content

Overview

Cloudflare Think uses the Vercel AI SDK internally. Think owns the streamText call, so add Latitude telemetry in beforeTurn() instead of at a model call site. Start with the basic setup. Add context only if you need traces to include user, session, tags, or metadata from your app.

Requirements

  • A Latitude API key
  • A Latitude project slug
  • A Cloudflare Workers project using @cloudflare/think
  • The nodejs_compat compatibility flag enabled in your Worker
  • LATITUDE_API_KEY and LATITUDE_PROJECT_SLUG configured as Worker secrets or variables

Basic Telemetry

This records Think model calls, tools, latency, tokens, prompts, and responses.
1

Install

2

Initialize Latitude once

If your Worker exposes secrets through process.env, this is all you need. Most Workers receive secrets through env bindings instead. In that case, keep one Latitude instance per Worker isolate:
Then use getLatitude(this.env).getTracer("cloudflare-think") in beforeTurn() and getLatitude(this.env).flush() in onChatResponse() / onChatError(). Do not create new Latitude() inside beforeTurn().

Add App Context

If your app uses Think’s default WebSocket chat entrypoint, pass the same context you would normally pass to capture() through useAgentChat({ body }).
Then read that context in beforeTurn() and pass it to getTracer():
This is the recommended setup for most Think apps.

Codemode Internal Tools

Requires @latitude-data/telemetry 3.6.0 or newer. Think’s codemode execute tool appears as a normal AI SDK tool span. Tools called from inside codemode run outside the active AI SDK tool-call context, so wrap both the internal tool set and the outer execute tool with createCodemodeTelemetry(). The helper records each internal codemode tool as an ai.toolCall <name> child span under execute, stamps the same Latitude context as the turn, records AI SDK and GenAI tool attributes, and marks failed tools with exception details. When concurrent execute calls cannot be correlated after crossing the codemode sandbox boundary, ambiguous internal spans are omitted instead of attaching them to the wrong trace.
This produces one trace waterfall with the codemode internals nested under the outer tool call:
By default, tool inputs and outputs are captured as span attributes. Disable capture or redact values if codemode tools handle sensitive data:

Programmatic Turns

If your app starts Think turns with your own runTurn() call, wrap that call with capture().
Keep getTracer() in beforeTurn():
Do not use capture.start() / scope.end() on Cloudflare Workers. Use capture() as a callback wrapper instead.

If You Cannot Wrap The Turn

If you cannot wrap the turn, pass context directly to the tracer from beforeTurn(). The context can come from agent state, Durable Object storage, auth state, or any place your agent can read during the turn.
This records the model and tool spans with the right context. It does not add a separate parent cloudflare-think-turn span.

Runnable Example

The Latitude repository includes a runnable Think example at examples/cloudflare-think-app. It includes an execute codemode tool backed by several demo tools, a small QA page, and a local verifier that checks model spans, codemode tool spans, userId, and sessionId against local Latitude.

Seeing Your Traces

Once connected, traces appear automatically in Latitude:
  1. Open your project in the Latitude dashboard
  2. Send a message to your Think agent
  3. The turn appears with model calls, tool calls, messages, latency, token usage, and errors