diff --git a/docs/design/playground-workspace/README.md b/docs/design/playground-workspace/README.md
new file mode 100644
index 00000000000..c486680fe09
--- /dev/null
+++ b/docs/design/playground-workspace/README.md
@@ -0,0 +1,24 @@
+# Playground workspace discussion
+
+> Draft for founder and frontend review. No implementation or scope approval is implied.
+
+Date: 2026-09-11.
+
+[Explore the interactive mockup](https://agenta-playground-workspace-concept.mahmoud-637.workers.dev) or read its [walkthrough and source notes](mockup/README.md).
+
+The proposal turns the agent playground into one or two panes with movable tabs. A conversation, file, explorer, or application can occupy either pane.
+
+Read [the product requirements document](prd.md) for the intended experience, then [the initial request for comments](rfc.md) for the architecture and tradeoffs. Both are deliberately high level. There is no implementation schedule or final interface contract.
+
+Related: [PR #6529: workspace-backed internal HTML apps](https://github.com/Agenta-AI/agenta/pull/6529). That proposal covers executing HTML and granting file access. This proposal covers presenting those apps alongside conversations and files.
+
+Terms used in these documents:
+
+- A resource is an underlying session, file, application, or remote computer.
+- A tab is an open view of a resource.
+- A pane holds ordered tabs and displays its selected tab.
+- A workspace stores the panes, open tabs, and keyboard focus for an agent's playground.
+- A runtime is a live client object, such as a chat connection, whose lifetime can outlast its React view.
+- A sandbox is the isolated environment where an agent runs tools or applications.
+
+Status: initial discussion drafts. The founder requested the split-pane direction and the candidate content types. The proposed first scope, lifecycle policies, and library preference are agent suggestions awaiting review.
diff --git a/docs/design/playground-workspace/mockup/README.md b/docs/design/playground-workspace/mockup/README.md
new file mode 100644
index 00000000000..1fe530d8e28
--- /dev/null
+++ b/docs/design/playground-workspace/mockup/README.md
@@ -0,0 +1,54 @@
+# Interactive playground concept
+
+[Open the Cloudflare preview](https://agenta-playground-workspace-concept.mahmoud-637.workers.dev).
+
+This desktop mockup illustrates the [PRD](../prd.md) and [RFC](../rfc.md). It uses local sample data and makes no agent, mounts, or remote-desktop API calls. Website and computer tabs are explicit placeholders. The Kanban example demonstrates the relationship to [#6529](https://github.com/Agenta-AI/agenta/pull/6529); it does not implement that proposal's HTML execution or permission bridge.
+
+## Try the idea
+
+1. Use the three scenario buttons to see a conversation beside a file, an app, or another conversation.
+2. Type a draft, then drag its tab into the other pane or use the pane's move button. The draft stays with the session. Dropping before another tab also changes order.
+3. Resize the divider with the pointer or focus it and press an arrow key. Switch to one pane to bring all open tabs together.
+4. Click a file card in the conversation. An already-open file receives focus; a new one opens in the other pane.
+5. Open the app scenario and move a board card. Select Files and expand `board.json` to see the same example data.
+6. Use the plus button to open another kind of tab, and the close button to close the selected tab. Reset restores the initial example.
+
+The layout, conversation drafts, example messages, and board data persist in this browser's local storage. The sidebar is visual context. On small screens the split workspace scrolls horizontally; the proposed mobile pane switcher is not implemented here.
+
+## Component reuse
+
+The mockup imports the repository's actual Button, Tabs, and SplitPane source from `web/packages/agenta-ui/src/components/ui/`. It also imports Agenta's generated theme variables, control scale, and shadcn token mapping. No copies of those components are maintained here.
+
+Relative source imports are deliberate for this standalone concept. They avoid loading the application's provider stack and require running the mockup inside a complete repository checkout. This is not the proposed production package structure.
+
+The content views and local interaction state are specific to the mockup. Native drag-and-drop illustrates tab placement; the move button supplies a keyboard-accessible alternative. Production runtime ownership, streaming, permissions, and complete accessibility remain subjects of the RFC.
+
+## Build and deploy
+
+From this directory, with Node.js 20 or newer:
+
+```sh
+npm ci --include=dev
+npx tsc --noEmit
+npm run build
+```
+
+The standalone dependency lock is local to this directory. A root application install is not required. Vite deduplicates component dependencies against this host; TypeScript uses local dependency paths for the same reason.
+
+With Cloudflare credentials supplied securely through the environment:
+
+```sh
+npx wrangler@4.72.0 deploy
+```
+
+The Worker serves static assets only. No credentials belong in the source or built assets.
+
+## Verification
+
+Built the static bundle and passed TypeScript checking. Tested the hosted URL with headless Chromium: tab movement by button and drag, draft preservation across move/collapse/reload, keyboard divider resizing, adding and closing tabs, and board data reflected in Files. Inspected screenshots in light and dark themes. No browser JavaScript errors appeared in the exercised flows.
+
+This verifies the concept's local interactions, not production chat performance or backend behavior.
+
+
+
+
diff --git a/docs/design/playground-workspace/mockup/index.html b/docs/design/playground-workspace/mockup/index.html
new file mode 100644
index 00000000000..92972fafb0e
--- /dev/null
+++ b/docs/design/playground-workspace/mockup/index.html
@@ -0,0 +1,12 @@
+
+
+
Plan the launch. Build the things you need along the way.
+
+
+
+ {settings && (
+
+ Agent configuration
+
+ Model: example model · Instructions: help prepare a product
+ launch.
+
+
+ Configuration stays outside the workspace in this concept.
+
+
+
+ )}
+
+
+ ONE WORKSPACE, DIFFERENT VIEWS
+
Your conversation, with your work beside it.
+
+ Open a file, compare sessions, or use an app. Every tab can live
+ on either side.
+
+ {tab.id === "research"
+ ? "What should we learn before the launch?"
+ : child
+ ? "Research the audience for our launch."
+ : "Help me prepare the launch. Put together a short brief and a board to track the work."}
+
+ {tab.id === "research"
+ ? "I would start with three questions for our first users."
+ : child
+ ? "I reviewed the example audience notes. Here are the themes to bring back to the parent conversation."
+ : "I’ve prepared a launch brief and a small board. We can refine the message here while keeping the work in view."}
+
+ {tab.id === "research" ? (
+
+
What work do they repeat every week?
+
Where do they need to stay in control?
+
What would make a first session useful?
+
+ ) : (
+ <>
+
+
+
+ >
+ )}
+
+ {child
+ ? "This view represents one child call, not a new independent session."
+ : "What would you like to adjust first?"}
+
+
+ Card changes are shared with board.json in the Files tab.
+
+
+ Local example only. Running real HTML and granting file access is
+ the separate proposal in{" "}
+
+ #6529
+
+ .
+
+
+ );
+ return (
+
+
+
+ {tab.kind === "computer"
+ ? "The agent’s computer"
+ : "A website beside your work"}
+
+
+ {tab.kind === "computer"
+ ? "A future remote desktop view could live in this tab. No computer is connected in this mockup."
+ : "An embeddable website could live in this tab. This example does not load an external website."}
+
+ Content placeholder
+
Try moving this tab to the other pane.
+
+ );
+ }
+}
+createRoot(document.getElementById("root")!).render();
diff --git a/docs/design/playground-workspace/mockup/src/style.css b/docs/design/playground-workspace/mockup/src/style.css
new file mode 100644
index 00000000000..4a7cc49d5be
--- /dev/null
+++ b/docs/design/playground-workspace/mockup/src/style.css
@@ -0,0 +1,889 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+:root {
+ font-family:
+ Inter,
+ -apple-system,
+ BlinkMacSystemFont,
+ "Segoe UI",
+ sans-serif;
+ color: var(--ag-colorText);
+ background: var(--ag-colorBgContainer);
+ font-size: 13px;
+}
+* {
+ box-sizing: border-box;
+}
+body {
+ margin: 0;
+}
+button,
+a,
+textarea {
+ -webkit-tap-highlight-color: transparent;
+}
+button {
+ font: inherit;
+}
+button svg {
+ width: 15px;
+ height: 15px;
+}
+a {
+ color: inherit;
+}
+h1,
+h2,
+h3,
+p {
+ margin: 0;
+}
+button:focus-visible,
+a:focus-visible,
+textarea:focus-visible {
+ outline: 2px solid var(--ag-colorPrimary);
+ outline-offset: 3px;
+}
+.app {
+ display: flex;
+ height: 100dvh;
+ min-height: 680px;
+}
+.sidebar {
+ width: 210px;
+ flex-shrink: 0;
+ background: var(--ag-colorBgLayout);
+ border-right: 1px solid var(--ag-colorBorderSecondary);
+ padding: 24px 14px 12px;
+ display: flex;
+ flex-direction: column;
+}
+.brand {
+ font-size: 27px;
+ font-weight: 650;
+ letter-spacing: -1.3px;
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ padding: 0 10px 26px;
+}
+.brandmark {
+ font-family: Georgia, serif;
+ font-size: 36px;
+ line-height: 28px;
+}
+.workspace-name {
+ padding: 11px 10px;
+ margin-bottom: 20px;
+ border: 1px solid var(--ag-colorBorderSecondary);
+ border-radius: 8px;
+ font-size: 12px;
+}
+.workspace-name span {
+ float: right;
+}
+.navitem {
+ padding: 9px 12px;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 4px;
+ color: var(--ag-colorTextSecondary);
+ border-radius: 7px;
+}
+.selected {
+ background: var(--ag-colorFillSecondary);
+ color: var(--ag-colorText);
+}
+.count {
+ margin-left: auto;
+ font-size: 11px;
+ color: var(--ag-colorTextTertiary);
+}
+.navlabel {
+ font-size: 10px;
+ letter-spacing: 1px;
+ color: var(--ag-colorTextTertiary);
+ margin: 29px 10px 12px;
+}
+.agent {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px;
+ border-radius: 7px;
+ font-size: 11px;
+}
+.avatar {
+ height: 42px;
+ width: 42px;
+ border-radius: 11px;
+ background: var(--ag-colorFillSecondary);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--ag-colorText);
+ flex-shrink: 0;
+}
+.avatar.small {
+ height: 26px;
+ width: 26px;
+ border-radius: 6px;
+}
+.avatar.tiny {
+ height: 21px;
+ width: 21px;
+ border-radius: 6px;
+}
+.gray {
+ background: var(--ag-colorFillTertiary);
+}
+.sidebar-note {
+ margin: auto 10px 25px;
+ color: var(--ag-colorTextTertiary);
+ line-height: 1.7;
+ font-size: 12px;
+}
+.profile {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ border-top: 1px solid var(--ag-colorBorderSecondary);
+ padding: 16px 6px 0;
+ font-size: 12px;
+}
+.profile > span {
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+ margin-left: auto;
+}
+main {
+ flex: 1;
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
+}
+header {
+ height: 53px;
+ flex-shrink: 0;
+ border-bottom: 1px solid var(--ag-colorBorderSecondary);
+ padding: 0 26px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.breadcrumb {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ color: var(--ag-colorTextSecondary);
+ font-size: 12px;
+}
+.breadcrumb strong {
+ font-weight: 500;
+ color: var(--ag-colorText);
+}
+.header-actions {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+}
+.header-actions a {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ font-size: 11px;
+ text-decoration: none;
+}
+.concept {
+ font-size: 10px;
+ border: 1px solid var(--ag-colorBorderSecondary);
+ padding: 4px 8px;
+ border-radius: 20px;
+ color: var(--ag-colorTextSecondary);
+}
+.agent-header {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 23px 26px 21px;
+}
+.agent-header h1 {
+ font-size: 19px;
+ font-weight: 600;
+ letter-spacing: -0.4px;
+}
+.agent-header p {
+ font-size: 12px;
+ color: var(--ag-colorTextSecondary);
+ margin-top: 4px;
+}
+.agent-header > button {
+ margin-left: auto;
+}
+.settings {
+ margin: 0 26px 10px;
+ padding: 12px;
+ background: var(--ag-colorBgLayout);
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ font-size: 11px;
+}
+.settings > button {
+ margin-left: auto;
+}
+.guide {
+ margin: 0 26px 22px;
+ padding: 19px 22px;
+ border: 1px solid var(--ag-colorBorderSecondary);
+ border-radius: 10px;
+ background: var(--ag-colorBgLayout);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 20px;
+}
+.eyebrow {
+ font-size: 9px;
+ letter-spacing: 1.25px;
+ font-weight: 650;
+ color: var(--ag-colorTextSecondary);
+}
+.guide h2 {
+ font-size: 19px;
+ font-weight: 500;
+ letter-spacing: -0.4px;
+ margin: 7px 0;
+}
+.guide p {
+ font-size: 12px;
+ color: var(--ag-colorTextSecondary);
+ line-height: 1.5;
+}
+.scenarios {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ flex-shrink: 0;
+}
+.scenarios button {
+ font-size: 11px;
+ justify-content: flex-start;
+ height: 27px;
+}
+.workspace-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin: 0 26px 8px;
+ font-size: 12px;
+}
+.workspace-toolbar > div {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+}
+.workspace-toolbar button {
+ font-size: 12px;
+}
+.dot {
+ display: inline-block;
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: var(--ag-colorSuccess);
+}
+.agent .dot {
+ margin-left: auto;
+}
+.muted {
+ color: var(--ag-colorTextSecondary);
+}
+.workspace-frame {
+ flex: 1;
+ min-height: 0;
+ margin: 0 26px;
+ border: 1px solid var(--ag-colorBorderSecondary);
+ border-radius: 10px;
+ overflow: hidden;
+}
+.pane {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ min-width: 0;
+}
+.pane-top {
+ height: 32px;
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 10px 0 16px;
+ border-bottom: 1px solid var(--ag-colorBorderSecondary);
+ background: var(--ag-colorBgLayout);
+ position: relative;
+}
+.pane-top > span {
+ font-size: 9px;
+ letter-spacing: 0.8px;
+ color: var(--ag-colorTextTertiary);
+}
+.pane-top b {
+ letter-spacing: 0;
+ font-weight: 400;
+ margin-left: 8px;
+ color: var(--ag-colorTextSecondary);
+}
+.focused > .pane-top {
+ box-shadow: inset 0 2px 0 var(--ag-colorPrimary);
+}
+.pane-top > div {
+ display: flex;
+ gap: 2px;
+}
+.pane-tabs {
+ flex: 1;
+ min-height: 0;
+}
+.tab-scroll {
+ overflow: auto;
+ flex-shrink: 0;
+ scrollbar-width: thin;
+}
+.tab-scroll [role="tab"] {
+ font-size: 12px;
+ padding-top: 12px;
+ padding-bottom: 12px;
+}
+.tab-body {
+ flex: 1;
+ min-height: 0;
+ overflow: auto;
+ margin: 0;
+}
+.tab-body[data-state="inactive"] {
+ display: none;
+}
+.conversation {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ min-height: 0;
+}
+.transcript {
+ padding: 20px 24px;
+ overflow: auto;
+ flex: 1;
+}
+.session-meta {
+ display: flex;
+ align-items: center;
+ gap: 7px;
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+ margin-bottom: 23px;
+}
+.session-meta > span:last-child {
+ margin-left: auto;
+}
+.user-message {
+ margin: 16px 0 24px 38px;
+ background: var(--ag-colorFillTertiary);
+ padding: 13px 15px;
+ border-radius: 12px 12px 3px 12px;
+ line-height: 1.7;
+ font-size: 12px;
+}
+.assistant-label {
+ display: flex;
+ gap: 7px;
+ align-items: center;
+ font-size: 11px;
+ font-weight: 600;
+ margin-bottom: 11px;
+}
+.assistant-message {
+ font-size: 12px;
+ line-height: 1.85;
+}
+.assistant-message > p {
+ margin: 12px 0;
+}
+.assistant-message ol {
+ padding-left: 20px;
+ list-style: decimal;
+}
+.resource-card {
+ display: flex;
+ width: 100%;
+ align-items: center;
+ text-align: left;
+ border: 1px solid var(--ag-colorBorderSecondary);
+ border-radius: 8px;
+ padding: 12px;
+ gap: 10px;
+ margin: 10px 0;
+ background: var(--ag-colorBgContainer);
+ transition: background 0.15s;
+}
+.resource-card:hover,
+.file-row:hover {
+ background: var(--ag-colorBgLayout);
+}
+.file-icon {
+ padding: 9px;
+ border-radius: 7px;
+ background: var(--ag-colorFillTertiary);
+ color: var(--ag-colorTextSecondary);
+}
+.resource-card strong {
+ display: block;
+ font-size: 12px;
+ font-weight: 500;
+}
+.resource-card span {
+ display: block;
+ font-size: 10px;
+ color: var(--ag-colorTextSecondary);
+ margin-top: 1px;
+}
+.resource-card > svg {
+ margin-left: auto;
+}
+.child-link {
+ display: flex;
+ gap: 6px;
+ align-items: center;
+ font-size: 10px;
+ width: 100%;
+ padding: 5px 0;
+ margin: 8px 0;
+}
+.child-link span {
+ color: var(--ag-colorSuccess);
+ margin-left: auto;
+}
+.composer-wrap {
+ padding: 8px 19px 12px;
+ flex-shrink: 0;
+}
+.composer {
+ border: 1px solid var(--ag-colorBorder);
+ border-radius: 10px;
+ box-shadow: 0 2px 8px #00000004;
+ padding: 10px 12px;
+}
+.composer textarea {
+ resize: none;
+ width: 100%;
+ height: 44px;
+ outline: none;
+ background: transparent;
+ font-size: 12px;
+ line-height: 1.5;
+}
+.composer > div {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+.composer span {
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+ display: flex;
+ gap: 5px;
+ align-items: center;
+}
+.composer-wrap small {
+ display: block;
+ text-align: center;
+ color: var(--ag-colorTextTertiary);
+ font-size: 9px;
+ margin-top: 8px;
+}
+.local-reply {
+ font-size: 11px;
+ color: var(--ag-colorTextSecondary);
+ margin-bottom: 20px;
+}
+.file-path {
+ padding: 12px 16px;
+ display: flex;
+ gap: 7px;
+ align-items: center;
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+ border-bottom: 1px solid var(--ag-colorBorderSecondary);
+}
+.file-path > span {
+ margin-left: auto;
+}
+.document article {
+ padding: 28px 32px;
+ max-width: 690px;
+ margin: auto;
+ font-size: 12px;
+ line-height: 1.85;
+}
+.document h2 {
+ font-size: 28px;
+ letter-spacing: -0.8px;
+ line-height: 1.25;
+ margin: 12px 0 18px;
+ font-weight: 550;
+}
+.document .lede {
+ color: var(--ag-colorTextSecondary);
+ font-size: 13px;
+ line-height: 1.8;
+}
+.document hr {
+ border: 0;
+ border-top: 1px solid var(--ag-colorBorderSecondary);
+ margin: 24px 0;
+}
+.document h3 {
+ font-size: 13px;
+ font-weight: 600;
+ margin: 22px 0 8px;
+}
+.document blockquote {
+ margin: 22px 0;
+ padding: 6px 14px;
+ border-left: 2px solid var(--ag-colorBorder);
+ color: var(--ag-colorTextSecondary);
+ font-style: italic;
+}
+.checkrow {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ padding: 4px 0;
+}
+.checkrow > span {
+ height: 13px;
+ width: 13px;
+ border: 1px solid var(--ag-colorBorder);
+ border-radius: 3px;
+}
+.checkrow .checked {
+ background: var(--ag-colorPrimary);
+ color: var(--ag-colorBgContainer);
+}
+.doc-foot {
+ margin-top: 30px;
+ padding-top: 14px;
+ border-top: 1px solid var(--ag-colorBorderSecondary);
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+}
+.explorer > h3,
+.explorer > p {
+ margin: 18px 20px 8px;
+}
+.explorer h3 {
+ font-size: 15px;
+}
+.file-row {
+ display: flex;
+ width: calc(100% - 40px);
+ align-items: center;
+ gap: 12px;
+ text-align: left;
+ padding: 16px 0;
+ margin: 0 20px;
+ border-bottom: 1px solid var(--ag-colorBorderSecondary);
+}
+.file-row strong,
+.file-row span {
+ display: block;
+ font-size: 12px;
+}
+.file-row span {
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+ margin-top: 4px;
+}
+.file-row > svg:last-child {
+ margin-left: auto;
+}
+.json {
+ margin: 20px;
+}
+.json pre {
+ font-size: 10px;
+ margin-top: 14px;
+}
+.board-heading {
+ padding: 26px 22px 20px;
+}
+.board-heading h2 {
+ font-size: 24px;
+ letter-spacing: -0.6px;
+ margin: 8px 0 5px;
+}
+.board-heading p {
+ color: var(--ag-colorTextSecondary);
+ font-size: 12px;
+}
+.board-columns {
+ display: flex;
+ gap: 10px;
+ padding: 0 17px;
+}
+.board-column {
+ flex: 1;
+ min-width: 0;
+ padding: 10px 7px;
+ background: var(--ag-colorBgLayout);
+ border-radius: 8px;
+ min-height: 270px;
+}
+.board-column h3 {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ font-size: 10px;
+ font-weight: 500;
+ margin-bottom: 13px;
+ white-space: nowrap;
+}
+.board-column h3 > span:last-child {
+ margin-left: auto;
+ color: var(--ag-colorTextTertiary);
+}
+.stage {
+ height: 6px;
+ width: 6px;
+ border-radius: 50%;
+ background: var(--ag-colorTextTertiary);
+}
+.stage-1 {
+ background: var(--ag-colorWarning);
+}
+.stage-2 {
+ background: var(--ag-colorSuccess);
+}
+.task {
+ border: 1px solid var(--ag-colorBorderSecondary);
+ border-radius: 7px;
+ padding: 10px 8px;
+ margin-bottom: 8px;
+ background: var(--ag-colorBgContainer);
+}
+.task > svg {
+ color: var(--ag-colorTextTertiary);
+ margin-bottom: 8px;
+}
+.task p {
+ font-size: 11px;
+ line-height: 1.5;
+ min-height: 32px;
+}
+.task button {
+ font-size: 9px;
+ margin-top: 12px;
+ padding: 0;
+ height: 20px;
+}
+.app-note {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin: 21px 22px 8px;
+ font-size: 10px;
+ color: var(--ag-colorTextSecondary);
+}
+.app-boundary {
+ margin: 12px 22px;
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+ line-height: 1.6;
+}
+.app-boundary a {
+ text-decoration: underline;
+}
+.empty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ gap: 15px;
+ height: 100%;
+ padding: 30px;
+ color: var(--ag-colorTextSecondary);
+}
+.empty h3 {
+ font-size: 18px;
+ color: var(--ag-colorText);
+}
+.empty p {
+ font-size: 12px;
+ line-height: 1.7;
+ max-width: 290px;
+}
+.empty > svg {
+ width: 30px;
+ height: 30px;
+}
+.pane-top .add-menu {
+ display: flex;
+ position: absolute;
+ right: 8px;
+ top: 29px;
+ z-index: 20;
+ flex-direction: column;
+ width: 255px;
+ padding: 7px;
+ border: 1px solid var(--ag-colorBorderSecondary);
+ box-shadow: 0 8px 30px #0002;
+ border-radius: 9px;
+ background: var(--ag-colorBgContainer);
+}
+.add-menu strong {
+ font-size: 11px;
+ padding: 8px;
+}
+.add-menu button {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ text-align: left;
+ padding: 9px 7px;
+ border-radius: 5px;
+ font-size: 12px;
+}
+.add-menu button:hover {
+ background: var(--ag-colorFillTertiary);
+}
+.add-menu button > span {
+ margin-left: auto;
+ color: var(--ag-colorTextTertiary);
+ font-size: 9px;
+}
+footer {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ justify-content: space-between;
+ height: 35px;
+ padding: 0 27px;
+ font-size: 10px;
+ color: var(--ag-colorTextTertiary);
+ flex-shrink: 0;
+}
+.status-message {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+.status-message svg {
+ color: var(--ag-colorSuccess);
+}
+@media (min-width: 1500px) {
+ .guide {
+ padding: 22px 26px;
+ }
+ .scenarios {
+ flex-direction: row;
+ }
+ .app {
+ font-size: 14px;
+ }
+}
+@media (max-width: 1000px) {
+ .sidebar {
+ width: 170px;
+ padding-left: 8px;
+ padding-right: 8px;
+ }
+ .guide {
+ margin: 0 16px 12px;
+ padding: 14px;
+ align-items: flex-start;
+ }
+ .guide h2 {
+ font-size: 16px;
+ }
+ .guide p {
+ max-width: 300px;
+ }
+ .workspace-frame {
+ margin: 0 16px;
+ }
+ .agent-header {
+ padding: 17px;
+ }
+ .workspace-toolbar {
+ margin-left: 16px;
+ margin-right: 16px;
+ }
+ .document article {
+ padding: 22px;
+ }
+ .transcript {
+ padding: 16px;
+ }
+ .board-columns {
+ padding: 0 8px;
+ gap: 5px;
+ }
+ .board-column {
+ padding: 8px 5px;
+ }
+ .header-actions {
+ gap: 5px;
+ }
+}
+@media (max-width: 720px) {
+ .sidebar {
+ display: none;
+ }
+ .app {
+ min-height: 750px;
+ }
+ .guide {
+ display: block;
+ }
+ .scenarios {
+ flex-direction: row;
+ flex-wrap: wrap;
+ margin-top: 12px;
+ }
+ .agent-header p {
+ display: none;
+ }
+ .agent-header > button {
+ font-size: 11px;
+ }
+ .header-actions .concept {
+ display: none;
+ }
+ header {
+ padding: 0 15px;
+ }
+ .workspace-frame {
+ overflow: auto;
+ }
+ .workspace-frame > [data-slot="split-pane"] {
+ min-width: 600px;
+ }
+ .pane-top b {
+ display: none;
+ }
+ footer > span:last-child {
+ display: none;
+ }
+ .settings {
+ flex-wrap: wrap;
+ }
+ .document h2 {
+ font-size: 23px;
+ }
+}
diff --git a/docs/design/playground-workspace/mockup/tailwind.config.ts b/docs/design/playground-workspace/mockup/tailwind.config.ts
new file mode 100644
index 00000000000..06a7e05b0ae
--- /dev/null
+++ b/docs/design/playground-workspace/mockup/tailwind.config.ts
@@ -0,0 +1,22 @@
+import { controlScale } from "../../../../web/oss/src/styles/theme/controlScale";
+import { shadcnTokens } from "../../../../web/oss/src/styles/theme/shadcnTokens";
+export default {
+ content: [
+ "./index.html",
+ "./src/**/*.{ts,tsx}",
+ "../../../../web/packages/agenta-ui/src/components/ui/{button,tabs,split-pane}.tsx",
+ ],
+ theme: {
+ extend: {
+ ...controlScale,
+ colors: {
+ ...shadcnTokens,
+ colorBorderSecondary: "var(--ag-colorBorderSecondary)",
+ colorBorder: "var(--ag-colorBorder)",
+ colorTextTertiary: "var(--ag-colorTextTertiary)",
+ colorPrimary: "var(--ag-colorPrimary)",
+ },
+ },
+ },
+ plugins: [],
+};
diff --git a/docs/design/playground-workspace/mockup/tsconfig.json b/docs/design/playground-workspace/mockup/tsconfig.json
new file mode 100644
index 00000000000..d3a79d215d8
--- /dev/null
+++ b/docs/design/playground-workspace/mockup/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "react-jsx",
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowImportingTsExtensions": true,
+ "noEmit": true,
+ "baseUrl": ".",
+ "paths": {
+ "react": ["node_modules/@types/react"],
+ "react/*": ["node_modules/@types/react/*"],
+ "*": ["node_modules/*"]
+ }
+ },
+ "include": ["src", "vite.config.ts", "tailwind.config.ts"]
+}
diff --git a/docs/design/playground-workspace/mockup/vite.config.ts b/docs/design/playground-workspace/mockup/vite.config.ts
new file mode 100644
index 00000000000..e14c9bff8be
--- /dev/null
+++ b/docs/design/playground-workspace/mockup/vite.config.ts
@@ -0,0 +1,15 @@
+import { defineConfig } from "vite";
+export default defineConfig({
+ resolve: {
+ dedupe: [
+ "react",
+ "react-dom",
+ "@radix-ui/react-slot",
+ "@radix-ui/react-tabs",
+ "class-variance-authority",
+ "clsx",
+ "tailwind-merge",
+ ],
+ },
+ build: { outDir: "dist" },
+});
diff --git a/docs/design/playground-workspace/mockup/wrangler.jsonc b/docs/design/playground-workspace/mockup/wrangler.jsonc
new file mode 100644
index 00000000000..91b0e539eab
--- /dev/null
+++ b/docs/design/playground-workspace/mockup/wrangler.jsonc
@@ -0,0 +1,5 @@
+{
+ "name": "agenta-playground-workspace-concept",
+ "compatibility_date": "2026-09-11",
+ "assets": { "directory": "./dist" },
+}
diff --git a/docs/design/playground-workspace/prd.md b/docs/design/playground-workspace/prd.md
new file mode 100644
index 00000000000..30300a2ed27
--- /dev/null
+++ b/docs/design/playground-workspace/prd.md
@@ -0,0 +1,69 @@
+# Product requirements: playground workspace
+
+> Draft for discussion. Proposed requirements and scope need founder approval.
+
+Date: 2026-09-11. Technical companion: [initial RFC](rfc.md).
+
+## Current experience
+
+The agent playground presents conversations through session tabs or a session rail. Files appear in a dedicated side pane that follows the active conversation. Agent configuration occupies another specialized pane.
+
+A user who wants to discuss a document while viewing it, compare two conversations, or use an agent-created app needs a more flexible arrangement. The founder's requested direction is one or two panes, each containing tabs that can move between panes.
+
+## Intended experience
+
+A user can keep a conversation on the left and a document or app on the right. Either side can contain any supported tab type. The user can return to one pane without losing open work.
+
+Example: an agent creates `todo.html` and `board.json`. The user opens the HTML beside the conversation, runs the app after granting access, and moves a card. The app updates `board.json`; the agent can read that file in a later turn. Switching conversations does not retarget the app to another session's files.
+
+The execution and access steps in this example depend on [PR #6529](https://github.com/Agenta-AI/agenta/pull/6529), which remains a separate proposal. Opening an HTML tab alone must not execute its author-provided scripts.
+
+## Candidate content
+
+| Content | Intended use | Scope note |
+| --- | --- | --- |
+| Agent session | Read, send, and manage a conversation | Suggested first scope |
+| Opened file | Read a document, source, or HTML preview | Suggested first scope; editing can follow |
+| File explorer | Browse a specific drive and open files into tabs | Suggested first scope |
+| Child-agent call | Inspect a particular child execution and possibly interact | Requires stable identity and supported interaction capabilities |
+| Website or link | View an embeddable external page | Sites can restrict embedding; provide an external-open alternative |
+| Computer view | View and control the agent's remote desktop | Requires a remote desktop service and access rules |
+| Internal app | Use an app hosted within Agenta, including an HTML board | HTML execution and file access connect to #6529 |
+| Other views | A Kanban board or another structured workspace view | Extension direction, not an initial delivery commitment |
+
+## Proposed behavior
+
+1. Users can open tabs in either pane, reorder them, and move them between panes. Provide a menu action as well as dragging so moving a tab is keyboard-accessible.
+2. Each pane selects one tab independently. The focused pane receives workspace keyboard commands; visible conversations continue to show updates.
+3. Opening an already-open resource focuses its existing tab initially. Showing duplicate views of the same resource is deferred.
+4. Moving a tab preserves the resource, conversation draft, and relevant view position. It must not stop a run, resend a message, or change file access.
+5. Returning to one pane retains the tabs from both panes. The precise merge order and selected tab need design review.
+6. Closing a tab does not delete its resource. Proposed default: closing a conversation view does not stop the server run; Stop remains explicit. This differs from the current tab-close button and requires a product decision.
+7. Restore open resource references and layout after reload. A missing file, deleted session, or expired computer shows an explanation and a recovery action without preventing other tabs from opening.
+8. File and app tabs keep their original drive and path context when another conversation becomes selected. A future explorer that follows focus must clearly indicate that behavior.
+9. On narrow screens, show one pane at a time while retaining access to all open tabs. Hidden controls must not receive keyboard focus.
+
+## Proposed first scope
+
+Validate the workspace using sessions, file previews, and a file explorer. Keep agent configuration accessible through the existing build/configuration flow while deciding whether it should become a tab.
+
+The first scope does not require arbitrary nested splits, floating windows, shared layouts across users, duplicate interactive views of one session, a new file editor, or all candidate content types. Preserve existing prompt comparison, agent onboarding, and drawer behavior as the agent workspace evolves.
+
+## Success criteria
+
+- A user can discuss a document while viewing it, then compare two different sessions without navigating away.
+- Moving a streaming conversation produces no cancellation, duplicated send, lost draft, or wrong-session shortcut.
+- Opening a file from session A and selecting session B leaves that file attached to its original drive.
+- Collapsing a pane and restoring the workspace after reload retain the expected tabs.
+- A slow or failed tab does not prevent interaction with the other pane.
+- Repeatedly opening and closing views releases unused view and connection resources according to the chosen lifecycle policy.
+
+Performance targets need measurement on an agreed device and representative transcripts. No latency or memory target has been validated yet.
+
+## Decisions for review
+
+- Is one or two panes the intended limit, or should the design anticipate arbitrary splits?
+- Should configuration stay outside the tab system initially?
+- Should closing a running conversation stop it or only close its view?
+- Should the explorer stay attached to one drive or optionally follow the focused conversation?
+- Which candidate content types belong in the first delivery?
diff --git a/docs/design/playground-workspace/rfc.md b/docs/design/playground-workspace/rfc.md
new file mode 100644
index 00000000000..6d3247e9558
--- /dev/null
+++ b/docs/design/playground-workspace/rfc.md
@@ -0,0 +1,124 @@
+# Initial RFC: playground workspace architecture
+
+> Rough request for comments, not an approved technical design or implementation plan.
+
+Date: 2026-09-11. Product companion: [PRD](prd.md).
+
+## Current architecture
+
+Code observations below refer to main commit `c6b52c09f75c69e19553d9693e4892a125e397f8`. They come from source inspection, not performance profiling.
+
+The outer playground owns configuration and the build/chat arrangement. It supplies `AgentChatPanel` for agent conversations alongside older prompt and comparison surfaces.
+
+```text
+Playground
+ Agent configuration
+ AgentChatPanel
+ Session tabs or rail
+ Visited conversation views
+ Files side pane for the active session
+```
+
+The desktop session store separates history from the ordered open-session list. Both, plus the active session, are scoped by project and chat surface, normally the agent. Drawers and onboarding can supply separate scope keys. Messages use session IDs.
+
+An atom family is a cached factory that returns an atom for a key. It supports dynamic keys. The limiting assumption here is one active session per chat scope, not Jotai itself.
+
+Conversation views mount on first visit and stay mounted while hidden. Live chat instances also live outside React in a registry keyed by session ID. The desktop retains them while their session tab remains open, including across route changes. However, their callbacks still bind to conversation components.
+
+The files pane has openness state by chat scope and selection state by session. Its host supplies the active session's drive context. Hydration hooks and shortcuts also use the scope's active session. Two independently visible conversations require those assumptions to change.
+
+Source entry points:
+
+- [Playground composition](../../../web/oss/src/components/Playground/Playground.tsx).
+- [AgentChatPanel](../../../web/oss/src/components/AgentChatSlice/AgentChatPanel.tsx).
+- [Desktop session state](../../../web/oss/src/components/AgentChatSlice/state/sessions.ts).
+- [Chat runtime registry](../../../web/packages/agenta-chat/src/state/sessionChats.ts).
+- [Hydration hooks](../../../web/oss/src/components/AgentChatSlice/hooks/useSessionHydration.ts).
+- [Files pane](../../../web/packages/agenta-entity-ui/src/drive/SessionFilesPane.tsx).
+
+## Proposed ownership
+
+Introduce a workspace layer above individual content views. Keep resources independent of their screen position.
+
+| Layer | Owns | Does not own |
+| --- | --- | --- |
+| Workspace | Pane layout, tab order, selected tabs, keyboard focus | Messages, file contents, execution permissions |
+| Tab view | Presentation, scroll, selection, visibility | The underlying resource's lifetime |
+| Resource state | Session records, file data, shared document changes | Which pane displays the resource |
+| Runtime registry | Live chat and remote desktop client objects | Pane placement |
+
+Conceptually, the workspace stores a map of tab IDs to resource references, ordered tab IDs per pane, a selected tab per pane, and the focused pane. This is an illustrative model, not a final serialized schema or public API.
+
+Resource identity names the underlying session, drive/path, child execution, or app instance. Tab identity names its view. Keeping these distinct allows future duplicate views without copying their underlying data. Initially, opening the same resource should focus its existing tab.
+
+A small renderer registry maps a tab kind to a lazily loaded React view. Sessions, files, explorers, websites, computers, and apps can implement the same host expectations: title/status, visibility, focus, close handling, and recovery from missing resources. Their data and permissions remain type-specific.
+
+A conversation opening a file requests an explicit resource and a preferred destination. The workspace chooses the pane and handles existing tabs. The conversation does not directly control a special right-hand files panel.
+
+## State and commands
+
+Keep Jotai for shared workspace state and retain existing entity/query state for backend data. A small workspace atom with derived subscriptions is sufficient to explore one or two panes. Tab labels subscribe to title and status, not entire transcripts.
+
+Centralize open, select, move, close, and collapse operations. A move updates both pane lists together and preserves tab identity. It must never invoke the current close-session operation, which drops the runtime; the current close button also requests cancellation when a run is active.
+
+Replace overloaded active-session checks with separate concepts: selected tab per pane, focused pane, visible sessions, and running sessions. Commands carry their target session or tab explicitly. Two sessions can be visible while only one receives keyboard input.
+
+Use one shared resource store across the panes. Per-pane identity can use context, but isolated Jotai stores per pane would complicate shared data and moving views. Define cleanup for dynamically cached tab atoms when views close, without evicting resource state still in use.
+
+## Moving and hiding views
+
+React state belongs to a component's position in its tree. Moving a keyed view between different pane parents can recreate it. A stable key alone does not preserve it across those parents. See [React state preservation](https://react.dev/learn/preserving-and-resetting-state).
+
+Two directions are possible:
+
+| Direction | Benefit | Cost |
+| --- | --- | --- |
+| Allow remounting and restore view state | Simple component structure; views can be unloaded | Drafts, scroll, and runtime callbacks need explicit ownership |
+| Keep views in stable hosts and change placement | Preserves more component-local state | More complex layout/focus handling; embedded document behavior still needs browser testing |
+
+Provisional preference: allow native views to remount once important state can be restored. Reuse the existing chat registry, but review callback and effect ownership before relying on it for background operation. Avoid mounting two independent interactive conversation owners for one session: the current registry rebinds callbacks to the latest committing view.
+
+Choose hidden-view policies by type. A running conversation can keep its runtime while reducing rendering work. An idle transcript or file preview can be eligible for unloading. An unsaved editor must retain its document model. Remote desktops and iframes need explicit suspension or bounded retention policies. Hiding a component does not stop its effects or connections.
+
+Closing a view, disconnecting a client, and cancelling a server run must become separate operations if the PRD's proposed close behavior is accepted.
+
+## Performance and persistence
+
+Load heavy tab implementations on demand. Keep streaming messages out of layout state and keep pointer-move resize state out of persistent storage. Persist a versioned layout description after completed actions, scoped to the user, project, and agent. Do not persist credentials or temporary authenticated app URLs as resource identity.
+
+The current chat hook throttles stream-driven UI updates to 50 milliseconds. The transcript virtualization path, which renders a window of long history, is experimental and disabled by default in its state definition. Neither observation proves that two large conversations will remain responsive.
+
+Measure typing and resizing with two streaming sessions, long history, an app iframe, and repeated open/close cycles. Watch render frequency, mounted views, memory, and live connections. Set budgets from those measurements. Use separate loading and error boundaries so one tab's failure does not replace the whole workspace.
+
+## Relationship to PR #6529
+
+[PR #6529](https://github.com/Agenta-AI/agenta/pull/6529) proposes an explicit HTML Run mode and a narrow `window.arg.fs` file-access bridge. It is an open design proposal, not shipped functionality.
+
+This workspace supplies the app's tab and placement. The HTML proposal supplies execution, file-access grants, and the validated parent/iframe message protocol. Opening, moving, focusing, or restoring a tab must not implicitly grant Run access or expand its file scope. Preview remains the initial mode as proposed in #6529.
+
+Keep app resource identity, view identity, and permission grants separate. Moving a tab retains its original file context. If moving recreates an iframe, invalidate the previous instance's message handling and establish the new instance under the chosen grant policy. Grant persistence and reauthorization remain decisions for the HTML proposal; restoring layout must not silently authorize execution.
+
+The workspace can first host existing static HTML previews. It need not wait for the file bridge. Conversely, the HTML Run experiment can use the existing file surface before this workspace exists. The proposals complement each other without requiring a stacked implementation.
+
+## Implementation directions
+
+| Direction | Fit | Tradeoff |
+| --- | --- | --- |
+| Extend specialized panels | A small number of fixed content combinations | Adds special cases as tab types grow |
+| Generic one/two-pane workspace | The requested arrangement | Own tab movement, accessibility, restoration, and lifecycle policy |
+| Docking library | Arbitrary splits, floating panels, development-environment layouts | Adopt the library's layout and rendering model |
+
+Provisional preference: a generic two-pane workspace using the existing SplitPane primitive and drag-and-drop tooling. Agenta already depends on [dnd-kit](https://dndkit.com/). If arbitrary docking is intended, evaluate [Dockview](https://dockview.dev/docs/overview/introduction/) before building equivalent behavior. Its [inactive rendering policies](https://dockview.dev/docs/core/panels/rendering/) still require decisions about background work.
+
+If a library owns layout, adapt its state to persistence and commands rather than maintaining a second competing layout in Jotai. A library does not solve session identity, grants, callback ownership, or run cancellation.
+
+## Open engineering questions
+
+- Can the existing conversation hooks consume explicit visibility and focus without depending on the scope's single active session?
+- Which callbacks must move out of the conversation component before its runtime can safely outlive it?
+- Can file views consume stable drive/path references without the active session provider?
+- Which views need preserved browser document identity rather than restored React state?
+- What stable identifiers and interaction capabilities exist for child executions and remote computers?
+- Where should the workspace live so desktop changes preserve onboarding, drawers, prompt comparison, and the mobile host?
+
+A useful first experiment is moving a streaming conversation and a file preview between panes, then collapsing to one pane. Verify draft/scroll restoration, uninterrupted execution, correct shortcuts, and unchanged file identity. This would test the proposed boundaries before committing to a larger implementation.