# Task

A piece of work the agent is doing, with each search, read or edit listed under it as it happens.

Source: https://suiss.app/ui/docs/ai/task

**React**

**Example**

```tsx
import { CheckCircleIcon } from "@phosphor-icons/react"
import { Bubble, BubbleContent } from "@/components/ui/bubble"
import { Message, MessageContent } from "@/components/ui/message"
import {
  Trace,
  TraceCollapsible,
  TraceCollapsibleContent,
  TraceCollapsibleTrigger,
  TraceIcon,
  TraceLine,
  TraceTitle,
} from "@/components/ui/trace"

const tasks = [
  {
    title: "Found the project files",
    steps: [
      "Searched for generateMetadata",
      "Read app/layout.tsx",
      "Read app/page.tsx",
    ],
  },
  {
    title: "Updated the page metadata",
    steps: ["Edited app/layout.tsx", "Edited app/page.tsx"],
  },
]

export default function TaskDemo() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4 py-6 text-sm">
      <Message align="end">
        <MessageContent>
          <Bubble align="end" variant="muted">
            <BubbleContent>
              Add Open Graph metadata to the home page.
            </BubbleContent>
          </Bubble>
        </MessageContent>
      </Message>
      <Message>
        <MessageContent className="gap-4">
          <Trace>
            {tasks.map((task, index) => (
              <TraceCollapsible
                key={task.title}
                defaultOpen={index === tasks.length - 1}
              >
                <TraceCollapsibleTrigger>
                  <TraceLine>
                    <TraceIcon>
                      <CheckCircleIcon />
                    </TraceIcon>
                    <TraceTitle>{task.title}</TraceTitle>
                  </TraceLine>
                </TraceCollapsibleTrigger>
                <TraceCollapsibleContent>
                  <Trace>
                    {task.steps.map((step) => (
                      <TraceLine key={step}>
                        <TraceTitle>{step}</TraceTitle>
                      </TraceLine>
                    ))}
                  </Trace>
                </TraceCollapsibleContent>
              </TraceCollapsible>
            ))}
          </Trace>
          <p>
            Added Open Graph defaults to app/layout.tsx and a title, description
            and image for the home page in app/page.tsx.
          </p>
        </MessageContent>
      </Message>
    </div>
  )
}
```

Task is a piece of work the agent is doing, such as finding the project files or updating a page. Each step, like a search, a read or an edit, appears under the task when the agent takes it.

