> ## Documentation Index
> Fetch the complete documentation index at: https://wb-21fd5541-update-reference-docs-40.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Trace generator functions

> Track sync and async generator functions with W&B Weave tracing

W\&B Weave supports tracing both sync and async generator functions, including deeply nested patterns. This page shows you how to decorate generator functions with `@weave.op` so that Weave captures their inputs, yielded outputs, and the full hierarchy of nested calls. Use this when you have streaming or lazily evaluated code paths whose outputs you want to inspect in the Weave UI alongside your other traces.

<Warning>
  Because generators yield values lazily, Weave logs outputs only when you fully consume the generator (for example, when you convert it to a list).
  To ensure Weave captures outputs in the trace, fully consume the generator (for example, with `list()`).
</Warning>

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from typing import Generator
    import weave

    weave.init("my-project")

    # This function uses a sync generator.
    # Weave will trace the Call and its input (`x`),
    # but output values are only captured once the generator is consumed (for example, with `list()`).
    @weave.op
    def basic_gen(x: int) -> Generator[int, None, None]:
        yield from range(x)

    # A normal sync function used within the generator pipeline.
    # Its calls are also traced independently by Weave.
    @weave.op
    def inner(x: int) -> int:
        return x + 1

    # A sync generator that calls another traced function (`inner`).
    # Each yielded value comes from a separate traced Call to `inner`.
    @weave.op
    def nested_generator(x: int) -> Generator[int, None, None]:
        for i in range(x):
            yield inner(i)

    # A generator that composes the above generator.
    # Tracing here produces a hierarchical Call tree:
    # - `deeply_nested_generator` (parent)
    #   - `nested_generator` (child)
    #     - `inner` (grandchild)
    @weave.op
    def deeply_nested_generator(x: int) -> Generator[int, None, None]:
        for i in range(x):
            for j in nested_generator(i):
                yield j

    # The generator must be *consumed* for Weave to capture outputs.
    # This is true for both sync and async generators.
    res = deeply_nested_generator(4)
    list(res)  # Triggers tracing of all nested calls and yields
    ```
  </Tab>

  <Tab title="TypeScript">
    ```plaintext theme={null}
    This feature is not available in the TypeScript SDK yet.
    ```
  </Tab>
</Tabs>

The following screenshot shows the **Traces** page with a selected trace of the preceding code. The center panel shows the trace tree for the selected trace. The trace tree shows the `deeply_nested_generator`, `nested_generator`, and `inner` Ops in the trace tree hierarchy.

<img src="https://mintcdn.com/wb-21fd5541-update-reference-docs-40/Q6tChntIBiYlAxny/weave/guides/tracking/imgs/generators.png?fit=max&auto=format&n=Q6tChntIBiYlAxny&q=85&s=169fdaa77d3cb7c1de89db0fbd198902" alt="Weave Traces page showing a selected trace tree illustrating deeply nested Ops" width="2078" height="1134" data-path="weave/guides/tracking/imgs/generators.png" />

## Consume generators

The following section explains why you must consume generators for Weave to record their outputs, and which consumption patterns work.

Weave captures generator outputs only after you fully consume the generator. Consume the generator by iterating over it (for example, with `list()`, a `for` loop, or `next()` until exhaustion). The same applies to async generators when you use `async for` or equivalent consumption.

For more information about decorating functions and methods with `@weave.op`, see [Create calls](/weave/guides/tracking/create-call).

## Accumulate yielded values into a single trace

If you want Weave to record a combined result (such as a joined string or a list) instead of the raw sequence of yielded values, use an accumulator.

You can use the `accumulator` parameter of `weave.op` to customize how yielded values are combined from generator functions, for example, to join streamed text tokens into a single string. The accumulator is a two-argument function that Weave calls once per yielded value, building up a result incrementally.

<Note>
  The `accumulator` parameter isn't available for TypeScript.
</Note>

The following example demonstrates a custom accumulator that appends each yielded value to a list, so Weave records that list as the call output after you fully consume the generator.

```python theme={null}
from typing import Generator
import weave

weave.init("your-team-name/your-project-name")

# Weave calls this after each yield. acc is None on the first call.
# The last value you return becomes the traced Op output.
def list_accumulator(acc, value):
    if acc is None:
        acc = []
    acc.append(value)
    return acc

# Set the accumulator parameter
@weave.op(accumulator=list_accumulator)
def basic_gen_with_accumulator(x: int) -> Generator[int, None, None]:
    yield from range(x)

# Iterate to completion so every yield runs and the accumulator can produce the final traced output.
result = list(basic_gen_with_accumulator(3))
print(result)
```
