> ## Documentation Index
> Fetch the complete documentation index at: https://tracevell.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Trace Functions

The `@observe` decorator (Python) or `observe()` wrapper (TypeScript) is the simplest way to trace a function. It automatically:

* Creates a span when the function is called
* Names the span after the function (or a custom name you provide)
* Captures input arguments and return values
* Ends the span when the function returns
* Records exceptions if the function throws

## When to Use Observe

Use `@observe` / `observe()` when you:

* Want to trace a function call
* Want automatic input/output capture
* Want a stable span name based on the function (or an explicit name)
* Want a parent span that groups downstream work (LLM calls, tool calls, DB calls)

## Nesting Behavior

Observed functions automatically nest. If function A calls function B, and both are observed, B's span becomes a child of A's span. This happens through context propagation—Tracevell tracks the "current" span and parents new spans to it.

You can also create additional spans inside an observed function. Those spans become children of the observed function’s span.

![Trace view showing nested spans for observed function calls](https://mintcdn.com/laminarai/pKM35iraOOzRKwfP/images/nested-trace.png?fit=max\&auto=format\&n=pKM35iraOOzRKwfP\&q=85\&s=80ebd97d74f2d4fa830a850288a59b71)

Nested spans in the trace view

***

## Example

Wrap a function you own so it shows up as a parent operation with downstream spans (LLM calls, tools, etc.) nested inside it.

> [tab] TypeScript
>
> ```typescript theme={null}
> import { observe } from '@lmnr-ai/lmnr';
>
> const answerQuestion = (question: string) =>
>   observe({ name: 'answerQuestion' }, async () => {
>     const response = await openai.chat.completions.create({
>       model: 'gpt-4o-mini',
>       messages: [{ role: 'user', content: question }],
>     });
>     return response.choices[0].message.content;
>   });
>
> await answerQuestion('What is the capital of France?');
> ```
>
> See also: [`observe(options, fn, ...args)`](https://tracevell.com/docs/sdk/observe#ts-observe)

> [tab] Python
>
> ```python theme={null}
> from lmnr import observe
>
> @observe()
> def answer_question(question: str) -> str:
>     response = openai.chat.completions.create(
>         model="gpt-4o-mini",
>         messages=[{"role": "user", "content": question}],
>     )
>     return response.choices[0].message.content
>
> answer_question("What is the capital of France?")
> ```
>
> See also: [`@observe()`](https://tracevell.com/docs/sdk/observe#py-observe)

## In the Tracevell UI

* The observed function appears as a span (often the root span for the trace).
* Auto-instrumented work inside it (LLM calls, vector DB calls, etc.) appears as child spans.
* Function arguments are recorded as span input and the return value as span output (unless you disable or override recording).

If you want to trace only part of a function (or trace blocks conditionally), see [Trace Parts of Your Code](https://tracevell.com/docs/tracing/structure/manual-span-creation.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.