Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sidmanale643/northstar/llms.txt

Use this file to discover all available pages before exploring further.

northstar.trace() marks the outermost boundary of a single agent invocation, creating a Run record in NorthStar. Every span, event, metric, and log call made while the trace is active is associated with that run. The function works in two forms: as a decorator (applied to a function) and as a context manager (used with with). Both forms automatically capture inputs, outputs, latency, and exceptions, and both support async functions.

Function signature

def trace(
    name: str | None = None,
    *,
    input: Any = _UNSET,
    metadata: Mapping[str, Any] | None = None,
    tags: Iterable[str] | None = None,
    capture_input: bool | None = None,
    capture_output: bool | None = None,
) -> _TraceFactory

Parameters

name
str | None
default:"None"
Display name for this run in the NorthStar dashboard. When used as a decorator and name is omitted, the wrapped function’s __name__ is used automatically.
input
Any
default:"(not set)"
Explicit input value to record for this run. When provided to the context manager form, it is stored as the user_input event. When used as a decorator, NorthStar captures the function’s arguments automatically and input is not needed.
metadata
Mapping[str, Any] | None
default:"None"
Arbitrary key-value pairs merged into the run’s metadata. Useful for routing, filtering, or annotating runs in the dashboard. Project name and environment (set in init()) are always included automatically.
tags
Iterable[str] | None
default:"None"
A list of string tags stored under metadata["tags"] on the run. Tags appear in the dashboard and can be used for filtering.
capture_input
bool | None
default:"None"
Override the global capture_inputs setting from init() for this trace only. Set to False to prevent function arguments from being recorded as user_input events.
capture_output
bool | None
default:"None"
Override the global capture_outputs setting from init() for this trace only. Set to False to prevent return values from being recorded as final_response events.

Decorator form

Apply @northstar.trace(...) above a function definition. When the function is called, a new trace run is started, arguments are captured as input, the return value is captured as output, and the run is finished and flushed when the function returns. Exceptions are recorded as errors on the run and re-raised.
import northstar

@northstar.trace("research-agent", tags=["rag"])
def run_agent(query: str) -> str:
    docs = retrieve_docs(query)
    return generate_answer(query, docs)
When name is omitted from the decorator, the function’s __name__ is used as the run name. For example, @northstar.trace() on a function called run_agent produces a run named "run_agent".

Context manager form

Use with northstar.trace(...) as trace: when you need explicit control — for example, to call trace.set_output() with a value computed at the end of a block, or to attach structured logging mid-run.
import northstar

with northstar.trace("research-agent", input={"query": query}) as trace:
    with northstar.span("retrieval"):
        docs = retrieve_docs(query)
    answer = generate_answer(query, docs)
    trace.set_output(answer)

_TraceHandle methods

Inside the with block, the context manager yields a _TraceHandle (or a silent no-op stub if the SDK is disabled). The handle exposes these methods:
set_output(output)
method
Records output as the final_response event for this run. Call this once at the end of the block to capture the agent’s answer. Respects the capture_output flag.
trace.set_output({"answer": answer, "sources": sources})
log_event(name, data)
method
Attaches a named custom event to the run. Equivalent to calling northstar.log_event() at trace scope.
trace.log_event("fallback_triggered", {"reason": "timeout"})
log_metric(name, value)
method
Records a numeric metric on the run. value must be a real number — bool is rejected.
trace.log_metric("confidence", 0.91)
log_metadata(metadata)
method
Merges metadata into the run’s metadata dictionary.
trace.log_metadata({"user_id": "u_123", "plan": "pro"})
model_call(name, *, model)
method → context manager
Opens a SpanKind.MODEL span attached directly to this run and yields a ModelSpan handle. Use this as a context manager to record LLM input messages, output messages, and token usage when you already hold a _TraceHandle reference.
with trace.model_call("answer-llm", model="gpt-4o") as llm:
    llm.record_input_messages(messages)
    response = openai_client.chat.completions.create(model="gpt-4o", messages=messages)
    llm.record_output_message(response.choices[0].message.model_dump())
    llm.record_usage(
        prompt_tokens=response.usage.prompt_tokens,
        completion_tokens=response.usage.completion_tokens,
    )

Async support

@northstar.trace() works transparently on async def functions. The trace is started before the coroutine is awaited and finished after it resolves, preserving the correct span context across await boundaries.
@northstar.trace("async-agent")
async def run_agent(query: str) -> str:
    docs = await retrieve_docs_async(query)
    return await generate_answer_async(query, docs)

Disabling input/output capture per trace

@northstar.trace("payment-agent", capture_input=False, capture_output=False)
def process_payment(card_number: str, amount: float) -> dict:
    # card_number will NOT be recorded even without redact_keys
    ...

Full example

import northstar

northstar.init(
    api_key="ns_...",
    project_id="myproject",
    project="Support Agent",
    environment="production",
)

@northstar.trace("support-agent", tags=["production"], metadata={"team": "cx"})
def handle_ticket(ticket_id: str, question: str) -> str:
    northstar.log_metadata({"ticket_id": ticket_id})
    docs = retrieve_docs(question)
    northstar.log_metric("docs_retrieved", len(docs))
    answer = generate_answer(question, docs)
    return answer

Build docs developers (and LLMs) love