---
title: "Composer panels"
description: "A composer-panel is contextual app UI above the composer. It is the only surface bound to the public composer API, so it can observe the draft, make atomic edits, see pending de…"
url: "https://sotaagents.ai/manual/developer-guide/composer-panels"
generated_by: "sotaagents-ldp"
docs_index: "https://sotaagents.ai/manual/llms.txt"
locale: "en"
---

# Composer panels

A `composer-panel` is contextual app UI above the composer. It is the only surface bound to the public composer API, so it can observe the draft, make atomic edits, see pending deferred results for its exact execution, and acquire a composer lock.

YAML

```
contributes:
  ui:
    - id: report-panel
      kind: nativeModule
      surface: composer-panel
      slot: chat.composer.panel
      module:
        entry: dist/ui/app.js
        export: ReportPanel
```

TSX

```
import { useComposer } from '@sota/core/hooks';

export function ReportPanel() {
  const value = useComposer((composer) => composer.value);
  const applyEdit = useComposer((composer) => composer.applyEdit);
  if (!value.includes('/report')) return null;
  return (
    <button type="button" onClick={() => applyEdit({
      mode: 'replace',
      content: [{ kind: 'text', text: 'Create a weekly report for ' }],
    })}>
      Use weekly report template
    </button>
  );
}
```

The slot must be exactly `chat.composer.panel`. The panel may render nothing when its app-owned condition is absent. A slash command and a panel are independent contributions.
