Skip to content
Judgment Labs
Esc
↑↓navigate↵open⌘Jpreview
On this page

Connect your agent

Put a test run's run ID and case ID on your agent's root span, so Judgment can score the trace.

Judgment scores a case from the trace your agent produces. To know which run and case a trace belongs to, it reads two attributes from the trace’s root span:

Key Value
judgment.test.run_id The run ID.
judgment.test.case_id The case ID.

Judgment reads only these two attributes. Each case corresponds to exactly one trace, so run your agent once per case, with each run producing its own trace. If a case receives more than one trace, Judgment scores the first one to complete and ignores the rest.

Three ways to tag the root span

All three approaches are valid. Choose whichever fits your agent runtime and use case.

1. Set the attributes yourself

This is the simplest instrumentation, and needs no Judgment helper. With plain OpenTelemetry, call span.set_attribute() / span.setAttribute() on your root span with the two keys. With judgeval, call Tracer.set_attributes() / Tracer.setAttributes() while the root span is the current span.

@Tracer.observe(span_type="agent")
def support_agent(case_input, run_id, case_id):
    Tracer.set_attributes({
        "judgment.test.run_id": run_id,
        "judgment.test.case_id": case_id,
    })
    ...
const supportAgent = Tracer.observe(
    async (caseInput: unknown, runId: string, caseId: string) => {
        Tracer.setAttributes({
            "judgment.test.run_id": runId,
            "judgment.test.case_id": caseId,
        });
        // ...
    },
);

2. Wrap the agent call (helper)

Instead of setting the attributes directly, you can wrap the call with Tracer.test_case() (Python) or Tracer.testCase() (TypeScript). Your agent’s entry point does not change.

from judgeval import Tracer

with Tracer.test_case(run_id, case_id):
    support_agent(case_input)
import { Tracer } from "judgeval";

await Tracer.testCase(runId, caseId, () => supportAgent(caseInput));

3. Send them in an HTTP header

When you call an agent that is already deployed, send the IDs as W3C baggage on the request:

baggage: judgment.test.run_id=<run_id>,judgment.test.case_id=<case_id>

Each case in a started run includes this header in its headers field, so you can pass it through unchanged:

for case in run["cases"]:
    httpx.post(agent_url, json=case["input"], headers=case["headers"])

Your server restores the baggage at its entry point, before any span starts. Wrap the handler in judgeval’s Tracer.continue_trace() / Tracer.continueTrace(): judgeval copies Judgment baggage onto every span it starts, the root included. This is the same pattern as distributed tracing. With another OpenTelemetry SDK, extract the baggage and set the two attributes on your root span yourself.

with Tracer.continue_trace(request.headers):
    result = support_agent(payload)
await Tracer.continueTrace(req.headers, () => supportAgent(payload));

Common issues

  • Send only baggage. Do not send a traceparent from a span that Judgment never receives, such as one exported to another vendor. The agent’s top-level span would then reference a parent that never arrives, so the case would have no root span and would never be scored.
  • Use the test suite’s project. The trace must be sent to the same Judgment project as the test suite.

Was this page helpful?