Skip to main content

Complete Workflows

This page shows how to structure an end-to-end trace in a real app: one root span per request/job, and a few child spans for the steps that matter. Keep most of your code descriptive and add spans only where they provide signal.
  1. Entry point: wrap your request handler / worker job with start_observe.
  2. Key steps: add observe spans for major stages (retrieval, generation, tools).
  3. Provider calls: rely on auto-instrumentation when possible (OpenAI, vector DBs, frameworks).
  4. Quality: attach evaluators at the root (optionally sampled).

Example: minimal RAG workflow

Where prompts fit

Fetch a prompt once per generation step, then call your LLM with prompt.text and prompt.model:

Where evaluators fit

Attach evaluators at the root so the whole trace (including auto-instrumented provider spans) inherits them:

Async workflow

Use the same structure in async code: root span at the entry point, child spans for key steps. Prefer the patterns used in your codebase (decorators vs context managers) and keep spans coarse-grained.

Next steps