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

# Step Class

The `Step` class is a Python Context Manager that can be used to create steps in your chainlit app. The step is created when the context manager is entered and is updated to the client when the context manager is exited.

## Parameters

<ParamField path="name" type="str" optional>
  The name of the step. Default to the name of the decorated function.
</ParamField>

<ParamField path="type" type="Enum" default="undefined" optional>
  The type of the step, useful for monitoring and debugging.
</ParamField>

<ParamField path="elements" type="List[Element]" optional>
  Elements to attach to the step.
</ParamField>

<ParamField path="language" type="str" optional>
  Language of the output. See
  [https://react-code-blocks-rajinwonderland.vercel.app/?path=/story/codeblock--supported-languages](https://react-code-blocks-rajinwonderland.vercel.app/?path=/story/codeblock--supported-languages)
  for a list of supported languages.
</ParamField>

<ParamField path="show_input" type="Union[bool, str]" default={false} optional>
  By default only the output of the step is shown. Set this to `True` to also
  show the input. You can also set this to a language like `json` or `python` to
  syntax highlight the input.
</ParamField>

<ParamField path="default_open" type="bool" default={false} optional>
  Whether the step should render expanded by default in the UI.

  <Note>
    Since version **2.3.0**. Requires a `defaultOpen` column in the `steps` table for SQL-based data layers. See the [migration guide](/guides/migration/2.3.0).
  </Note>
</ParamField>

<ParamField path="metadata" type="Dict" optional>
  Custom metadata dictionary to attach to the step. Persisted with the step in the data layer.
</ParamField>

<ParamField path="tags" type="List[str]" optional>
  Tags to attach to the step for filtering and categorization.
</ParamField>

<ParamField path="id" type="str" optional>
  Unique identifier for the step. Auto-generated as a UUID if not provided.
</ParamField>

<ParamField path="parent_id" type="str" optional>
  ID of the parent step. Automatically resolved from the context manager nesting hierarchy if not provided.
</ParamField>

<ParamField path="icon" type="str" optional>
  Name of a Lucide icon to display instead of the default step avatar. See [https://lucide.dev/icons](https://lucide.dev/icons) for available icons.

  <Note>
    Since version **2.11.0**.
  </Note>
</ParamField>

<ParamField path="thread_id" type="str" optional>
  ID of the thread this step belongs to. Automatically resolved from the current session context if not provided.
</ParamField>

## Send a Step

```python theme={null}
import chainlit as cl

@cl.on_message
async def main():
    async with cl.Step(name="Test") as step:
        # Step is sent as soon as the context manager is entered
        step.input = "hello"
        step.output = "world"

    # Step is updated when the context manager is exited
```

## Stream the Output

```python theme={null}
from openai import AsyncOpenAI

import chainlit as cl

client = AsyncOpenAI()

@cl.on_message
async def main(msg: cl.Message):

    async with cl.Step(name="gpt4", type="llm") as step:
        step.input = msg.content

        stream = await client.chat.completions.create(
            messages=[{"role": "user", "content": msg.content}],
            stream=True,
            model="gpt-4",
            temperature=0,
        )

        async for part in stream:
            delta = part.choices[0].delta
            if delta.content:
                # Stream the output of the step
                await step.stream_token(delta.content)
```

## Nest Steps

To nest steps, simply create a step inside another step.

```python theme={null}
import chainlit as cl


@cl.on_chat_start
async def main():
    async with cl.Step(name="Parent step") as parent_step:
        parent_step.input = "Parent step input"

        async with cl.Step(name="Child step") as child_step:
            child_step.input = "Child step input"
            child_step.output = "Child step output"

        parent_step.output = "Parent step output"
```

## Update a Step

```python theme={null}
import chainlit as cl


@cl.on_chat_start
async def main():
    async with cl.Step(name="Parent step") as step:
        step.input = "Parent step input"
        step.output = "Parent step output"

    await cl.sleep(2)

    step.output = "Parent step output updated"
    await step.update()
```

## Remove a Step

```python theme={null}
import chainlit as cl


@cl.on_chat_start
async def main():
    async with cl.Step(name="Parent step") as step:
        step.input = "Parent step input"
        step.output = "Parent step output"

    await cl.sleep(2)

    await step.remove()
```