It is built with [Trace](https://suiss.app/ui/docs/components/trace): a `TraceCollapsible` for each task and a nested `Trace` for its steps.

Use [Plan](https://suiss.app/ui/docs/ai/plan) when the agent decides the steps before it starts. Use Task when the steps come from the work itself, and the agent only knows the next one once it has taken the last.

| | Plan | Task |
| --- | --- | --- |
| Steps | Every step, from the start | Each step, once the agent takes it |
| Pending steps | Yes, waiting their turn | None |
| Title | The goal, with progress: "2 of 4 done" | What the agent is doing, then what it did |
| Per reply | One plan | One or more tasks, each closing when it is done |

## Installation

Task is built with [Trace](https://suiss.app/ui/docs/components/trace).

```bash title="Terminal"
npx shadcn@latest add @esuiss/trace
```

Or use the [suiss/ui CLI](https://suiss.app/ui/docs/cli):

```bash title="Terminal"
npx @esuiss/ui@latest add trace
```

## Usage

```tsx
import {
  Trace,
  TraceCollapsible,
  TraceCollapsibleContent,
  TraceCollapsibleTrigger,
  TraceIcon,
  TraceLine,
  TraceTitle,
} from "@/components/ui/trace"
```

```tsx
<Trace>
  <TraceCollapsible defaultOpen>
    <TraceCollapsibleTrigger>
      <TraceLine>
        <TraceTitle>Found the project files</TraceTitle>
      </TraceLine>
    </TraceCollapsibleTrigger>
    <TraceCollapsibleContent>
      <Trace>
        <TraceLine>
          <TraceIcon>
            <SearchIcon />
          </TraceIcon>
          <TraceTitle>Searched for app/page.tsx</TraceTitle>
        </TraceLine>
        <a href="/files/app/page.tsx">
          <TraceLine>
            <TraceIcon>
              <FileTextIcon />
            </TraceIcon>
            <TraceTitle>Read app/page.tsx</TraceTitle>
          </TraceLine>
        </a>
      </Trace>
    </TraceCollapsibleContent>
  </TraceCollapsible>
</Trace>
```

### Status

Set the task's status from its steps. Write the title in the present tense while the task runs, and in the past tense once it is done.

| Steps | `status` | Title |
| --- | --- | --- |
| A step is still running | `"running"` | Updating the page metadata |
| A step failed | `"error"` | Failed to update the page metadata |
| Every step is done | none | Updated the page metadata |

Put several tasks in one `Trace`. Keep the running task open, and close each task once it is done.

## AI SDK

Stream each task as a data part with its own `id`. The AI SDK replaces a data part with the same `id`, so writing a task again with a new step updates it in place.

```ts title="app/api/chat/route.ts"
const stream = createUIMessageStream({
  execute: async ({ writer }) => {
    writer.write({ type: "data-task", id: "update", data: { title, steps } })
  },
})
```

```tsx
const tasks = message.parts.filter((part) => part.type === "data-task")
```

## API Reference

See [Trace](https://suiss.app/ui/docs/components/trace#api-reference).

**React Native, SwiftUI, Jetpack Compose**

```tsx
import { CheckCircleIcon, FileTextIcon, MagnifyingGlassIcon, NotePencilIcon } from "phosphor-react-native"
import { View } from "react-native"
import { Bubble, BubbleContent } from "@/components/ui/bubble"
import { Icon } from "@/components/ui/icon"
import { Message, MessageContent } from "@/components/ui/message"
import { Text } from "@/components/ui/text"
import { Trace, TraceCollapsible, TraceCollapsibleContent, TraceCollapsibleTrigger, TraceDescription, TraceIcon, TraceLine, TraceTitle } from "@/components/ui/trace"

export function AiTaskExample() {
  return (
    <View className="w-full gap-4">
      <Message align="end">
        <MessageContent>
          <Bubble variant="muted">
            <BubbleContent>Update the page titles for the docs.</BubbleContent>
          </Bubble>
        </MessageContent>
      </Message>
      <Trace>
        <TraceCollapsible>
          <TraceCollapsibleTrigger>
            <TraceLine>
              <TraceIcon>
                <Icon as={CheckCircleIcon} />
              </TraceIcon>
              <TraceTitle>Found the project files</TraceTitle>
            </TraceLine>
          </TraceCollapsibleTrigger>
          <TraceCollapsibleContent>
            <Trace>
              <TraceLine>
                <TraceIcon>
                  <Icon as={MagnifyingGlassIcon} />
                </TraceIcon>
                <TraceTitle>Searched for generateMetadata</TraceTitle>
                <TraceDescription>6 results</TraceDescription>
              </TraceLine>
              <TraceLine>
                <TraceIcon>
                  <Icon as={FileTextIcon} />
                </TraceIcon>
                <TraceTitle>Read app/docs/layout.tsx</TraceTitle>
              </TraceLine>
            </Trace>
          </TraceCollapsibleContent>
        </TraceCollapsible>
        <TraceCollapsible defaultOpen>
          <TraceCollapsibleTrigger>
            <TraceLine>
              <TraceIcon>
                <Icon as={CheckCircleIcon} />
              </TraceIcon>
              <TraceTitle>Updated the page metadata</TraceTitle>
            </TraceLine>
          </TraceCollapsibleTrigger>
          <TraceCollapsibleContent>
            <Trace>
              <TraceLine>
                <TraceIcon>
                  <Icon as={NotePencilIcon} />
                </TraceIcon>
                <TraceTitle>Edited app/docs/[slug]/page.tsx</TraceTitle>
                <TraceDescription>+8 −3</TraceDescription>
              </TraceLine>
              <TraceLine>
                <TraceIcon>
                  <Icon as={NotePencilIcon} />
                </TraceIcon>
                <TraceTitle>Edited app/docs/layout.tsx</TraceTitle>
                <TraceDescription>+2 −1</TraceDescription>
              </TraceLine>
            </Trace>
          </TraceCollapsibleContent>
        </TraceCollapsible>
      </Trace>
      <Text>Each docs page now builds its title from the page name.</Text>
    </View>
  )
}
```

```swift
import EsuissUI
import PhosphorSwift
import SwiftUI

struct TaskExample: View {
  var body: some View {
    VStack(alignment: .leading, spacing: 16) {
      Message(align: .end) {
        MessageContent {
          Bubble(variant: .muted, align: .end) { BubbleContent("Update the page titles for the docs.") }
        }
      }
      Trace {
        TraceCollapsible {
          TraceCollapsibleTrigger {
            TraceLine {
              TraceIcon { Ph.checkCircle.regular }
              TraceTitle(verbatim: "Found the project files")
            }
          }
          TraceCollapsibleContent {
            Trace {
              TraceLine {
                TraceIcon { Ph.magnifyingGlass.regular }
                TraceTitle(verbatim: "Searched for generateMetadata")
                TraceDescription(verbatim: "6 results")
              }
              TraceLine {
                TraceIcon { Ph.fileText.regular }
                TraceTitle(verbatim: "Read app/docs/layout.tsx")
              }
            }
          }
        }
        TraceCollapsible(initiallyExpanded: true) {
          TraceCollapsibleTrigger {
            TraceLine {
              TraceIcon { Ph.checkCircle.regular }
              TraceTitle(verbatim: "Updated the page metadata")
            }
          }
          TraceCollapsibleContent {
            Trace {
              TraceLine {
                TraceIcon { Ph.notePencil.regular }
                TraceTitle(verbatim: "Edited app/docs/[slug]/page.tsx")
                TraceDescription(verbatim: "+8 −3")
              }
              TraceLine {
                TraceIcon { Ph.notePencil.regular }
                TraceTitle(verbatim: "Edited app/docs/layout.tsx")
                TraceDescription(verbatim: "+2 −1")
              }
            }
          }
        }
      }
      Text("Each docs page now builds its title from the page name.").textStyle(.base).foregroundStyle(EsuissColor.foreground)
    }
  }
}
```

```kotlin
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.adamglin.PhosphorIcons
import com.adamglin.phosphoricons.Regular
import com.adamglin.phosphoricons.regular.CheckCircle
import com.adamglin.phosphoricons.regular.FileText
import com.adamglin.phosphoricons.regular.MagnifyingGlass
import com.adamglin.phosphoricons.regular.NotePencil
import com.esuiss.ui.components.Bubble
import com.esuiss.ui.components.BubbleContent
import com.esuiss.ui.components.BubbleVariant
import com.esuiss.ui.components.Icon
import com.esuiss.ui.components.Message
import com.esuiss.ui.components.MessageAlign
import com.esuiss.ui.components.MessageContent
import com.esuiss.ui.components.Text
import com.esuiss.ui.components.Trace
import com.esuiss.ui.components.TraceCollapsible
import com.esuiss.ui.components.TraceCollapsibleContent
import com.esuiss.ui.components.TraceCollapsibleTrigger
import com.esuiss.ui.components.TraceDescription
import com.esuiss.ui.components.TraceIcon
import com.esuiss.ui.components.TraceLine
import com.esuiss.ui.components.TraceTitle

@Composable
fun TaskAIDefault() {
    Column(Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(16.dp)) {
        Message(Modifier.fillMaxWidth(), align = MessageAlign.End) {
            MessageContent {
                Bubble(variant = BubbleVariant.Muted) { BubbleContent("Update the page titles for the docs.") }
            }
        }
        Trace {
            TraceCollapsible {
                TraceCollapsibleTrigger {
                    TraceLine {
                        TraceIcon { Icon(PhosphorIcons.Regular.CheckCircle, contentDescription = null) }
                        TraceTitle("Found the project files")
                    }
                }
                TraceCollapsibleContent {
                Trace {
                    TraceLine {
                        TraceIcon { Icon(PhosphorIcons.Regular.MagnifyingGlass, contentDescription = null) }
                        TraceTitle("Searched for generateMetadata")
                        TraceDescription("6 results")
                    }
                    TraceLine {
                        TraceIcon { Icon(PhosphorIcons.Regular.FileText, contentDescription = null) }
                        TraceTitle("Read app/docs/layout.tsx")
                    }
                }
                }
            }
            TraceCollapsible(initiallyExpanded = true) {
                TraceCollapsibleTrigger {
                    TraceLine {
                        TraceIcon { Icon(PhosphorIcons.Regular.CheckCircle, contentDescription = null) }
                        TraceTitle("Updated the page metadata")
                    }
                }
                TraceCollapsibleContent {
                Trace {
                    TraceLine {
                        TraceIcon { Icon(PhosphorIcons.Regular.NotePencil, contentDescription = null) }
                        TraceTitle("Edited app/docs/[slug]/page.tsx")
                        TraceDescription("+8 −3")
                    }
                    TraceLine {
                        TraceIcon { Icon(PhosphorIcons.Regular.NotePencil, contentDescription = null) }
                        TraceTitle("Edited app/docs/layout.tsx")
                        TraceDescription("+2 −1")
                    }
                }
                }
            }
        }
        Text("Each docs page now builds its title from the page name.")
    }
}
```

Task on mobile is built from the same parts as on the web: [Trace](https://suiss.app/ui/docs/components/trace), [Message](https://suiss.app/ui/docs/components/message), [Bubble](https://suiss.app/ui/docs/components/bubble). The example above is a static demo; connect it to your agent by rendering the same parts from your messages.

## Installation

**React Native**

```bash title="Terminal"
npx @esuiss/ui@latest add trace message bubble
```

**SwiftUI**

```bash title="Terminal"
npx @esuiss/ui@latest add trace message bubble --platform swift
```

**Jetpack Compose**

```bash title="Terminal"
npx @esuiss/ui@latest add trace message bubble --platform kotlin
```

## API Reference

See [Trace](https://suiss.app/ui/docs/components/trace), [Message](https://suiss.app/ui/docs/components/message), [Bubble](https://suiss.app/ui/docs/components/bubble).

