Witdem
EN / DE
Back

Haystack

Haystack observability beyond a green pipeline

A finished Haystack run means components executed. It does not mean the product job succeeded. Observability has to cover both stories on the same run.

What ran vs what it meant

Haystack pipelines compose retrievers, generators, and tools. Tracing shows which components fired. That is useful, but it is only half the picture.

You also need a clear product goal. Did the job you named actually hold? Without that question, a green pipeline can hide an empty or ungrounded answer.

Think in layers on one run: tracing for spans, evaluation for quality checks, cost for spend, and outcomes for “was the job done?” Keep them joined. Do not leave the last layer in a chat or a sheet.

Product goal — was the job done? Cost — what did this run spend? Evaluation — quality vs criteria? Tracing — Haystack component spans

What this means in practice

Picture one Haystack RAG run from start to finish. You walk the same run twice: once for components, once for the job you promised the user.

First you look at tracing. Retrievers ran. The generator returned. Spans look fine. That only says the pipeline finished its steps.

Then you ask the product question. Is there a usable answer? Is it grounded in the retrieved context? If those checks fail, the run failed for the user — even when HTTP status looks healthy.

Attach cost to that same run identity. Tokens and tool spend matter more when you know whether the goal passed. A cheap miss and an expensive miss are different reviews, but both need the goal marked.

Write the rule once next to the code. Every engineer should score the same run the same way. That is Haystack observability beyond a green status light.

Example: false success

Both retrievers can return hits. The generator can return HTTP 200. The answer can still be empty or ungrounded. That gap is a false success.

Trace

Looks healthy

  1. Retrievers returned hits
  2. Generator finished
  3. HTTP 200 OK

Everything ran as planned.

Product goal

Still failed

Empty or ungrounded answer

Runtime OK. Job not done.

Ops may trust the green path. Product still sees a failed job. Without a named goal on the run, those two views never meet.

Hits from a retriever are not the same as a useful answer. A finished generator span is not the same as grounded text the user can trust.

A product goal is a short shared rule for “done.” Evidence is the fields that prove pass or fail. Keep both beside Haystack component spans.

Then a review can ask a fair question: did we spend money on a real win, or on a clean pipeline that still missed the job?

Instrument the pipeline

Use one integration point. Wrap the pipeline. Keep Haystack’s native tracer. Attach meaning on the data you get back.

The snippet below reports whether an answer is present. That is a simple start. You can add richer checks later without changing the wrap shape.

from witdem_sdk.integrations.haystack import instrument

pipeline = instrument(
    build_pipeline(...),
    report_result=lambda result: {
        "result": "completed" if result.get("answer", {}).get("answer") else "unresolved",
        "result_valid": bool(result.get("answer", {}).get("answer")),
        "requirements": {"non_empty_answer": bool(result.get("answer", {}).get("answer"))},
    },
)

Declare success next to the code

Put the product goal in the repo. Then every engineer scores the same run with the same rule.

A contract names the artifact and the goal. Pass means the answer field is present. The rule lives in git with the pipeline, not only in a dashboard toggle.

version: 1
service:
  name: haystack-answer
  runtime: haystack
contracts:
  useful_answer:
    artifact:
      name: Answer
      valid:
        non_empty: $.answer
    product_goal:
      name: Non-empty answer
      achieved:
        all:
          - $.witdem.artifact_valid

What to look for on the run

Goal achievement, evidence fields, and spend should share one run identity. Keep them beside component spans. Do not replace spans with a lone score.

When you open a run, you want the path and the outcome together. That is how you debug a false success without guessing across tools.

Run replay of Haystack advanced RAG with outcome markers on the same run
Run replay — Haystack advanced RAG path plus product goal on the same run

Run the example

Start from the parallel-retriever example in the open-source repo. Wire the instrument helper, declare a goal, and review one run end to end.

Read the Haystack integration docs if you need the API shape. Keep tracing in place. Add the outcome layer beside it.

GitHub example Haystack docs

FAQ

Does a green Haystack pipeline mean success? No. Green means components finished. Success means the product goal you named held for that run.

Do I replace Haystack’s native tracer? No. Keep native tracing for component spans. Attach outcome fields next to them on the same run.

What is a product goal for RAG? A short shared rule for “done,” such as a non-empty answer or a grounded answer check. Evidence is the fields that prove pass or fail.

Where should the rule live? In the repo next to the pipeline, so reviews reuse one definition instead of inventing “good” in each tool.

Related

Agentic workflow observability · LangGraph observability · LangChain observability · OpenAI Agents observability

Get started Read the docs GitHub
Witdem

Analytics for AI agents and multi-step AI applications.

Home Guide Privacy Legal notice License