OpenHands,
one scenario at a time.
The OpenHands app map in the Self-Healing Codebase Project. Named mini scripts show what to set up, what to do, and what should happen.
778 behavior IDs · 28 families · 844 named recipes & support steps
16 October 2026 · PR #18334 at 9a3c3a69
Canvas 1.27.1 · Agent Server 1.55.0 · automation 1.20.0
This is the map at the revision above, including its open bug notes. It does not incorporate later changes on main or claim a fresh verification run. Setup & reading guide · Download the scenario inventory
How to read the scripts & bug markers
- Given
- The starting state and prerequisites.
- Do
- Actions, followed by observations.
- Expect
- The intended application behavior.
Open a scenario to read its script. The reading outline highlights the action path; Expect gives the behavior to check. Open Exact CLI recipe & bug checks for every instruction, diagnostic, selector, placeholder and executable known-bug block. Use that original recipe for a complete replay.
Known failure A defect reproduced in the source map.
Known issueBlocked A reported issue or path awaiting its named prerequisites. A blocked check is not a reproduced failure.
Not run A check not exercised in the source map.
Mapped behavior An expected behavior; this marker does not mean it passed.
Markers describe the particular paths and notes inside a script. A script can exercise a local path and also record an issue blocked on Cloud prerequisites.
Start with an example: Create a secret · A scenario with a known bug.
No scenarios match. Try a different word or reset.
F01 First run, onboarding and sign-in
22 behaviors · Read this family’s scripts
- First-run gateF01.first-run-gateMapped behavior
- ConsentF01.telemetry-consentKnown issueBlocked
- Modal shellF01.onboarding-modalMapped behavior
- Choose agentF01.onboarding-choose-agentKnown issueBlocked
- LLM stepF01.onboarding-setup-llmMapped behavior
- Say helloF01.onboarding-say-helloMapped behavior
- Tab titleF01.document-titleMapped behavior
- PreviewF01.onboarding-previewMapped behavior
- Skip checklist boxF01.onboarding-skip-checklistMapped behavior
- PhoneF01.onboarding-phoneMapped behavior
- Error pageF01.route-error-boundaryMapped behavior
- Onboarding again with the saved endpointF01.onboarding-repeat-endpointKnown failure
- Clean upF01 · setup / cleanupSupport step
- Backend stepF01.onboarding-backend-stepMapped behavior
- ACP credentialsF01.onboarding-acp-secretsMapped behavior
- Pi and OpenCode credentialsF01.onboarding-acp-secretsMapped behavior
- Skip into the appF01.onboarding-skipMapped behavior
- Last backend removedF01.api-key-entryMapped behavior
- Skip to API-key screenF01.onboarding-skip · F01.api-key-entryMapped behavior
- ConnectF01.api-key-entryMapped behavior
- Stale key re-promptF01.api-key-entryMapped behavior
- Close on the last stepF01.onboarding-hello-closeMapped behavior
- Recommended automationF01.onboarding-recommended-automationMapped behavior
- Cloud login columnF01.onboarding-cloud-loginBlocked
- Locked Cloud first runF01.locked-cloud-first-runBlocked
- Cookie-auth redirectF01.cookie-auth-redirectBlocked
- Bootstrap spinnerF01.bootstrap-loadingNot run
Family notes & prerequisites for known issues
- Use a fresh run or
browser resetfor every first-run check, and neveronboard --skipfirst. The browser profile lives in<run>/private/browser-profile.browser resetclears only the browser, so the server keeps the consent answer (the consent modal does not return), the LLM profile and the agent kind. control-openhands loginpasses both key prompts: the onboarding backend step, and the API-key screen, where it names the backendLocalwhen Host Name is empty (after Skip and afterrestart --rotate-key, with no duplicate backend). Use it when the screen is only in the way. To check the screen itself (the disabled Connect, the wrong-key line, a chosen name), use the explicit fills above.- Inactive onboarding slides stay mounted and are translated off-screen. Plain
browser testidslists only the active slide, butcountandwaitstill find handles on the others. Assert the active step withdata-current-step, for examplebrowser wait '[data-testid=onboarding-modal][data-current-step="2"]'. Thetestid=selector cannot carry attribute filters. - Slide indices renumber. After the public backend step succeeds, "Choose your agent" becomes index
0and has no Back.previewOnboardingStepcounts phases with the backend step included, so0and1look identical on a healthy backend. - The consent modal (z-70) sits over the onboarding modal, and clicks at the screen center land on agent tiles once it closes. A forced click on
first-run-onboarding-screenselected Codex. Check backdrop non-dismissal withbrowser mouse-click 40 40, a corner outside the modal. - The say-hello default message ("Create a basic webpage…") makes the agent work for a while. Replace it with a tiny prompt to keep model cost down.
- On a local backend, Next on the LLM step also points the
defaultagent profile at the profile it just created. Activating another LLM profile does not move that pointer, and while it stays, deleting the onboarding profile answers409LLM profile is referenced by 1 agent profile(s): default.control-openhands llm preset deepseekmoves it todeepseek-flashand reportsrepointed;llm setdoes not. In the UI, editdefaultin Settings → Agents and pick the profile intestid=agent-profile-llm-selector. - On a local backend the LLM step edits an LLM profile and never reads or writes the raw LLM settings (#18218). It takes the active profile, else the one the
defaultagent profile points at (the Agent Server's backfill of an older install's raw settings), else a fresh one with the default model. It reads the profile only once the backend's health check reports it connected, so a step mounted while the Agent Server was down fills in after it comes back (verified 2026-10-12 withcontrol-openhands service stop agent-server, thenrestart). If the profiles cannot be read it showsFailed to load existing profile. Please try again.(testid=onboarding-llm-load-error) with Retry (testid=onboarding-llm-load-retry) and Next disabled. Next without changes only sendsPOST /api/profiles/<name>/activate. - The tab title prefixes a status emoji to the stored title. A generated title that already starts with an emoji therefore shows twice (
✅ ✅ Reply hello without tools | OpenHands). Right after launch the title isConversation <id prefix>until a reload picks up the generated one. - Right after Next, the ACP step reads "Checking for an existing Claude Code login…" with Next disabled. Wait for
testid=onboarding-acp-auth-detectedbefore reading the banner. The "already signed in" banner depends on the host's CLI login. On a clean CI machine the fields become required, and Next is blocked until they are filled. - Choosing an ACP agent saves
agent_kind: acpimmediately. Re-choose OpenHands before leaving, or later conversations in the run use the ACP agent. - In preview mode, Skip and Close are inert. The LLM slide shows
gpt-5.6-soleven when another model is saved, so do not read it as data loss. browser toasts --historylists every status or alert text (toasts and alert banners) seen since the page loaded, including success toasts and progress lines such asChecking your backend connection…. Read it on a page that has just loaded (or reloaded) to check that no error toast appeared. A page with a standing banner never reads[]: the app shell of a backend with no LLM lists theYour LLM isn't set up yetalert.- Known issue #16601 (
F01.telemetry-consent): Analytics consent reappears sporadically. Live prerequisite: The multi-day trigger and backend consent response when the modal returns; opted-in localStorage alone does not reproduce it. - Known issue #16526 (
F01.onboarding-choose-agent): 403 error when selecting an agent in the onboarding agent selection modal. Live prerequisite: An authenticated hosted Cloud account with the reported organization-membership mismatch during onboarding.
F02 App shell, sidebar and command menu
28 behaviors · Read this family’s scripts
- Sidebar linksF02.nav-linksMapped behavior
- Pin as homeF02.pin-as-homeMapped behavior
- Collapse and expandF02.sidebar-collapseMapped behavior
- Settings gearF02.settings-linkMapped behavior
- Conversation listF02.conversation-listMapped behavior
- Open and close the menuF02.command-menu-open-closeMapped behavior
- Every item navigatesF02.command-menu-itemsMapped behavior
- Toggle sidebarF02.command-menu-toggle-sidebarMapped behavior
- Search, empty state, keyboardF02.command-menu-searchMapped behavior
- Open in a new tabF02.command-menu-new-tabMapped behavior
- Keyboard focusF02.command-menu-focusMapped behavior
- Phone drawerF02.mobile-drawerMapped behavior
- Back chevronF02.mobile-top-barMapped behavior
- Phone command menuF02.command-menu-phoneMapped behavior
- Checklist cardF02.checklistMapped behavior
- Item linksF02.checklist-item-linksMapped behavior
- ProgressF02.checklist-progressMapped behavior
- Item previewF02.checklist-previewMapped behavior
- MinimizeF02.checklist-minimizeMapped behavior
- DismissF02.checklist-dismissMapped behavior
- Hide from settingsF02.checklist-hideMapped behavior
- All completeF02.checklist-all-completeMapped behavior
- Setup guideF02.super-admin-setup-guideBlocked
- Setup tourF02.super-admin-setup-tourBlocked
- Update tileF02.update-tileMapped behavior
- Error toastF02.error-toastsMapped behavior
- Check for errorsF02 · setup / cleanupSupport step
- RestoreF02 · setup / cleanupSupport step
- Existing conversations while collapsedF02.sidebar-collapseKnown failure
- Alert bannerF02.alert-bannerBehavior contract
- Settings 404 modalF02.settings-404-modalBehavior contract
Family notes & prerequisites for known issues
- The rail animates its width for 200 ms. A
bboxtaken right after the collapse click reads an intermediate width (about 70); measure afterbrowser reload. browser urlstraight after clicking Customize can still read/customize; desktop redirects to/mcpa moment later. Usebrowser wait-url '/mcp$'./settingsredirects to/settings/agentson desktop but shows the settings menu on phone. That redirect also marks the checklist's Customize your agent item done, so visiting Settings by any route completes it. The sidebar Customize link (/customize) does not.- The pin toggles are hidden until hover (
visibleisfalse), except a pinned row's toggle, which stays visible. They exist only on the expanded rail. - The two desktop elements share the label
Sidebar navigation, and settings pages add a secondcomplementarylandmark, sorole=complementaryis ambiguous. Useaside[data-collapsed]for the desktop rail andtestid=sidebar-mobile-drawerfor the drawer. - HeroUI tooltips (the collapsed rail and checklist previews) often stay closed on the first
browser hoverafter a navigation. Hover a neighbor first, then the target, andbrowser waitfor the tooltip. Nevercountit right away. - When collapsed, the expand chevron is
opacity-0 pointer-events-noneuntil the rail is hovered. A forced click on it lands on the logo link and does nothing; hover the logo first. - With the full list open, the command-menu panel covers the viewport center, so clicking the backdrop button by selector only works after a filter shortens the list (type
secrfirst).control-openhands browser mouse-click 1300 500hits the desktop backdrop with any list length. - The new-tab path works with
browser click ... --button middleand with--modifiers Control(orMeta). The phone drawer's backdrop has no handle;browser mouse-click 350 400clicks it. - Escape closes one layer at a time (#18044): with the command menu open over the phone drawer, the first Escape closes the menu and the second closes the drawer. Focus goes back to whatever had it when the menu opened: right after
browser goto /conversationsthat is the composer (chat-inputtakes focus on load), and on/settings/appit is<body>. - Toggle sidebar at phone width flips the stored desktop state without any visible change. Expand the rail again after returning to desktop.
- Typing does not reset the command menu's selection. The active option keeps its index, cut down to the shorter list, from the last ArrowUp/ArrowDown or hover, and a pointer resting where the list opens hovers the option under it. A term with several matches can then run a later one on Enter: after two
ArrowDownpresses, typingLLM profiles(LLM profiles and Model Router) selects Model Router. Before opening the menu for an Enter check, rest the pointer withbrowser hover 'testid=command-menu-trigger', and readaria-activedescendantbefore Enter when a term matches several items. Repro candidate, not yet filed. - The command menu's LLM profiles item uses a magnifier icon (
lucide-search, the same icon as the menu's search field). - Dismissing the checklist with its X and the App settings switch write the same browser-local flag, so either one undoes the other. Clicking Join the OpenHands Slack counts as joining and opens an external tab you must close.
- Registry access depends on the sandbox. Where the browser cannot reach
registry.npmjs.org(ERR_CERT_AUTHORITY_INVALID), the update check reportsCouldn't check for updates; that is the environment, not the product. Where it can, the badge readsUp to dateand the check saysYou're running the latest version. - Adding a custom MCP server tests the connection first and refuses an unreachable one (
Could not reach the server..., orConnection failed: McpError: Connection closedforuvx mcp-server-timehere), so the all-complete recipe uses the local stdio fixture.
F03 Home and starting work
42 behaviors · Read this family’s scripts
- No-LLM bannerF03.llm-not-configured-bannerMapped behavior
- Blocked composerF03.composer-blocked-without-llmMapped behavior
- DraftF03.draft-persistenceMapped behavior
- Entry pointsF03.home-entry-pointsMapped behavior
- `/model` on homeF03.home-model-commandMapped behavior
- Launch without a folderF03.launch-without-workspace · F03.draft-persistenceKnown issueBlocked
- Code / Automate toggleF03.launcher-mode-toggleMapped behavior
- Automate launchF03.launch-automate-modeMapped behavior
- PluginsF03.plugin-pickerKnown issueBlocked
- Plugin reaches the agentF03.launch-with-pluginKnown issueBlocked
- Creation failureF03.create-error-toastKnown issueBlocked
- Folder browserF03.folder-browserKnown issueBlocked
- Favorites and locationsF03.folder-browser-locationsMapped behavior
- Open WorkspaceF03.open-workspace-dialogMapped behavior
- Launch in a folderF03.launch-in-workspaceKnown issueBlocked
- Search, groups and emptyF03.workspace-dropdown-searchMapped behavior
- ReloadF03.selection-after-reloadMapped behavior
- Workspace modeF03.workspace-modeMapped behavior
- ManageF03.manage-workspacesKnown issueBlocked
- Recommended railF03.recommended-automations-railMapped behavior
- Responder choiceF03.recommended-responder-choiceMapped behavior
- Cloud optionF03.responder-cloud-optionMapped behavior
- Missing integrationF03.recommended-missing-integrationMapped behavior
- Already addedF03.recommended-hides-addedMapped behavior
- Activity listF03.home-automations-list · F03.home-automation-linksMapped behavior
- Row menu, Run now and CancelF03.home-row-menu · F03.cancel-in-flight-run · F03.home-automation-linksKnown failure
- TooltipF03.home-run-tooltipMapped behavior
- Run outcomesF03.home-run-outcome-healthKnown failureBlocked
- View and EditF03.home-row-menuMapped behavior
- Turn offF03.turn-off-confirmationMapped behavior
- PinF03.pinned-automations-gridMapped behavior
- Pinned menuF03.pinned-card-menuMapped behavior
- Pinned linksF03.pinned-card-linksMapped behavior
- ReorderF03.pinned-reorder-dragMapped behavior
- Backend downF03.automations-backend-downMapped behavior
- PhoneF03.phoneMapped behavior
- CleanupF03.pinned-automations-gridMapped behavior
- Implicit-launch readinessF03.composer-blocked-without-llmKnown failure
- Target across Local backendsF03.selection-after-reloadKnown failure
- Saved workspaces across Local backendsF03.workspace-dropdown-searchKnown failure
- Invalid project sub-agentF03.launch-in-workspaceKnown issueBlocked
- Open repository dialogF03.open-repository-dialogKnown issueBlocked
- Isolated workspace noticeF03.isolated-workspace-noticeBehavior contract
- Workspaces unsupportedF03.workspaces-unsupportedBehavior contract
- Recommended prompt launchF03.recommended-prompt-launchBehavior contract
- Home automations view moreF03.home-automations-view-moreBehavior contract
Family notes & prerequisites for known issues
- Once a workspace is confirmed,
open-workspace-buttonis not rendered (the preview bar replaces it): a click on it waits the full 30 s. Reopen throughhome-git-control-bar-preview, or reload. - A pick in the workspace dropdown is stored in sessionStorage at once, before Confirm or Launch, and closing the dialog with the X keeps it: a bullet that needs the earlier workspace selected must pick it again instead of relying on the last confirmation.
control-openhands workspace openandconversation start --workspacesave that folder as a standalone workspace (api GET /api/workspaceslists it underworkspaces). When another family used them first on the same stack, Add all subdirectories leaves those folders out of theworkspaceparent and the dropdown is grouped: options readworkspace, qa-f03-repoandOther, qa-f18-repo.role=option[name="qa-f03-repo"]still matches (substring), but the menu text and theworkspace-group-headercount2in the Search bullet assume F03's own fixtures only.- Folder rows navigate on a single click; there is no path field. The browser starts at the server home,
<run>/private/home, two levels below<run>. After any conversation without a workspace,<run>/private/home/workspaceexists: it shows as aworkspacerow and, after the next page load, aworkspacefavorite (folder-browser-sidebar-workspace), which is not<run>/workspace. - A workspace and its parent can share a name (
workspace); their test ids differ only by prefix (manage-workspaces-row-vsmanage-workspaces-parent-row-). chat-inputis a contenteditablediv: it stays editable when the composer is "disabled"; assert the Send button and the absence of a new conversation instead.conversation startwithout--staynavigates home and loses a picked workspace and plugins; drive the submit button as above.- Responder Continue with local setup writes an
OPENHANDS_URLsecret; delete it so F14 counts stay clean. - The rail lists about 15 cards (proven ones, then conversation launchers such as
research-brief-writer);browser testidsreports only the first few, so check a card withbrowser count 'testid=recommended-automation-rail-card-<id>'. Any automation whose name matches a card (Daily news digest) hides that card, so avoid catalog names in fixtures. - The home draft (
oh:home-prompt-draft) survives the no-LLM bullets;browser typeappends to it, sobrowser fill 'testid=chat-input' ''before typing a slash command. - Imported automations arrive disabled and home lists only enabled ones; turn them on before looking for rows. A run dispatched from home and then cancelled still leaves a
QA_F03 Pong — <date>conversation in the sidebar. - With the Agent Server stopped, a reload does not render home at all; trigger the error path before reloading, then
restart. - Deleting the last automation leaves its id in the pinned localStorage key (pruning skips an empty list); the grid still hides it.
- Pinned cards reorder only by mouse drag; there is no keyboard or menu alternative. Drive it with
browser drag <handle> --by DX,DY --steps 20;browser drag <handle> <target>reports ok but leaves the order unchanged. VITE_HOME_AUTOMATIONS_DEMO=true(build-time) swaps the home automation sections for demo data; never verify against such a build.- The Code / Automate choice is component state, not stored: every page load and every return to home starts in Code. A toggle check after a navigation must click Automate again.
- When the Agent Server is stopped, background refetches can add a generic
An error occurredtoast (#18051). ForF03.create-error-toast, retain the complete video and toast history and report any extra toast with its timing; do not waive it from the count. - The workspace combobox uses one message for an empty list and for a search with no match: both read
No workspaces yet(workspace-dropdown-empty), with + Add Workspace still below it (#18037). - Known issue #17108 (
F03.open-repository-dialog): The repository picker lists a search result for input the user has already cleared. Live prerequisite: An authenticated Cloud Git provider and a real repository search response that remains pending after clearing the input. - Known issue #16801 (
F03.launch-without-workspace): Agent starts by looking in workspace, even when started with "no workspace". Live prerequisite: A working Claude Opus agent and the original task/prompt that makes it explore the default workspace; the prompt is absent. - Known issue #16210 (
F03.plugin-picker): [Cloud Backends] Plugins not available when starting a new conversation. Live prerequisite: An authenticated Cloud organization with configured account plugins before opening New Chat > Plugins. - Known issue #15701 (
F03.launch-in-workspace): Creating Conversation toast stuck visible. Live prerequisite: The original stuck creation request/outcome sequence; the report is intermittent and gives no deterministic trigger. - Known issue #18480 (
F03.open-repository-dialog): an Azure DevOps Enterprise user belonging to several organizations can see only one organization's repositories. Live prerequisite: a real Cloud/Enterprise sign-in with two organizations and distinct repositories; the report's mocked two-organization capture is not a real-backend reproduction. - Known issue #18418 (
F03.create-error-toast,F03.launch-with-plugin): hosted runtime 1.50.1 can fail during skills/plugins setup because its packaged plugin-schema resource is missing. Live prerequisite: the affected Cloud runtime/PyInstaller image and original plugin setup plus its account. A Local 1.55.0 launch does not verify that deployment. - Known issue OpenHands/software-agent-sdk#5837 (
F03.folder-browser): case-only directory names at a page boundary can repeat the server cursor; Canvas detects the repeated cursor and the directory listing fails instead of showing all choices. Live prerequisite: a case-sensitive filesystem with enough directories to cross the real picker page boundary, including two distinct case-only names. A case-insensitive Mac volume cannot hold that fixture. - Known issue OpenHands/software-agent-sdk#5849 (
F03.folder-browser,F03.manage-workspaces): re-adding a saved workspace or removing an already-removed stale row can return500 because the registry writes even for a no-op. Live prerequisite: an owned read-only workspace registry plus the already-saved or stale picker row; changes to registry mtime/inode alone are not a Canvas failure.
F04 Conversation list and folders
41 behaviors · Read this family’s scripts
- Empty listF04.empty-stateMapped behavior
- View menuF04.view-menuMapped behavior
- Start in a workspaceF04.new-thread-pickerKnown failure
- Row opens its conversationF04.cardKnown issueBlocked
- Live statusF04.card-live-statusMapped behavior
- Group by workspaceF04.grouped-foldersKnown failure
- Collapse one folderF04.folder-collapseMapped behavior
- Collapse allF04.collapse-allMapped behavior
- New conversation in a folderF04.folder-new-conversationMapped behavior
- Folder previewF04.folder-preview-moreMapped behavior
- Reorder foldersF04.folder-reorderMapped behavior
- Load moreF04.load-moreMapped behavior
- OrganizeF04.organizeMapped behavior
- Header dividerF04.list-headerMapped behavior
- RenameF04.card-renameMapped behavior
- SortF04.sortMapped behavior
- StopF04.stopMapped behavior
- PresetsF04.presetsMapped behavior
- Threads scopeF04.thread-scopeMapped behavior
- Hide olderF04.hide-olderMapped behavior
- Automation filterF04.automation-filterMapped behavior
- Row metadataF04.metadata-togglesMapped behavior
- Hover previewF04.hover-previewMapped behavior
- PinF04.pinMapped behavior
- Pinned previewF04.pinned-preview-moreMapped behavior
- Edit tagsF04.edit-tagsMapped behavior
- Tag overflowF04.tag-overflowMapped behavior
- Remove tagsF04.edit-tags-removeMapped behavior
- Tag filterF04.tag-filterMapped behavior
- Filter chipsF04.filter-chipsMapped behavior
- Automation setup tagF04.automation-setup-tagMapped behavior
- DownloadF04.downloadMapped behavior
- Download failureF04.download-errorMapped behavior
- ArchiveF04.archiveMapped behavior
- Show archived and UnarchiveF04.show-archived-unarchiveKnown issueBlocked
- DeleteF04.deleteMapped behavior
- PhoneF04.phoneMapped behavior
- A later-page pinF04.pinKnown failure
- Fresh-browser groupingF04.grouped-foldersKnown failure
- Delete allF04.delete-allKnown issue
- Collapsed railF04.collapsed-railMapped behavior
- Cloud picker and start tasksF04.cloud-picker · F04.start-task-cardsKnown issueBlocked
- CleanupF04 · setup / cleanupSupport step
Family notes & prerequisites for known issues
- A plain
--expect-url '/conversations/'returns at once when the browser is already on a conversation page. Start creation clicks from/(browser goto /), and never navigate away before the click returns: leaving early skips the client-side metadata write, so the new conversation lands in No workspace although the server has its working directory. - Workspace grouping, pins, archives and preferences live in this browser's localStorage (
openhands-agent-server-conversation-metadata,pinned-conversations,archived-conversations,conversation-panel-preferences).browser resetloses them: archived rows reappear and every conversation moves to No workspace. - Folder test ids embed the sanitized absolute workspace path (
thread-folder-ws--tmp-...-qa-f04-repo). Select with[data-testid^="thread-folder-ws-"][data-testid$="<folder>"]or by the+button's accessible name. - Row links carry
?backend=default-local; anchor URL regexes without$. - Hover and ⋮ need the row on screen:
browser scroll '<row>'first, andbrowser hoverbefore clickingellipsis-buttonor the pin. - Escape closes the ⋮ menu and returns focus to its ⋮ button (#18044); an outside
browser mouse-clickcloses it too. If Tab has moved focus to the next row's link, that row's preview tooltip opens and takes the first Escape, so press Escape twice. Inside the phone drawer the first Escape closes the menu and the next one the drawer. - The Stop, Delete and Delete all dialogs name their buttons
cancel-buttonandconfirm-button, like the Archive and Edit tags dialogs (#17915, fixed by #18151);role=dialog >> role=button[name="..."]still works. - With the drawer open at phone width there are two
conversation-panelelements; scope withtestid=sidebar-mobile-drawer >> .... - Recent is exactly the fresh default layout (By date, Updated, all threads, old conversations shown), so a new user sees Recent checked. Active and Compact also turn on Hide old conversations: Recent plus a manual Threads → Active only reads
More options · Custom, not Active. Presets never change the hide-older cutoff. - In By workspace mode Load more often adds no visible row: later rows join existing folders behind their More button.
- By workspace never shows
No conversations foundwhile any workspace is registered: empty workspace folders stay. - Pinned rows bypass tag and automation filters and suppress the filtered empty states; unpin before asserting them.
- The page size is 20; filters, Active scope and archives apply only to loaded pages.
- The ⋮ menu offers Stop for idle and finished conversations too (they count as active); it disappears only once paused.
service stop agent-serverneedscontrol-openhands restartand abrowser reloadbefore anything else works.- The list refreshes on an interval: a row keeps
conversation-status-workingandConversation <id5>for up to about 40 s after the conversation finished. Usebrowser wait ... --timeout 60000, not an immediatecount. - Model-written titles vary from run to run; match finished conversations on a word from the prompt (
has-text=pong), never on the whole title. - Opening a conversation from the sidebar never changes its tags, also right after an automation setup conversation (one tagged
automationsetup: draft): the other conversation keeps its tags and opens as a normal chat (recipe in F07F07.open-by-url). A conversation that did get the tag loses it with Edit tags (remove-tag-automationsetup). - Known issue #17919: Delete all deletes only the loaded pages, and its dialog states that smaller count (
F04.delete-all). - Known issue #18155 (
F04.show-archived-unarchive): Missing-runtime conversations shown as Archived but never hidden, chipped, or unarchivable. Live prerequisite: A Cloud sandbox or local runtime that becomes MISSING and non-resumable; ordinary local pause remains resumable. - Known issue #17497 (
F04.card): Corrupted conversation data breaks the entire conversation history list instead of handling individual broken conversations. Live prerequisite: The original corrupted persisted conversation or a deterministic corruption fixture after model-switch failure and fork. - Known issue #17257 (
F04.start-task-cards): Cloud provisioning has no in-progress start-task cards because the list hook always returns an empty array. Live prerequisite: An authenticated Cloud backend producing an in-progress sandbox/repository start task. - Known issue #16750 (
F04.card): Conversation list does not load while automation is running. Live prerequisite: A prompt automation or native delegated task that remains running during conversation-list reload; no usable model is configured here. - Known issue #15946 (
F04.card): Show conversations hidden by active/stale agent-server leases. Live prerequisite: A copied lease-bearing persisted conversation and second owner/expired-lease state; never alter another live run's state. - Known issue OpenHands/software-agent-sdk#4987 (
F04.card): Autotitle input has broken user-message separators and emoji-list formatting; verify the resulting visible title with a real provider. Live prerequisite: A working autotitle model and captured title-generation input/output; Canvas only consumes the resulting server title. - Known issue OpenHands/software-agent-sdk#4537 (
F04.card): A native delegated task can freeze the sidebar conversation list and cause request timeouts until it ends. Live prerequisite: A working model with native TaskTool delegation holding the parent state lock during list reload. - Known issue OpenHands/software-agent-sdk#4080 (
F04.card): One unregistered persisted tool observation can make a whole conversation disappear from the list and return404. Live prerequisite: A copied persisted conversation with its original unregistered observation kind and missing tool-module registration.
F05 Composer, slash commands and plan mode
25 behaviors · Read this family’s scripts
- Type and sendF05.send-messageMapped behavior
- Draft survives navigationF05.draft-persistenceKnown issueBlocked
- Home draftF05.draft-persistenceKnown issueBlocked
- Auto-resizeF05.composer-resizeMapped behavior
- Tools menu and macrosF05.plus-menuMapped behavior
- Show dialogsF05.plus-menuMapped behavior
- Agent profile before startF05.agent-profile-switchMapped behavior
- Attach a file and an imageF05.attach-filesKnown failureKnown issueBlocked
- Size limitF05.attach-size-limitMapped behavior
- Image aloneF05.image-only-sendKnown issueBlocked
- Paste textF05.pasteMapped behavior
- Dictation failureF05.dictationBlocked
- Switch LLM profileF05.llm-profile-pickerKnown issueBlocked
- Profile identityF05.profile-identityKnown issueBlocked
- Overflow menuF05.overflow-menuKnown failureKnown issue
- Context windowF05.context-window-meterKnown issueBlocked
- Stop and resume with a queued follow-upF05.stop-resume · F05.queued-messageMapped behavior
- Slash menuF05.slash-menuMapped behavior
- `/model`F05.slash-modelMapped behavior
- `/btw`F05.slash-btwKnown issueBlocked
- `/goal`F05.slash-goalKnown issueBlocked
- `/plan` and `/code`F05.slash-plan-codeMapped behavior
- Plan cardF05.plan-previewMapped behavior
- Build shortcutF05.build-plan-shortcutMapped behavior
- `/plan <task>` and `/code <task>`F05.slash-plan-code-taskMapped behavior
- Build buttonF05.plan-previewMapped behavior
- PhoneF05.phoneMapped behavior
- Home file re-pickF05.attach-filesKnown failureKnown issueBlocked
- Unmatched failed-conversation profileF05.profile-identityKnown failureKnown issueBlocked
Family notes & prerequisites for known issues
- Always export your own
OH_VERIFY_RUN.launch --newrepoints the sharedcurrentsymlink, and another agent relying oncurrentdrove and then stopped this family's stack mid-run. If the URL jumps to a page you never opened orfetch failedappears, runcontrol-openhands statusbefore blaming the product. conversation wait <id>right after sending returns at once with the previousfinishedstatus. Useconversation wait <id> --fresh;--until runningthen a terminal wait only works for turns longer than the poll interval (aReply with onlyturn on deepseek-flash can finish first, and--until runningthen times out).- The slash menu stays open while you type a command; press Escape before Enter or Enter selects the highlighted option instead of sending.
- Conversation drafts are saved 500 ms after the last keystroke and flushed on navigation and unmount, so text typed just before leaving comes back.
- Escape closes the
+tools menu (browser count 'testid=tools-context-menu'is0) and returns focus tochat-plus-button, whether focus was on the trigger or on a menu item. A menu left open covers attachments in screenshots. Escape also closes the narrow-width "More input actions" overflow menu (browser count 'testid=chat-input-overflow-menu'is0, the trigger'saria-expandedisfalse) and returns focus to the trigger, whether focus was on the trigger, onoverflow-model-buttonor on a profile row of the open Model submenu (#18174). - After a client-side switch between conversations (a sidebar row, or a user-message branch in
F06.branch-from-here) Send keeps the previous conversation's state (Known failure, #18202; draft fix PR #18203). Switching from an empty composer to one with a saved draft restores the text next to a disabled Send; this is a race (Send came up enabled in 1 of 7 tries), so one enabled reading does not show the bug is gone. Switching from a composer with text to an empty one leaves Send enabled, and clicking it does nothing. Typing orbrowser reloadfixes it, and Enter in the field sends the restored text anyway. Readbrowser enabled 'testid=submit-button'after a reload, or after typing. - Expected: a prompt that a suggestion chip (
testid=chat-suggestions) or a+> Macros item writes into the composer enables Send at once. Known failure (reproduced 2026-10-09, #18202): on a new No workspace conversation,browser click 'testid=chat-suggestions >> text=Fix README'(orbrowser click 'testid=chat-plus-button',browser hover 'testid=macros-button',browser click 'testid=fix-readme-button') fills the field, butbrowser enabled 'testid=submit-button'isfalse(5 of 5 tries at desktop; a race at phone) until a character is typed. Both paths callsetMessageToSend, which writes the text without an input event. - Uploaded chips and thumbnails have no test ids. Their remove buttons are named
Remove <file name>(file chip) andRemove image(thumbnail), and Send, Stop and Play readSend message,StopandResume the agent task(#18033); select by those names, or by text/alt. browser uploadfeeds the hidden input directly. To drive the real path,+> Add Files and Images, usecontrol-openhands browser upload-via 'testid=add-files-and-images-button' <file>, which answers the native file chooser.- The home composer has no
interactive-chat-boxwrapper: scope its chips and thumbnails withtestid=home-chat-launcher. conversation eventsrows show a message's text and its attachment count (images: 1for the image-only message, whose text is a blank);--grep 'data:image/png;base64'searches whole events and quotes theimagecontent block inexcerpts.- A user row with
images: 1proves that the image reached the Agent Server, not the model. Only the reply proves that the model saw it. On agent-server 1.53.0 and older,deepseek/*profiles drop the image before the LLM call (F05.image-only-send). An image sent with no text then leaves deepseek-flash with an empty task. On 2026-10-08 it ranenv, read the run directory and other files on the host, and decoded the picture from the event store with PIL to answer. Pause such a conversation (control-openhands conversation pause <id>), and use the question-plus-image send for the model check. - The pill resolves the conversation's stamped profile before the user-level default, so profiles that share a model are told apart by name. The stamp lives in this browser's localStorage (
openhands-agent-server-conversation-metadata), not on the server (api GET /api/conversations/<id>has no profile name): read it withbrowser eval, notapi GET. - The
Switched to profilenotes are client-side and gone after reload; assert the pill andconversation status. /planmessages go to a separate planner conversation; the browser stays on the parent/conversations/<id>, so wait on the planner id fromconversation list.- Only the newest goal status offers
Resume(#18036): once a resumed goal has posted a newer status, the oldinterruptedrow shows no button, also after a reload. Counttestid=goal-resumeafter the resumed goal ends; while it runs the count is0anyway. - Opening the context popover logs a 404 for
/api/llm/balanceon the local backend inbrowser errors --app-only; it does not break the popover. --observetakes the verbs' selector syntax:testid=and plain CSS segments are watched by an in-page MutationObserver (observedBymutation), whilerole=,text=and other engines are polled every 20 ms (poll-20ms), which misses a state shorter than that; prefer atestid=or CSS form for anything brief.- At
narrow(320 px) the overflow menu's Model submenu opens to the right of the menu and runs off screen: each profile row starts at x about 270 with width 210 (browser bbox 'testid=chat-input-llm-profile-option-deepseek-flash',insideViewportfalse), so both names readdeepse…. Pick profiles by test id: the click lands on the strip of about 50 px that stays on screen. Known issue: #18063 (filed from the follow-up noted in #18015; the submenu also runs past the bottom edge, so the LLM Profiles link cannot be clicked atnarrow) (F05.overflow-menu). - Known issue #17788 (
F05.attach-files): Cloud attachment upload rejects valid runtime data when cached fields are empty strings. Live prerequisite: A Cloud sandbox whose cached runtime URL/key are blank while the fresh runtime lookup is already ready. - Known issue #17621 (
F05.context-window-meter): Compact context always fails after exactly 60s — client-side timeout aborts a condensation the server then completes. Live prerequisite: A real summarizing model and conversation whose condensation takes longer than 60 seconds. - Known issue #17476 (
F05.context-window-meter): Planning socket stats overwrite the main conversation's context meter. Live prerequisite: A real planning sub-conversation and main conversation with distinct nonzero usage stats. - Known issue #17429 (
F05.slash-btw): 500 error with /btw. Live prerequisite: The exact pending tool/streaming state that triggers the generator-pickle error, plus a working model for the side question. - Known issue #17271 (
F05.context-window-meter): New chat retains context/state from the previous conversation. Live prerequisite: A completed conversation with nonzero token usage before New Chat; a dummy-key run supplies no genuine context usage. - Known issue #17263 (
F05.context-window-meter): Context meter stays pinned after a successful compaction once the condenser has its own usage entry. Live prerequisite: A real successful compaction whose condenser usage remains larger than the default agent usage. - Known issue #16851 (
F05.profile-identity): wrong model is displayed when loading existing conversation. Live prerequisite: The original conversation/model-switch history and usage record showing Opus with a Fable selector; a dummy-key conversation has no usage evidence. - Known issue #16835 (
F05.context-window-meter): Agent Canvas sidebar shows "Cache Hit: 0" while backend correctly records nonzero cache_read_tokens. Live prerequisite: A working prompt-caching model/proxy and a real conversation reporting nonzero cache_read_tokens. - Known issue #16430 (
F05.attach-files): File upload does not have an indication of progress. Live prerequisite: A remote or throttled real upload that stays in flight long enough to inspect progress and composer state. - Known issue #16339 (
F05.attach-files): Agent not informed of file location for files uploaded via canvas in cloud. Live prerequisite: An authenticated Cloud upload sandbox and working model to inspect the delivered filename/path notification and read the uploaded file. - Known issue #15782 (
F05.draft-persistence): Prompt disappears when a conversation is stopped. Live prerequisite: Clarify whether prompt means unsent composer text or the already-sent history message, and capture that state before sidebar Stop. - Known issue OpenHands/software-agent-sdk#5639 (
F05.llm-profile-picker): A profile switched before the first message can be absent from token/cost statistics after its successful turn. Live prerequisite: A working model, a profile switch before the first run, and nonzero usage/cost after that turn. - Known issue OpenHands/software-agent-sdk#5627 (
F05.slash-goal): After backend restart the goal chip can remain Running while the conversation is paused, and Stop does not clear it. Live prerequisite: A working model goal loop active during graceful backend restart, then goal-status and resume readback. - Known issue OpenHands/software-agent-sdk#5523 (
F05.image-only-send): DeepSeek V4.1 Flash images can be sent to another fallback profile because its vision capability is not detected. Live prerequisite: A working DeepSeek V4.1 Flash vision profile and another fallback profile, with an image-bearing turn. - Known issue OpenHands/software-agent-sdk#5492 (
F05.slash-goal): A goal can stop as Complete when its judge replies with complete as the string false. Live prerequisite: A real goal judge response containing complete as the string false rather than a JSON boolean. - Known issue OpenHands/software-agent-sdk#5330 (
F05.slash-btw): A /btw side question can prevent reuse of the normal conversation prompt cache. Live prerequisite: A working caching provider and comparable ordinary-message versus /btw prompt/cache records. - Known issue OpenHands/software-agent-sdk#4498 (
F05.context-window-meter): Compaction can leave an orphaned tool call/result in the live history and make the next provider request fail. Live prerequisite: A real condensation splitting an action/result pair, followed by the next provider request. - Known issue OpenHands/software-agent-sdk#4382 (
F05.context-window-meter): ACP cost can miss cache/thought usage, silently become zero, or inflate after stalled/reset cost updates. Live prerequisite: An authenticated ACP provider emitting cache/thought token usage or reset/stalled cumulative cost updates. - Known issue #17239 (
F05.llm-profile-picker): The reported model/profile picker can open above the viewport with unreachable rows. A frozen-target Local check with eight LLM profiles passed on Home at 1512x720, 1440x1000, 390x844 and 320x700, and in a genuine conversation at 1512x720 and 390x844: internal scrolling and selecting the first/last profile worked. The Cloud screenshot and real ACP multi-model picker remain unverified; they need an approved Cloud session or ACP account/adapter with a multi-row model catalogue. Local profile geometry is not proof of those branches. Runbackfill-18309-settings-worker, Agent Server/SDK 1.54.0; evidence includesF05.llm-profile-picker/17239-conversation-1512x720.pngand17239-conversation-phone.png. - Known issue OpenHands/software-agent-sdk#5824 (
F05.slash-goal): resuming after a failed judge audit can show iteration 2 of a maximum of 1 and run beyond the selected goal cap. Live prerequisite: an agent/judge run whose audit fails, followed by a successful incomplete judge verdict after Resume; a controller-only test does not establish the Canvas banner outcome. - Known issue OpenHands/software-agent-sdk#5889 (
F05.attach-files): a same-name attachment upload that fails part-way can replace the previous workspace file with partial content. Live prerequisite: an owned isolated backend with a controlled mid-upload filesystem failure (the original Linux file-size limit or an equivalent bounded child-process limit), a pre-existing target and a real Canvas overwrite. Never change resource limits on a shared runtime; a normal successful upload does not verify failure atomicity. - Known issue OpenHands/software-agent-sdk#5820 (
F05.context-window-meter): manual compaction on a null/no-op condenser can return500. Verification is blocked by genuine populated usage/context metrics: idle and refused-loopback runs leaveusage=null, so neither composer nor Usage panel offers Compact context. A separate direct endpoint check returned500 but is not a Canvas reproduction. Use an existing real conversation with usage and no condenser, or an authorized successful provider run; never fabricate stats to expose the action.
F06 Agent activity: messages, events and lifecycle
35 behaviors · Read this family’s scripts
- One run that exercises the streamF06.markdown-rendering · F06.event-groups · F06.thinking · F06.events-matchKnown issueBlocked
- Expand a group and its rowsF06.event-groups · F06.thinking · F06.tool-visualizersKnown issueBlocked
- Open files from the streamF06.workspace-path-linksMapped behavior
- Markdown file previewF06.markdown-file-previewMapped behavior
- TimestampsF06.timestampsMapped behavior
- Copy a message and a code blockF06.message-copy · F06.code-block-copyMapped behavior
- Long table cellF06.markdown-renderingKnown issueBlocked
- Non-zero exit badgeF06.tool-visualizersKnown issueBlocked
- Task listF06.task-list · F06.status-indicatorMapped behavior
- Empty stateF06.empty-state-suggestionsMapped behavior
- Pending bubble and long messagesF06.pending-messages · F06.user-and-agent-messagesMapped behavior
- Browser clock aheadF06.clock-skew-sendMapped behavior
- Server lost: banner, failed send, reconnectF06.error-banner · F06.pending-messages · F06.reconnectKnown failureKnown issueBlocked
- Banner RetryF06.error-bannerMapped behavior
- Failed send survives leavingF06.failed-send-persistsMapped behavior
- Live chip, stop and resumeF06.live-activity · F06.stop-resumeKnown issueBlocked
- Reload mid-runF06.reload-mid-runKnown issueBlocked
- Older historyF06.load-older-historyKnown issueBlocked
- Scroll to bottomF06.scroll-to-bottomMapped behavior
- Confirmation mode onF06.confirmation-modeKnown issueBlocked
- Confirmation shortcutsF06.confirmation-shortcutsMapped behavior
- Branch from hereF06.branch-from-hereKnown issueBlocked
- ImagesF06.image-attachmentsMapped behavior
- Error eventsF06.error-eventsKnown issueBlocked
- Skill installed bannerF06.skill-install-bannerMapped behavior
- No LLMF06.llm-not-configured-bannerMapped behavior
- Critic (`F06.critic-result`, blocked)F06.critic-resultBlocked
- PhoneF06.phoneMapped behavior
- After each groupF06 · setup / cleanupSupport step
- Planner discovery with many childrenF06.tool-visualizersKnown failureKnown issueBlocked
- Hook eventsF06.hook-eventsBehavior contract
- Corrective nudgeF06.corrective-nudgeBehavior contract
Family notes & prerequisites for known issues
control-openhands conversation events <id>returns the last 25 events unless you pass--last N; it reads the server's 100-event pages untilNrows are in hand (pagessays how many it read,more: truethat older pages remain), so--last 500covers a 150-event conversation in two pages (total152,pages2,morefalseon the Older history conversation;--last 25there reads one page,moretrue) and--from-startreads from the oldest.--kindsand--grepfilter before--lastcounts, and pages are read until--lastmatching rows are in hand:--kinds MessageEvent --last 3is the three newest messages,--kinds MessageEvent --last 500all thirty, and--grep 'qa older 1'reachesqa older 1on the oldest page with the default--last(count11,pages2). Event texts are cut at about 160 characters.--observetakes the same selector syntax as the verbs:testid=and plain CSS segments (joined with>>) are watched by an in-page MutationObserver (observedBymutation; the Older history bullet's--observe 'testid=loading-older-events'is one), while other engines (role=,text=,nth=) are polled every 20 ms instead (not driven in this family).role=button[name="Expand"]also matches "Expand thinking" and "Expand actions"; use[exact]to target tool rows. Each click flips the row to Collapse, sonth=0walks to the next collapsed row.- Tool rows show no success icon; the only indicators are the
exit Nbadge for non-zero exits and a clock icon (status-icon) for timeouts. A single action is not grouped: it renders as a bare row withoutevent-group. - The model writes the tool titles and may append to commands (it turned
ls /missingintols ...; echo "EXIT:$?", exit 0). Ask for the command "verbatim, with nothing appended" when the exit code matters. - The agent itself may open files with
canvas_ui_control(a third action in the echo/file run). Close the file tab before proving that a path link opens it. - On Settings → Verification the Security Analyzer field (All tab) is shown only while Confirmation Mode is on: switch Confirmation Mode on first, then pick the analyzer. Check
api GET /api/settingsafter saving. - Confirmation mode with the default Security Analyzer
LLMuses ConfirmRisky(HIGH): harmless commands run without a prompt. Set the analyzer toNoneto confirm every action, and restoreLLMafterwards. The composer stays editable while waiting (status "User needed"); the buttons read Cancel / Continue. - The confirm and cancel shortcuts accept Meta or Ctrl and ignore a held key's auto-repeat; once a response is sent the listener is detached, so a second press sends nothing (#18127). Hints read
Ctrl+↩/Ctrl+⇧+⌫off Apple platforms. - Known failure, Canvas UI (#18202, reproduced 2026-10-09; draft fix PR #18203): after a user-message branch the composer holds the prefilled text but Send stays disabled (
browser enabled 'testid=submit-button'isfalse, and a click on it times out withelement is not enabled). The prefill is a saved draft thatsrc/hooks/chat/use-draft-persistence.tswrites into the field without an input event, and the composer is reused across the client-side switch, so its Send state keeps the source conversation's empty field. Editing the text, a reload, or Enter in the field (browser press Enter --selector 'testid=chat-input') all work. A draft restored by a sidebar switch behaves the same (F05 Gotchas). - Known failure, likely Agent Server: every message in a branched conversation ends with
ConversationErrorEventLLMAuthenticationError("Your LLM API key appears to be invalid or has expired."), while the source conversation keeps working (OpenHands/software-agent-sdk#5465). Do not use branches as fixtures for other checks. - "The terminal session was reset because the underlying tmux server/session disappeared" (clock
status-iconon the row) appears after aservice stop agent-server/restartcycle. Sincelaunchgives each run its own shortTMUX_TMPDIR, other runs no longer cause it. The underlying product bug is still open (OpenHands/OpenHands#17946) for plainagent-canvasinstances:bin/agent-canvas.mjs→scripts/dev-with-automation.mjspassesTMUX_TMPDIR=<state>/tmuxto the Agent Server butensureDirectoriesnever creates it (dev-safe.mjsdoes), so tmux 3.4 falls back to the shared/tmp/tmux-<uid>/openhandssocket and another instance's restart or stop kills this run's windows. The model usually reruns the command; expect an extra action. - The
ConversationErrorEventbanner is not restored after navigating away and back (or a reload); read the error from the events API instead. - After
restart, reconnection takes about 20 s without a click; clickerror-message-banner-retryto reconnect at once. The error banner does not come back after a page reload once the stack is healthy. - "Sending..." lasts about 100 to 650 ms on a local stack, too short to hover and click
chat-message-stop; that stop path is not driven here. TheF06.pending-messagesfailure path needsservice stop agent-server. browser clockinstalls a fake clock that stays with the page across reloads and client-side navigation. Install it before thegotowhose page should see it, and put it back withbrowser clock --offset-ms 0plusbrowser reload; comparebrowser eval "new Date().toISOString()"withdate -uwhen in doubt.- The pending-message queue lives in page memory, so a failed bubble survives sidebar navigation and a backend
restartbut not abrowser reloadorbrowser gotoof the conversation (src/stores/optimistic-user-message-store.ts). Leave and return through the sidebar when provingF06.failed-send-persists. The sidebar card's title is the first message or model-written: click its link by id,'a[href*="/conversations/<id>"] >> nth=0'. - Both the pending bubble and the echoed message carry
testid=user-message, socount 'testid=user-message >> has-text=...'is one too high while a failed bubble is still shown; count attempts withconversation events <id> --kinds MessageEvent(user rows:"source": "user") and the bubbles withchat-message-retry. - Local
Stopcalls the Agent Server's interrupt (Cloud pauses the sandbox instead, seepauseConversation): a command already running in the terminal is cut off, recorded asAgentErrorEvent+InterruptEvent, and after Play the model only reports the interruption. - The no-LLM banner reuses the home banner's test ids (
home-llm-not-configured-banner). It exists only in a run where no LLM was ever configured: use a separatelaunch --new, never remove the profile from the shared run. - Read the clipboard with
control-openhands browser clipboard, neverbrowser eval "navigator.clipboard.readText()". An agent bubble that contains a code block holds twocopy-to-clipboardbuttons (the code block's is hidden until hovered): scope the bubble's with>> nth=0. - Plan-mode previews (
plan-preview-*) and the BTW side messages render in this stream but are reached from the composer's mode controls; they are not mapped here. - Known issue #18117 (
F06.thinking): Inline thinking leaks into the agent chat bubble. Live prerequisite: A live model that emits a leading inline think block on a tool-call turn, plus its finalized ActionEvent. - Known issue #17559 (
F06.load-older-history): History pagination can show both an action and its observation (ready-for-dev companion to #16947). Live prerequisite: A real persisted history page boundary splitting an action/observation or ACP started/completed pair; dummy-key errors do not produce these tool pairs. - Known issue #17492 (
F06.tool-visualizers): Failed browser, glob, grep, and file editor tool calls render as successful in chat. Live prerequisite: A working model emitting failed browser, glob, grep, planning-editor and file-editor observations with is_error=true. - Known issue #17490 (
F06.tool-visualizers): Terminal commands that fail with an ordinary non-zero exit render as successful in chat. Live prerequisite: A working model producing a completed terminal command with nonzero exit_code and is_error=false. - Known issue #17161 (
F06.markdown-rendering): markdown sanitizer lets untrusted content set rel="opener" and any target on links. Live prerequisite: A real reasoning, activated-skill, tool-description or error-detail body rendered without includeStandard. The attempted skills dialog exposed public skills only and did not reach the affected chat renderer. - Known issue #17026 (
F06.thinking): agent-canvas: final-reply thinking block missing for text-only turns (reasoning_content not read for MessageEvents). Live prerequisite: A reasoning-capable live model emitting nonempty MessageEvent.llm_message.reasoning_content on a text-only turn, followed by reload. - Known issue #16842 (
F06.reconnect): A late close from a replaced WebSocket marks the active connection disconnected. Live prerequisite: A transport fixture delaying an old socket close until its replacement is open; ordinary server restart cannot select that ordering. - Known issue #16719 (
F06.live-activity): Agent status always says "thinking" even when nothing is happening. Live prerequisite: The event/status trace and deterministic stalled or errored state from the original report; its trigger is unspecified. - Known issue #16686 (
F06.error-events): LLM errors not propagated to the frontend. Live prerequisite: A Nebius credential and its rejected DeepSeek-V3 request, or the original complete emitted error fixture. - Known issue #16582 (
F06.stop-resume): After reconnect, a maximum-iteration error can fail to pause the agent through the legacy event handler. Live prerequisite: A maximum-iteration legacy error delivered after socket replacement, with a real model run reaching that limit. - Known issue #16455 (
F06.events-match): Duplicate messages from the agent in 1.12.0. Live prerequisite: The original duplicated event/stream trace or deterministic prompt and timing; the report provides no reproducible trigger. - Known issue #16341 (
F06.tool-visualizers): Code-explorer subagent frequently errors. Live prerequisite: A working model with native code-explorer delegation and the original repository task; no delegated-tool output can be generated without credentials. - Known issue #15626 (
F06.error-events): Conversation can fail with LiteLLM auth error when database server at 127.0.0.1:5432 is unreachable. Live prerequisite: The original LiteLLM proxy/database-failure event or a disposable proxy with its PostgreSQL dependency unavailable. - Known issue #15606 (
F06.reload-mid-run): When re-loading ACP conversations, messages disappear or move. Live prerequisite: An authenticated Codex ACP session emitting intermediate messages while another window reloads history. - Known issue #15527 (
F06.reconnect): Canvas briefly shows "disconnected" when coming back to an idle tab. Live prerequisite: The original custom-domain deployment, idle duration and tab-suspension/network transition; those details are missing. - Known failure OpenHands/software-agent-sdk#5635 (
F06.reconnect), reproduced 2026-10-12 atfa1f724ab573with SDK 1.54.0 and Chromium 153.0.8010.12: sandbox pause returned 204 but an already communicating session socket remained open for more than 10 seconds. A new Canvas tab received a subsequentrun:falsemarker while the original tab did not. DELETE returned 200 and GET returned 404, yet both held sockets remained open for more than 10 seconds; Canvas later redirected by metadata polling. Recipe: open an idle dummy-profile conversation and confirm its marker/socket; POST/api/conversations/prepare-for-sandbox-pause, retain the original tab for 10 seconds, open a second tab, POST a new unique user event withrun:false, then compare the two transcripts. DELETE the owned conversation and read lifecycle metadata for another 10 seconds. Use--run <run>andbrowser events --kinds websocket-created,websocket-open,websocket-close --last 100; no frame bodies or auth data are recorded. Evidence:backfill-18309-surface-rechecks/F06.reconnect/pause-delete-sockets-5635.json,pause-new-tab-5635.png,pause-stale-tab-5635.png. The expected socket shutdown/reconnect remains unchanged; polling recovery must not be mistaken for socket closure. - Known issue OpenHands/software-agent-sdk#5465 (
F06.branch-from-here): Branch from here can lose encrypted LLM credentials, so the fork fails its first turn with LLMAuthenticationError. Live prerequisite: A working cipher-backed model conversation, then fork and a successful turn on the fork. - Known issue OpenHands/software-agent-sdk#5447 (
F06.error-events): An Anthropic Claude Opus5.5 conversation can fail with400 when its next request ends in an assistant prefill. Live prerequisite: Anthropic Claude Opus5.5 credentials and a real trailing-assistant-prefill request. - Known issue OpenHands/software-agent-sdk#5354 (
F06.event-groups): A mixed valid/invalid tool batch can be split into separate assistant messages, breaking call/result pairing on the next provider request. Live prerequisite: A live model turn mixing valid, invalid and valid tool calls in one response. - Known issue OpenHands/software-agent-sdk#5225 (
F06.error-events): A provider-rejected image tool result can leave the conversation permanently failing on every resume. Live prerequisite: A real provider-rejected poisoned image tool_result in a disposable persisted history, followed by retry. - Known issue OpenHands/software-agent-sdk#5108 (
F06.tool-visualizers): The native SDK Gemini editor can report success while corrupting unrelated invalid-UTF8 bytes in the file. Live prerequisite: An Agent Server configured with the native Gemini edit tool set and a real tool edit of an invalid-UTF8 fixture; Gemini ACP uses a different external executor. - Known issue OpenHands/software-agent-sdk#5096 (
F06.tool-visualizers): The canonical agent file editor can replace a symlink instead of editing its target; Undo does not restore the link. Live prerequisite: A working model invoking canonical file-editor str_replace/insert through a real symlink, then undo. - Known issue OpenHands/software-agent-sdk#5092 (
F06.confirmation-mode): A revocation message sent while waiting for confirmation can implicitly approve the pending action. Live prerequisite: A working model proposing a real confirmation-gated marker action, then a revocation user message. - Known issue OpenHands/software-agent-sdk#5074 (
F06.tool-visualizers): After server restart a native delegated child can remain Running while the parent loses its task mapping/result. Live prerequisite: A native delegated child still running during an owned server crash and parent recovery. - Known issue OpenHands/software-agent-sdk#5038 (
F06.tool-visualizers): The agent file editor can refuse valid Chinese UTF8 text as binary when its sample splits a character; Canvas Files uses a separate preview detector. Live prerequisite: A live canonical file-editor view/edit on the specific UTF8 sample alignment; Canvas Files preview uses a separate NUL sniff, not this validator. - Known issue OpenHands/software-agent-sdk#4990 (
F06.stop-resume): An ACP turn can keep executing tool calls while the UI already reports Paused. Live prerequisite: An authenticated Claude Code ACP turn executing separate marker-writing tools while Pause is pressed. - Known issue OpenHands/software-agent-sdk#4983 (
F06.tool-visualizers): Agent grep can silently miss extended-regex matches when its runtime falls back to system grep. Live prerequisite: A runtime without ripgrep and a live agent grep call using extended regex and escaped literal punctuation. - Known issue OpenHands/software-agent-sdk#4965 (
F06.error-events): A strict OpenAI-compatible provider can reject blank content in the saved history, preventing later turns. Live prerequisite: A strict OpenAI-compatible provider and a real history containing blank text or empty content arrays. - Known issue OpenHands/software-agent-sdk#4777 (
F06.stop-resume): Stop can still start a queued tool after it finishes waiting on a resource lock. Live prerequisite: A live batch with a second real tool waiting on a declared-resource lock when Stop is pressed. - Known issue OpenHands/software-agent-sdk#4668 (
F06.tool-visualizers): A planning editor card can lose old/new content and fail to show the complete edit diff. Live prerequisite: A live planner create/edit yielding PlanningFileEditorObservation with old/new contents for the chat diff. - Known issue OpenHands/software-agent-sdk#4663 (
F06.tool-visualizers): Parallel Python-fallback glob calls can change process cwd and return files from the wrong workspace. Live prerequisite: Concurrent real glob/tool calls in distinct workspaces with the Python fallback active. - Known issue OpenHands/software-agent-sdk#4661 (
F06.tool-visualizers): Same-name project subagents can resolve to another conversation workspace definition. Live prerequisite: Two native task-enabled conversations with same-name project subagent definitions and a working model for delegation. - Known issue OpenHands/software-agent-sdk#4583 (
F06.tool-visualizers): An agent editor insertion at EOF can join onto the last line when the file has no trailing newline. Live prerequisite: A working model invoking file-editor insert at EOF on a file with no trailing newline. - Known issue OpenHands/software-agent-sdk#4558 (
F06.error-events): A saved encrypted fallback profile can send ciphertext as its key and fail authentication, leaving only the primary error visible. Live prerequisite: A working encrypted saved fallback profile and real primary-model failure that triggers fallback resolution. - Known issue OpenHands/software-agent-sdk#4540 (
F06.tool-visualizers): Synthetic GLM/Kimi tool calls can render as raw tool_call syntax instead of executing. Live prerequisite: Synthetic provider credentials and a GLM/Kimi turn emitting the raw tool_call wrapper. - Known issue OpenHands/software-agent-sdk#4532 (
F06.confirmation-mode): After restarting while awaiting confirmation, approval can execute the tool but the next model request omits its assistant call. Live prerequisite: A real confirmation-paused action persisted across backend restart, then approval and a working provider call. - Known issue OpenHands/software-agent-sdk#4077 (
F06.reload-mid-run): Retried or late streaming deltas can duplicate live text; a stalled subscriber can delay Stop and finalization. Live prerequisite: A working stream interrupted/retried or delivered to a controlled stalled subscriber, with delta/state-order capture. - Known issue #16947 (
F06.load-older-history): Loading older history can leave both the action and its newer observation visible because UI projection depends on arrival order. Live prerequisite: A real long conversation whose REST boundary splits an action/observation pair; keep companion #17559 linked separately. - Known issue #18445 (
F06.load-older-history,F06.reconnect): a failed initial Cloud history search can be swallowed into an empty page while the runtime count succeeds, advancingafter_seqpast history that was never displayed. Live prerequisite: a Cloud account and owned conversation with a genuinely failing App APIevents/searchand a successful runtimeevents/count. The Local failure path throws instead and is not an equivalent check. - Known issue OpenHands/software-agent-sdk#5969 (
F06.stop-resume): a conversation can report finished but reject Play with already-running, or delay a follow-up, while a slow event webhook is still pending. Live prerequisite: a genuinely successful model run on an owned backend with a bounded slow webhook receiver, then Play or send during that completion window. - Known issue OpenHands/software-agent-sdk#5740 (
F06.error-events): a Responses display delta withoutitem_idcan terminate the turn with an AttributeError. Live prerequisite: the genuine provider/transformer streaming path producing that incomplete event; the report did not retain its original raw SSE. A credential-free parser diagnostic proves the SDK exception, not a Canvas model turn. - Known issue OpenHands/software-agent-sdk#5806 (
F06.branch-from-here): editing a displayed user message first reads its parent event; if that event has become unreadable/missing on the server, the action can fail with 500 instead of a missing-event response. Live prerequisite: an owned persisted conversation with a still-displayed user message whose event storage is missing, followed by the actual Edit action. A random unknown-ID API call proves neither this UI path nor the batch-get contract, which Canvas does not call. - Session reconnects use the latest received
after_seqcursor (F06.reconnect). For a local metadata check, retain the open page, send genuinerun:falseuser events, record/events/count, restart the owned backend and inspect finite WebSocket lifecycle metadata: the reconnect cursor is the previous count minus one and a subsequent recovery marker appears once. This does not measure frame-body replay or Cloud behavior. - Stop persists
pausedbefore an in-flight model request completes (F06.stop-resume); the persisted state and reloaded Stopped UI survive an Agent Server restart. A bounded credential-free check can use the tracked accept-only endpoint and an exact listener PID proven to descend from the owned launcher; never kill by pattern or resume the paused conversation.
F07 Conversation page, header and management menu
25 behaviors · Read this family’s scripts
- Open by URLF07.open-by-urlKnown issueBlocked
- Leaving an automation setup conversationF07.open-by-urlKnown issueBlocked
- Unknown idF07.missing-redirectMapped behavior
- Rename inlineF07.rename-inlineKnown failure
- Rename from the menu, empty valueF07.rename-inlineKnown failure
- History skeleton and sidebar entryF07.history-skeleton · F07.open-by-urlKnown issueBlocked
- Status menu, stopF07.status-menuKnown issueBlocked
- MenuF07.menu-openMapped behavior
- Stop with confirmationF07.stop-confirmMapped behavior
- Branch from a messageF07.branch-from-messageKnown failure
- Delete with confirmationF07.delete-confirmMapped behavior
- Paused conversationF07.menu-items-by-state · F07.status-menuKnown issueBlocked
- HooksF07.hooks-modalMapped behavior
- SkillsF07.skills-modalMapped behavior
- Project skills and configured hooksF07.skills-modal-project · F07.hooks-modalMapped behavior
- Agent toolsF07.agent-tools-modalMapped behavior
- Export transcriptF07.export-transcriptKnown issueBlocked
- Download dataF07.download-zipKnown failureKnown issueBlocked
- UsageF07.display-costMapped behavior
- Right panelF07.right-panel-toggleMapped behavior
- OverviewF07.overview-toggleMapped behavior
- Git actionsF07.git-actions-menuKnown failure
- Panel routeF07.panel-routeMapped behavior
- Git control barF07.git-control-barKnown issueBlocked
- Pull sends at onceF07.git-control-bar-sendBlocked
- Cloud-onlyF07.cloud-onlyKnown issueBlocked
- PhoneF07.phoneMapped behavior
- Whitespace-only header renameF07.rename-inlineKnown failure
- Already-deleted conversationF07.delete-confirm · F07.rename-inlineKnown failure
Family notes & prerequisites for known issues
- The stop and delete confirmation buttons carry
cancel-buttonandconfirm-button; role names insiderole=dialogwork too. stop-button,show-skills-button,show-hooks-buttonandshow-agent-tools-buttonalso exist in the composer, andellipsis-buttonin sidebar rows: always scope totestid=chat-pane-headerortestid=conversation-name-context-menu.- Stop Runtime (status menu) and Stop Conversation (menu) both navigate to
/conversations. On a finished local conversation the agent server keepsfinished; use a running conversation to seepausedand Start Runtime. - Rename has no Escape-to-cancel: Escape leaves the input open and the next blur saves whatever was typed.
- Escape closes the status-dot menu, as it closes the "..." and Git actions menus (
browser count 'testid=server-status-context-menu'is0). A menu opened by click or Enter returns focus toserver-status-menu-trigger; one opened by hover closes without moving focus (focus left on a menu item falls tobody). Touch taps cannot be driven with the CLI, so the tap path is unverified. - The status menu reads
Running/Stop Runtimefor a finished local conversation too; only a paused one showsServer Stopped/Start Runtime. - Panel and Overview columns animate: read their state with
browser wait <sel> --state hidden|visible, not an immediatebrowser visible. - The Skills dialog shows the list read with the page or at the last Refresh: a project skill added later appears after Refresh (or
browser reload), not on reopening the dialog within 10 minutes. Its own text says to click Refresh. tabs-pane-headerandconversation-overview-columnstay in the DOM when hidden: assert withbrowser visibleoraria-pressed, notcount.browser visible 'testid=usage-panel'right after Display Usage and Cost can readfalse;browser waitfirst.- Exports and the zip land in
<run>/private/downloads; the transcript holds the prompts and the zip holds the full event store. Review before sharing. --observeaccepts the same selector syntax as other verbs ('testid=chat-messages-skeleton') as well as CSS.- A sidebar row click lands on
/conversations/<id>?backend=default-local: end--expect-urlregexes without$there. role=button[name="Pull"]also matchesPull Request; add[exact].- The Open Workspace folder browser has no path field: walk it with
folder-browser-upandfolder-browser-entry-<name>.fixture git-repoputs the repo in<run>/workspace, three levels above theworkspacefavorite. - The repo, branch and Pull/Push chips come from
git remote get-url originin the workspace, read when the page loads: reload after changing the remote. - The Usage tab logs
GET /api/llm/balance404 on a local backend (F27); count it inbrowser errors --app-onlybut it is not an F07 failure. - The Overview drawer has no Automations, Skills, MCP or Secrets sections. The Overview menu offers Workspace and Git rows only, and its drawer opens only Pull Requests (
F27.overview-drawer). - Dialogs move focus inside when they open and keep Tab inside: the Skills and Hooks dialogs start on their close button, Stop and Delete on
cancel-button, Export onclose-transcript-export-modal, Agent Tools onclose-system-message-modal. In the Hooks dialog, focusing Refresh with Tab opens its tooltip, which takes the first Escape; a second Escape closes the dialog. - The Hooks dialog shows the workspace's
hooks.jsonas of its last read (its first open for the conversation after a page load, or Refresh), not the hooks the conversation started with: after the hooks steps above,browser goto /conversations/<git-id>(started before the file existed; itshook_configisnull) and opening the dialog lists both events too. A reopen within 5 minutes of that read shows the same list and sends no request: click Refresh after editinghooks.json. - A prompt- or agent-type hook shows its text under Commands (the
prompt, or an agent hook'ssystem_prompt). With the Hooks dialog closed (the hooks steps above end that way; otherwisecontrol-openhands browser click 'testid=close-hooks-modal'), write<run>/workspace/qa-f07-repo/.openhands/hooks.jsonas{"stop":[{"hooks":[{"type":"prompt","prompt":"QA_F07 prompt hook"}]}],"session_start":[{"hooks":[{"type":"agent","system_prompt":"QA_F07 agent hook"}]}]}, runcontrol-openhands browser goto /conversations/<hooks-id>, open the menu andcontrol-openhands browser click 'testid=conversation-name-context-menu >> testid=show-hooks-button', clicktestid=hooks-modal >> testid=refresh-hooks, thenrole=button[name="Session Start 1 hook"]androle=button[name="Stop 1 hook"]insidetestid=hooks-modal(an event expanded before a Refresh stays expanded, and a second click collapses it, so start from a reopened dialog). Incontrol-openhands browser snapshot 'testid=hooks-modal'they expand, in that order, toMatcher * Commands QA_F07 agent hook Type: agent Timeout: 60sandMatcher * Commands QA_F07 prompt hook Type: prompt Timeout: 60s, andbrowser text 'testid=hooks-modal >> pre'returnsQA_F07 agent hookandQA_F07 prompt hook(control-openhands browser screenshot --feature F07.hooks-modal --name prompt-agent-hooks). An agent hook withoutsystem_promptshows no box: with{"session_start":[{"hooks":[{"type":"agent"}]}]}, close, reopen and Refresh,Session Start 1 hookexpands toMatcher * Commands Type: agent Timeout: 60sandbrowser count 'testid=hooks-modal >> pre'is0. - An agent hook shows its
system_prompt, the text it runs with, even when it also carries aprompt, and an agent hook with only apromptshows no box. With{"session_start":[{"hooks":[{"type":"agent","prompt":"QA_F07 stray prompt","system_prompt":"QA_F07 agent system prompt"}]}],"stop":[{"hooks":[{"type":"agent","prompt":"QA_F07 prompt only"}]}]}inhooks.json, close, reopen and Refresh the dialog, then expand both events:Session Start 1 hookreadsMatcher * Commands QA_F07 agent system prompt Type: agent Timeout: 60s,Stop 1 hookreadsMatcher * Commands Type: agent Timeout: 60s, andcontrol-openhands browser count 'text=QA_F07 stray prompt'andbrowser count 'text=QA_F07 prompt only'are0(browser screenshot --feature F07.hooks-modal --name agent-hook-system-prompt). Agent hooks inhooks.jsonreally run on the next turn in that workspace (the session-start one shows aHook: SessionStart failedrow), so write the recipe's two-eventhooks.json(pre_tool_useandstop) back and Refresh afterwards. - With the Agent Server down, Refresh in the Hooks dialog shows its own fetch error (#18177): after
control-openhands service stop agent-serveron an open dialog,refresh-hooksandbrowser wait 'testid=hooks-modal >> text=Failed to fetch hooks' --timeout 30000, the dialog readsFailed to fetch hooks. Please try again later.under its explanation (browser count 'testid=hooks-modal >> text=Failed to fetch skills'is0). The 502s and the closed WebSocket thatbrowser errors --app-onlythen lists are the outage itself. Run it last, orrestartafterwards. - After the user-message branch in
F07.branch-from-message, Send stays disabled next to the prefilled text (browser enabled 'testid=submit-button'isfalse; Known failure #18202, see F05 Gotchas). Enter in the field sends it. - Known issue #18136 (
F07.cloud-only): Connect Repo on a cloud conversation does not save the repository on the server. Live prerequisite: An authenticated Cloud sandbox/repository provider and a second fresh browser to compare server repository metadata. - Known issue #17494 (
F07.export-transcript): Transcript export leaks raw i18n template for ACP tool calls without a title. Live prerequisite: An authenticated ACP session that emits a titleless tool call, then Markdown and HTML export. - Known issue #16876 (
F07.history-skeleton): Planning-agent history flag stays true forever when sub-conversations fetch fails — infinite chat loading skeleton. Live prerequisite: A real planning sub-conversation whose batch lookup fails or yields null, with the main history available. - Known issue #16727 (
F07.open-by-url): Conversation corrupted after VM restart: "Missing event file". Live prerequisite: A disposable VM interrupted at the event-write boundary or the original missing-event persisted fixture. - Known issue #16356 (
F07.open-by-url): Conversation LLM config is frozen at creation time — resuming after API key rotation fails permanently with LLMAuthenticationError. Live prerequisite: A working provider key that can be rotated/revoked, an existing conversation using it, and a replacement profile. - Known issue #15543 (
F07.git-control-bar): Bad parsing for branch retrieval. Live prerequisite: The original Git probe stdout/interleaving that temporarily puts a filename in the branch badge; dirty state alone is not a deterministic trigger. - Known issue OpenHands/software-agent-sdk#5640 (
F07.download-zip): Download conversation data can return404 after a warm-pool server initializes a custom conversation-storage path. Although closed upstream, the pinned SDK 1.55.0 still reads the default configuration path here; this remains a supported-version distinction, not a freshly reproduced failure. Live prerequisite: A deferred-init warm-pool Agent Server initialized with a non-default conversations_path; this launcher starts an already-initialized server. - Known failure OpenHands/software-agent-sdk#5629 (
F07.rename-inline), reproduced 2026-10-12 atfa1f724ab573, SDK 1.54.0. A second server's native first load rewrote a newer saved title with its startup copy; the connected Canvas header showed that older title. Recipe: create an idle conversation on A and PATCH its title toQA_SHARED_BEFORE_B_5629_REPEAT; run pinned SDK Pythonpython .agents/skills/verify-openhands/scripts/fixtures/shared-storage-server.py --run <run> --seconds 300in the background. It starts only a bounded no-editor SDK B sharing this run's conversation directory/cipher/session key; its privateserver.jsonsupplies the port and owned operator/PGID. After B listens, PATCH A toQA_SHARED_AFTER_B_5629_REPEATand confirm disk. Runcontrol-openhands service stop agent-server --run <run>, thenpython .../fixtures/shared-storage-server.py --run <run> --load-id <id>: native B/events/countreturned 200 and disk reverted to BEFORE_B. Restart A only to serve Canvas, choose default-local and doctor; use the Add Backend recipe from F25 to connect B at its recorded port with the private key file, then open its card: the header reads BEFORE_B. SIGTERM only the recorded helper operator and verify its port/PGID gone; the helper also bounds runtime and terminates remaining group descendants. Evidence:backfill-18309-surface-rechecks/F07.rename-inline/metadata-repeat-before-b-load-5629.json,metadata-repeat-after-b-load-5629.json,shared-first-load-reverted-5629.png. The native first-load request is explicit; stale catalog display alone is insufficient proof of this overwrite. - Known failure OpenHands/software-agent-sdk#5539 (
F07.download-zip), reproduced 2026-10-12 atfa1f724ab573, SDK 1.54.0: three real overlapping receivers of one idle conversation made 929 requests in 20 seconds, including 31 completed corrupt ZIPs with status 200, 106 server 500s, 269 ingress 502s and 133 RemoteProtocolErrors. A sequential 2,000-request control returned valid ZIPs. Recipe (use the pinned SDK Python with httpx):python .agents/skills/verify-openhands/scripts/fixtures/download-trajectory-overlap.py --base-url <own-base-url> --conversation-id <id> --api-key-file <run>/private/session-key --output-dir <run>/private/trajectory-overlap --seconds 20 --clients 3 --rounds 5000 --slow-ms 2. It enforces loopback, request/duration/network/uncompressed/member budgets and bounded CRC reads; aborts and unsupported archives remain unverified. While it runs, usebrowser goto /conversations/<id>, openchat-pane-header >> ellipsis-button, clickdownload-trajectory-button, thenbrowser downloads --last 3 --inspect(all CLI commands with--run <run>). That Canvas click downloaded an inspectable ZIP; its particular result is not claimed corrupt. Private raw samples stay private. Evidence:backfill-18309-surface-rechecks/F07.download-zip/trajectory-overlap-5539-summary.jsonandoverlapping-download-5539.png. The summary correction excludes two ambiguous Content-Length differences that could be intentional deadline aborts; only completed corrupt ZIPs count as corrupt downloads. - Known issue OpenHands/software-agent-sdk#5094 (
F07.open-by-url): After ACP session/load fails, the backend can create a fresh model session while Canvas still shows the old context. Live prerequisite: An authenticated Codex ACP session whose original session/load fails while persisted history remains. - Known issue OpenHands/software-agent-sdk#4893 (
F07.status-menu): A sandbox frozen mid-run can resume with a stale Running state that rejects normal resume requests. Live prerequisite: A disposable sandbox/VM frozen mid-run with a live model and persisted ownership state. - Known failure OpenHands/software-agent-sdk#4800 (
F07.rename-inline), reproduced 2026-10-12 atfa1f724ab573, SDK 1.54.0. A refused rename changed the server's GET title whilemeta.jsonkept the previous title; graceful shutdown subsequently persisted the rejected title. Recipe: create an idle dummy-profile conversation, then double-clickconversation-name-title, fillconversation-name-inputwithQA_META_BEFORE_4800and press Enter; verify GET/disk. Record the original mode and temporarilychmod 0500 <run>/private/state/dev_conversations/<id-hex>to deny an atomic metadata replacement. Rename through that UI toQA_META_REFUSED_4800: the permission-denied toast/HTTP 500 appears, GET shows REFUSED, disk still shows BEFORE. Restore the exact original directory mode infinally, thenrestart,doctor, GET and reload (CLI with--run <run>): REFUSED was persisted during graceful shutdown. Only the owned temporary directory is changed; evidence contains title/timestamp fields, not stored secrets. Evidence:backfill-18309-surface-rechecks/F07.rename-inline/metadata-before-4800.json,metadata-denied-4800.json,refused-title-4800.png,metadata-after-graceful-restart-4800.json. Tags/autotitle and ownership-conflict branches remain untested. - Known issue #16877 (
F07.open-by-url): Untitled terminal-status conversations are reported to keep the 3-second title polling interval. On frozen targetfa1f724ab5737a17453ad6081129eb91c5a423c6, a real Localautotitle:false/idle conversation retainedtitle:null, while eight browser batch GETs had 30.008–30.031-second intervals over 210 seconds. The direct adapter supplies a default display title. This does not exercise the Cloud null-title IDLE/FINISHED branch, which needs an approved Cloud conversation with a failed/unsupported title job. Runbackfill-18309-coordinator-checks, Agent Server/SDK 1.54.0, automation 1.19.3; retainedevidence/F07.open-by-url/16877-local-polling.jsonand16877-local-idle.png. Arrange the empty conversation withapi POST /api/conversations --write --data @<idle-autotitle-disabled-payload>, open/conversations/<id>, clearbrowser network, leave the tab foreground, then readbrowser network --filter ids= --last 100andconversation status <id>. No model call or response was used.
F08 Workspace drawer: files and changes
34 behaviors · Read this family’s scripts
- Open the drawerF08.panel-toggleMapped behavior
- Switch and close by tabF08.tab-barMapped behavior
- ReloadF08.drawer-state-reloadMapped behavior
- Overflow menuF08.tabs-menuMapped behavior
- Pin/unpinF08.tabs-pinMapped behavior
- ResizeF08.drawer-resizeMapped behavior
- VS Code linkF08.vscode-linkKnown issueBlocked
- ArchivedF08.archived-disabledBlocked
- Workspace pathF08.files-workspace-pathMapped behavior
- TreeF08.files-treeKnown issueBlocked
- Tree toggleF08.files-tree-toggleMapped behavior
- Tree resizeF08.files-tree-resizeMapped behavior
- File discoveryF08.files-discovery-settingsMapped behavior
- Rich/PlainF08.files-rich-plainKnown issueBlocked
- Open in new windowF08.files-open-new-windowKnown issueBlocked
- Open-file stripF08.files-open-tabsMapped behavior
- No selectionF08.files-no-selectionMapped behavior
- Second agent turn: commit, binaries, auto-refreshF08.files-auto-refresh · F08.files-refreshKnown failureKnown issueBlocked
- FallbacksF08.files-fallbacksKnown issueBlocked
- File-editor edits auto-refresh; deleted file errorsF08.files-auto-refresh · F08.files-load-errorKnown issueBlocked
- Open from chatF08.files-open-from-chatMapped behavior
- Tool-card path chipF08.files-open-from-tool-chipMapped behavior
- Commits listF08.uncommitted-changes · F08.commit-rowsKnown issueBlocked
- Diff modesF08.diff-view-modesMapped behavior
- Markdown previewF08.diff-markdown-previewMapped behavior
- Deleted fileF08.diff-deleted-fileMapped behavior
- From the overviewF08.changes-from-overviewMapped behavior
- Empty statesF08.commits-states · F08.files-empty-workspaceMapped behavior
- Commit capF08.commits-capMapped behavior
- Phone panel pageF08.phone-panel-pageMapped behavior
- Direct panel URLF08.panel-direct-urlMapped behavior
- ErrorsF08 · setup / cleanupSupport step
- Rich fenced codeF08.files-rich-plainKnown failureKnown issueBlocked
- Git filename with a spaceF08.uncommitted-changesKnown failureKnown issueBlocked
- File listing above one MiBF08.files-treeKnown failureKnown issueBlocked
- Subdirectory Git pathsF08.uncommitted-changes · F08.diff-view-modesKnown failureKnown issueBlocked
- Plain parent containing a repositoryF08.uncommitted-changesKnown failureKnown issueBlocked
Family notes & prerequisites for known issues
- When the drawer is closed, its tabs stay mounted at width 0.
browser count 'testid=files-tab'is1even then, so assert withbrowser visibleorright-panel-togglearia-pressed. - The tab row is a
tablist "Conversation panels"ofrole=tabcontrols, each named after its tab even when inactive (#17612), sorole=tab[name="Commits"]finds the Commits tab whether or not it is active;role=button[name="Commits"]finds nothing.aria-selectedmarks the selected tab. Theconversation-tab-*test ids still work. - The tab row ends with the ellipsis menu (
Customize tabs), then theVSCodebutton (drawer-vscode-link, namedOpen in VS Code) when the runtime reports a running editor. #17660 removed that button and #18048 restored it, so on a checkout between the two the drawer has no editor control at all. - The overflow menu is not a
role=menu. Escape closes it and returns focus to the tab bar'sellipsis-button, both in the desktop drawer and on the phone/panelpage; choosing a row or an outside click (browser mouse-click) closes it too. - The Files list and the open preview do not follow bash edits:
use-auto-refresh-files-on-edit.tsrefreshes the file queries only for file-editor observations, and its comment says shell observations skip them on purpose (so that every shell command does not reload canvas iframes). This map still expects files the agent writes to appear (F08.files-auto-refresh), so the bash case stays a fail row. Clickfiles-tab-refreshonce before asserting on files the agent made with the shell. Since #18032 that one click also re-reads the open file (the content fetch revalidates instead of using the browser HTTP cache, and the rich preview gets a new?v=), and a page reload shows the current body without a click. - The chat also fetches the file list (to linkify paths). A conversation page left open while the agent works can therefore show a stale tree the moment the drawer first opens.
- Binary detection is a NUL-byte sniff of the first 8 KB, and the Office message also needs that sniff to trip. A 4-byte
PK\003\004"pptx" or random bytes without a NUL render as text in the plain viewer. Fixtures must contain a NUL. control-openhands fixture folderwrites a plain folder withnotes.md, but by the time the conversation has run the folder holds an empty.git, so a conversation that leavesnotes.mdin place showsUncommitted 1 filerather than the empty state. Delete it first (as in the recipe).- Diff views are Monaco.
testid=file-diff-viewerandfile-single-viewerare not on the DOM; read text throughtestid=editor-container. The narrow drawer falls back to an inline (not side-by-side) diff. The view-mode buttons are namedOld version,DiffandNew version, andcollapseis namedExpandorCollapseafter its state (#18033). browser eval "navigator.clipboard.readText()"hangs for about 2 minutes (no clipboard permission). Usecontrol-openhands browser clipboardto read what Copy wrote.browser click ... --observeaccepts the usual selector syntax (testid=...).- Two
.cursor-ew-resizegrips sit in the conversation page (chat/drawer, then the Files tree); scope the tree one withtestid=files-tab-tree-resize-handle. - At phone width, chat path links (and the agent's
canvas_ui_controltab and file requests, throughsrc/services/canvas-ui.ts) navigate to/conversations/<id>/panel(#18045); at desktop width they open the side drawer and the URL does not change. A/panelURL above 1024 px redirects to/conversations/<id>, so a bullet that leaves the phone viewport on/panelends on the chat route. - If the agent's terminal resets mid-command ("terminal session was reset", for example after a
restart), the agent reruns the command. Check the workspace withgit statusthrough a second prompt rather than trusting the first observation. Runs no longer share a tmux server (OpenHands/OpenHands#17946). - Known issue: #17567 (Monaco disposed-model page error on diff unmount; it also fires on collapse and on a diff→old switch).
- Known issue #18108 (
F08.files-tree): Files tab shows "No files in workspace" on cloud when the agent writes outside /workspace/project. Live prerequisite: An authenticated Enterprise Cloud sandbox, no repository selected, with files outside its default working directory. - Known issue #17773 (
F08.files-tree): Files tab always shows "No files in workspace" on Windows local backend. Live prerequisite: A Windows local Agent Server using cmd.exe; this run is macOS. - Known issue #16949 (
F08.files-refresh): Keep Files and Changes views source-driven after refresh. Live prerequisite: An authenticated Cloud repository for the refresh-query mismatch, or real file-editor observations causing an in-place M-to-D Git refetch. - Known issue #16716 (
F08.uncommitted-changes): Diff view is regularly out of sync. Live prerequisite: The original simultaneous-agent/shared-repository state or a deterministic stale-diff trigger; the report only suggests that timing. - Known issue #16689 (
F08.files-load-error): Whenworkspace/paths throw a 401, call the workspace-session endpoint. Live prerequisite: The original fresh-VM URL, auth/cookie state and exact request sequence; the report says the trigger is unclear. - Known issue #16454 (
F08.uncommitted-changes): Diff list is showing duplicate entries. Live prerequisite: The original Git changes response and update sequence producing duplicate rows; the report provides no trigger. - Known issue #16331 (
F08.files-tree): file preview panel stops working during streaming. Live prerequisite: A real streaming/tool-running conversation while selecting a second workspace file. - Known issue #15692 (
F08.uncommitted-changes): Diff still shows after agent has committed and pushed. Live prerequisite: A real agent commit/push terminal observation while the diff remains mounted, plus a disposable Git remote. - Known issue #15567 (
F08.files-load-error): Workspace file preview returns 401 Unauthorized on non-HTTPS non-loopback hosts. Live prerequisite: A plain-HTTP non-loopback deployment and browser accessing that origin, with workspace-cookie observation. - Known issue #15519 (
F08.files-load-error): "files" tab in Files side panel throws 401 Unauthorized. Live prerequisite: The reported Linux Docker deployment/auth topology; this isolated run uses the macOS source launcher. - Known issue #15501 (
F08.files-rich-plain): Generated-page JavaScript was blocked by an iframe sandbox. Files Rich intentionally disables scripts; the report does not identify whether Files or Browser was used. Live prerequisite: The original preview panel and file URL or minimal page identifying the intended surface; Files Rich deliberately blocks scripts, while Browser is separate. - Known issue OpenHands/software-agent-sdk#4562 (
F08.files-load-error): Plain-HTTP non-loopback workspace previews can return401 after the browser rejects the workspace-session cookie. Live prerequisite: A plain-HTTP non-loopback same-origin browser deployment with real workspace-cookie observation. - Known issue #16871 (
F08.vscode-link): the sharedtransformVSCodeUrlstill accepts arbitrary schemes, and the current Clouduse-unified-vscode-url.tsbranch passes sandboxexposed_urlseditor values through it without the Local origin gate. Live prerequisite: an authorized Cloud account/sandbox whose editorexposed_urlsvalue can be controlled for safe URL-scheme rejection checks. Local inspection on 2026-10-12 atfa1f724ab573found no Download via VS Code action in the real card menu: its only production caller does not supply the requiredshowOptionsprop. The current drawer opens withnoopener,noreferrer. Neither the old opener exploit nor the remaining Cloud scheme scenario was reproduced. Evidence:backfill-18309-surface-rechecks/F04.download/vscode-card-action-absent-16871.pngand its ARIA snapshot. Keep this linked to the live editor-link consumer; do not infer the whole issue resolved from the removed card action. - Known issue OpenHands/software-agent-sdk#5845 (
F08.vscode-link): reserved characters in the workspace path can split the editor URL's unencodedfolderparameter and open the wrong folder. Live prerequisite: a supported origin serving a genuinely enabled/running editor and an owned conversation in a path containing&or#. A direct URL-constructor call does not exercise the link; Cloudexposed_urlstakes another path. - Known issue OpenHands/software-agent-sdk#5784 (
F08.files-rich-plain,F08.files-fallbacks,F08.files-open-new-window): a path-prefixed Agent Server can set a workspace cookie whose Path omits the prefix, leaving HTML/image/file previews unauthorized. Live prerequisite: an authenticated path-prefixed owned Local server withOH_WEB_URLand a real cookie-authenticated preview; the ordinary root-path launch cannot exercise that cookie Path.
F09 Settings shell and navigation
26 behaviors · Read this family’s scripts
- Gear entry and index redirectF09.entry-gear · F09.index-redirectMapped behavior
- Collapsed railF09.entry-collapsed-railMapped behavior
- Command menuF09.entry-command-menuMapped behavior
- Command menu coverageF09.command-menu-coverageMapped behavior
- Deep links without a modelF09.entry-deep-linksMapped behavior
- Deep links from the composerF09.entry-deep-linksMapped behavior
- Legacy URLF09.legacy-agent-redirectMapped behavior
- Desktop navF09.desktop-navMapped behavior
- Page headerF09.page-headerMapped behavior
- LandmarksF09.landmarksMapped behavior
- Phone hub and BackF09.phone-hub · F09.phone-backMapped behavior
- Resize from the hubF09.hub-resize-redirectMapped behavior
- Widths around the breakpointF09.breakpoint-sweepMapped behavior
- Tablet selectorF09.tablet-selectorMapped behavior
- Synced badgeF09.synced-badgeMapped behavior
- Cloud linksF09.cloud-linksBlocked
- Update card and dialogF09.update-card · F09.update-modal · F09.update-up-to-dateMapped behavior
- Update availableF09.update-availableKnown issueBlocked
- Update dialog at phone widthF09.update-modal-phoneMapped behavior
- Sidebar version tileF09.sidebar-version-tileBlocked
- Unknown sub-pageF09.unknown-subpathMapped behavior
- After the familyF09 · setup / cleanupSupport step
- Locked cloud landingF09.locked-cloud-landingBehavior contract
- Hidden llm redirectF09.hidden-llm-redirectBehavior contract
Family notes & prerequisites for known issues
browser clickreturns the URL before client-side navigation and redirects settle (it prints/or/settings). Always follow a navigating click withbrowser wait-url '<regex>$'before asserting.- At phone width there are two
backend-selector-settings-linkelements (hidden desktop sidebar plus the drawer); scope withtestid=sidebar-mobile-drawer >> ...or the click fails in strict mode. The hub's nav links share testids with the desktop nav, so scope them withtestid=settings-mobile-hub >> .... - The page does not scroll inside the settings
<main>; the app shell column does.browser scroll <selector> --by Nonly scrolls the element into view and ignores--by; hover the content first, thenbrowser scroll --by N(mouse wheel at the pointer). - Only
/settings/appis taller than a 1000 px viewport in a fresh run; use it for the pinned-nav check. - Visiting
/settings/agentsticks the checklist item "Customize your agent" for good (struck through, still a working link, so the bullet order above is fine), and configuring a model hides the Home banner. Run the banner deep link beforellm preseton a fresh run. - Registry reachability depends on the sandbox and changes between runs. When the browser cannot reach
registry.npmjs.org(seen asERR_CERT_AUTHORITY_INVALIDthrough a proxy), the version badge and sidebar tile stay hidden and the dialog shows the failure state; that is environment, not product. When it can, a checkout at the latest release shows "Up to date" and the failure text cannot be produced. Checkbrowser networkfor the registry request before deciding which update rows areblocked. - The update dialog's
role="dialog"wrapper has no accessible name, sorole=dialog[name=...]does not match it; usetestid=agent-canvas-update-modal. - The
/settings→/settings/agentsredirect only happens at ≥1024 px. Below that (phones and tablets)/settingsis the hub; do not expect a redirect there. - From 768 to 1023 px the sidebar rail stays and the phone top bar is gone; the Settings selector above each subpage provides sibling navigation. The rail's gear (
backend-selector-settings-link) still returns to the hub. - The phone hub is indented 32 px while sub-pages start at 16 px (hub padding inside the page padding); that is current layout, not overflow.
- The "LLM Profiles" rename in
useSettingsNavItemstargets a/settingsnav item that does not exist, so it never applies; the LLM nav item always reads "LLM". - Known issue #17508 (
F09.update-available): After installing a newer package, an older running bundle can keep showing its own version and an update banner. Live prerequisite: Isolated old/new package installs with the old process still serving, or the original stale bundle/cache capture after update. - The public
SettingsNavigationexport renders the legacySettingsMobileDrawerwith a half-opacity black scrim (bg-black/50). Check its modern and fallback compiled CSS as a build contract. The routed phone hub usesSettingsMobileHub, so its navigation recipe does not exercise the exported drawer; visual verification of that export needs an embedding host.
F10 LLM profiles
34 behaviors · Read this family’s scripts
- Empty listF10.list-emptyMapped behavior
- Open the editorF10.createMapped behavior
- API key help linkF10.api-key-helpMapped behavior
- Provider and model listsF10.model-pickerMapped behavior
- Every provider is offeredF10.provider-list-completeMapped behavior
- Cloud provider paginationF10.cloud-provider-paginationBlocked
- Create the first profileF10.create · F10.name-autofillMapped behavior
- A typed name sticks; a cleared one follows againF10.name-autofillMapped behavior
- Name rulesF10.name-validationMapped behavior
- Validation failureF10.create-validationKnown issue
- Custom modelF10.custom-modelKnown issue
- Second profile from a verified modelF10 · setup / cleanupSupport step
- Row menuF10.actions-menuMapped behavior
- Set as defaultF10.set-defaultMapped behavior
- DuplicateF10.duplicateMapped behavior
- RenameF10.renameMapped behavior
- Rename onto an existing nameF10.rename-conflictMapped behavior
- EditF10.editKnown issueBlocked
- Basic re-save keeps a hidden Base URLF10.basic-save-keeps-base-urlMapped behavior
- Leave without savingF10.editor-discardMapped behavior
- Schema field validation and re-applyF10.schema-validation · F10.edit-default-reapplyKnown issue
- New profile prefillF10.create-prefillMapped behavior
- Link to a provider connectionF10.connection-link · F10.list-groupedMapped behavior
- Add models from a providerF10.add-modelsMapped behavior
- Broken linkF10.broken-linkMapped behavior
- ChatGPT subscription, pre-authF10.subscriptionKnown failureKnown issueBlocked
- DeleteF10.delete · F10.delete-defaultMapped behavior
- Command menu and direct URLF10.listMapped behavior
- Phone layoutF10.phoneMapped behavior
- Default profile drives a conversationF10.default-usedKnown issueBlocked
- Persistence across a restartF10.listMapped behavior
- Load errorF10.list-statesMapped behavior
- CleanupF10 · setup / cleanupSupport step
- Embedded editor starts on BasicF10.create-prefill · F10.editKnown failureKnown issueBlocked
- Off-catalog Basic modelF10.model-pickerKnown failure
- Azure Base URL on BasicF10.model-pickerKnown failure
- Slow invalid preflightF10.create-validationKnown failureKnown issue
- Deleted title profile after failed cleanupF10.deleteKnown failure
- Connection-linked provider dispatchF10.custom-model · F10.connection-linkKnown failureKnown issue
- Bedrock named-profile importF10.default-usedKnown issueBlocked
- Unavailable subscription upstream is handledF10.subscriptionKnown failureKnown issueBlocked
- Schema unavailableF10.schema-unavailableBehavior contract
- Cloud readonlyF10.cloud-readonlyBehavior contract
Family notes & prerequisites for known issues
- Save always runs a real completion against the provider (except for connection-linked profiles). A bad or missing key fails fast with the provider's message; budget one tiny call per Save.
- The editor's starting tab is inferred from the values it loads. Edit opens on whichever tab the profile's non-default values need (
QA_renamedandQA_advopened on Basic,QA_brokenon All). A new editor opens on Basic only while the agent's LLM settings are all defaults: once the Default profile has a temperature (the schema step) it opens on All, and this survives deleting every profile, because the agent settings keep the last applied values. Click the tab you need before touching its fields, orllm-provider-input/llm-custom-model-input/llm-api-key-help-anchorwill not exist. control-openhands service stop agent-servercannot show this page's error states: the whole app switches to the disconnected-backend screen.- In Edit,
llm-api-key-inputholds the stored encrypted key token (about 140 masked characters), not an empty field. Never runbrowser valueon it: it prints the token. Leave it untouched to keep the key. - An open provider or model listbox intercepts clicks on the editor's buttons (
cancel-profile-btn,save-profile-btntime out with "subtree intercepts pointer events"):browser press Escapefirst. - Provider and model options render in a portal outside the editor and modals: select
testid=provider-item-<name>unscoped. Only verified providers haveprovider-item-*IDs and only Other models havemodel-item-*IDs; userole=option[name="..."][exact]for the rest.browser testids --filter model-itemlists only items scrolled into view;browser countfinds the rest. - The auto-filled Profile Name never reuses an existing profile's name: picking a model whose name is already a profile's (for example
deepseek-flashafterllm preset deepseek) empties the field, which disables Save. Recipes fillprofile-name-inputwith aQA_*name anyway. - A duplicate profile name is flagged:
aria-invalidtrueand a taken-name alert. The alert has its own wording,An LLM profile with this name already exists. …. - The Rename modal does not check duplicates client-side (Rename stays enabled); the server's 409 comes back as the toast
Profile '<name>' already exists, andbrowser errors --app-onlycounts onehttp-errorand oneconsole.errorfor it. - Set as default (and deleting the Default) rewrites the agent's active LLM settings (
control-openhands llm show). Deleting every profile leaves the last applied model and key in agent settings. - The app never leaves profiles without a Default:
src/routes/root-layout.tsxrunsuseEnsureActiveProfile(src/hooks/use-ensure-active-profile.ts), which activates the first profile with a key (else the first profile) whenever profiles exist but none is Default, whether never activated or because the Default was deleted (this is what promotes a profile inF10.delete-default). Sollm set --no-activatekeeps the Default only while another profile is Default: on a run whose only profile is the arranged one,control-openhands api GET /api/profiles --pick active_profileflips fromnullto it at the next page load (browser reload) and the agent's LLM settings follow (llm show). - Profiles created by Add models are named from the model (
deepseek-chat, …), notQA_*. The chooser hides a model when a profile with that name exists, not when a profile uses that model. Clean them up before the connection: the server refuses to delete a connection while profiles reference it. - A profile linked to a missing connection is grouped under a header showing the raw connection id (
00000000…) instead of a name. - The All tab logs many
[i18n] Missing translation for key "SCHEMA$LLM$..."console warnings; they are not page errors. - The list follows the server's order, which sorts by profile file name:
QA_pro-copy-1lists beforeQA_pro-copy(-sorts before.json's.). Do not assert a strict alphabetical order on names that are prefixes of each other. - Toasts last only a few seconds. A
browser screenshottaken after a slow command can miss them, so assert withbrowser wait-textorbrowser toasts. - A new profile keeps the inherited LLM options the editor shows, such as temperature.
Subscription models are not loaded yet.uses the translatedSETTINGS$SUBSCRIPTION_MODELS_NOT_LOADEDcopy in settings and onboarding. It shows when a subscription profile is saved beforeGET /api/llm/subscription/openai/modelsanswers; checking that branch needs the real request to be pending or failed.- Known issue #17785: Saving DeepSeek-v4-flash on Windows Desktop can fail with missing cache_creation_tokens instead of saving. The reported path needs a Windows Desktop 1.24.0 environment with its SDK dependency resolution and an approved DeepSeek key; this macOS source run cannot establish that result. (
F10.create-validation). - Known issue #17706: A freshly resolved npm-launcher environment can reject openhands/claude-* conversations because LiteLLM sends prompt_cache_key. Reproduction needs an approved OpenHands proxy key with an Anthropic model and the affected fresh transitive dependency resolution; a keyless initialization cannot prove provider acceptance. (
F10.default-used). - Known issue #17391: ChatGPT Business subscription login can be refused or use a fallback model with a 404. Completing the entitlement and selected-model checks needs an approved ChatGPT Business workspace login and the reported Docker subscription runtime. (
F10.subscription). - Known issue OpenHands/software-agent-sdk#5181: The SDK can turn an advertised output limit into a requested default cap and silently drop an explicitly enabled reasoning_effort. The narrowed maintainer scope needs an authenticated OpenRouter/proxy route exposing lower-limit endpoints and capability metadata, or a real endpoint accepting the explicit override; a synthetic empty-metadata response would not establish production behavior. (
F10.schema-validation). - Known issue OpenHands/software-agent-sdk#4934: Switching to a MiniMax M3 profile can fail because the SDK sends unsupported reasoning_effort. The runtime switch needs approved working credentials for the starting model and MiniMax route; the reported provider rejection cannot be proved with a loopback connection error. (
F10.schema-validation,F10.default-used). - Known issue OpenHands/software-agent-sdk#4613: A namespaced model such as openai/openai/example-model can have its inner provider prefix stripped again in Responses API and reach the provider as example-model. Reproduction needs an approved OpenAI-compatible endpoint serving the namespaced model and its exact stored API-mode settings; a loopback connection refusal cannot prove the outbound identifier. (
F10.custom-model). - Known issue OpenHands/software-agent-sdk#4511: Disabling prompt caching can still emit cache_control on preexisting cache-marked tool messages. The report only supplies a Python serializer reproduction; a Canvas check needs the exact persisted/tool-message precondition and a provider request that exposes the cache markers, with approved model access. (
F10.schema-validation). - Known issue OpenHands/software-agent-sdk#4250: A Cloud Workers AI configuration can fail on context-window validation or be routed as OpenAI with an invalid Cloudflare key. Reproduction needs a disposable OpenHands Cloud account, its Workers AI endpoint/key and the exact saved model configuration; the report supplies no complete configuration steps. (
F10.custom-model,F10.default-used). - Known issue OpenHands/software-agent-sdk#4247: An LM Studio configuration can fail with LLM Provider NOT provided although its models endpoint works. Reproduction needs the reachable LM Studio service and the exact model ID/provider-qualified config, which the report does not supply as text; the reported CLI/Docker SDK 1.16.1 installation is not this source stack. (
F10.custom-model). - Known issue OpenHands/software-agent-sdk#5890: Switching the conversation LLM can lose the managed-key refresh-on401 hook. Blocked: needs an approved managed-key refresh source and an allow-listed real model endpoint that returns401 and accepts the refreshed key. Refused loopback cannot establish the refresh/retry outcome; do not supply a fake successful completion. (
F10.edit,F10.default-used). - Known issue OpenHands/software-agent-sdk#5862: DeepSeek invalid-key401 responses can be classified as bad-request errors. Blocked by this pass's loopback-only provider routing: a real invalid-key validation request to DeepSeek must be authorized to capture its actual401 shape. No usable key or successful inference is needed, but a loopback connection error does not prove this classification. (
F10.create-validation). - Known issue OpenHands/software-agent-sdk#5838: A live LLM switch during a running tool step can be acknowledged before the new LLM is persisted for GET/restart. Blocked: needs a genuine model-issued bounded tool step (for example
sleep 20) and an approved starting model. Refused-loopback initialization never enters that step. (F10.default-used). - Known issue #17806: A model-only Save must preserve an untouched key. Current SDK1.55 refused-loopback validation rejects Save before persistence; the stored key marker remains set. Completing Basic/Advanced preserved-key and runtime-switch proof needs an approved route that accepts preflight. Keep dummy traffic on refused loopback until an external route is authorized; a rejected Save does not establish either key loss or successful preservation through Save. (
F10.edit).
F11 Provider connections
21 behaviors · Read this family’s scripts
- Empty stateF11.list-emptyMapped behavior
- Other entry pointsF11.listMapped behavior
- Validation and provider pickerF11.create-validation · F11.provider-pickerMapped behavior
- CreateF11.createMapped behavior
- RowF11.listMapped behavior
- CancelF11.create-cancelMapped behavior
- Server errorF11.create-errorMapped behavior
- Second connectionF11 · setup / cleanupSupport step
- Row menuF11.row-menu · F11.row-menu-focusKnown failure
- EditF11.editMapped behavior
- Bulk addF11.add-modelsMapped behavior
- The agent uses the connection's keyF11.agent-uses-connectionKnown issue
- Rotate the keyF11.rotateKnown issue
- Rename a linked connectionF11.editMapped behavior
- Delete is refused while referencedF11.delete-referencedMapped behavior
- DeleteF11.deleteMapped behavior
- Phone layoutF11.phoneMapped behavior
- Long name and provider changeF11.long-name · F11.editMapped behavior
- Persistence across a backend restartF11.createMapped behavior
- Unlisted providerF11.edit-unlisted-providerMapped behavior
- Stale reference and cleanupF11.delete-stale-referenceMapped behavior
- Load errorF11.load-errorMapped behavior
- Errors sweepF11 · setup / cleanupSupport step
- Redacted key is rejectedF11.create-validation · F11.editKnown failure
- Store lock keeps unrelated routes responsiveF11.listKnown failure
- Connection URL edit reaches next chatF11.edit · F11.agent-uses-connectionKnown failureKnown issue
- CloudF11.cloudBehavior contract
Family notes & prerequisites for known issues
- Select the Provider by clicking an option (
testid=provider-item-<name>exists only for verified providers; use'role=option[name="<label>"]'for the others), or withbrowser choose 'testid=provider-connection-provider-input' <label>.browser fillalone types a filter that is cleared on blur and leaves Save disabled. browser fill ... --value-file <key file>needs no positional value and prints only the length; keep keys out of commands and screenshots (the field is a password input).- Duplicate display names are accepted (two rows called
QA_conn), and so is any base URL text; rows then differ only by order ('testid=provider-connection-row >> nth=1'). Keep fixture names unique. - Edit's Save is enabled even with no changes, and a blank key on Edit is omitted from the request (the stored key is kept); there is no way to clear a key.
- The delete spinner (
aria-busy) lasts under 100 ms on a local stack;--observesees onlyDeletethen<absent>. role=dialogmatches two nested elements in these modals; count> 0, do not expect1.- The first profile added on a run with no profiles becomes the active one. Activating a linked profile copies the resolved key into the active agent settings, which keep the connection id: that is why the server still counts a reference after every linked profile is gone (see
F11.delete-stale-reference) (OpenHands/software-agent-sdk#5498). - Delete a connection's linked profiles before the connection; then also make an unlinked profile active, or the delete is refused.
- Rotation results are read from the conversation (
conversation events ... --kinds ConversationErrorEvent,MessageEventand the banner in the chat), not from the settings page, which never shows the key. - Model Router's Add connection reuses this modal (F12); its toasts and fields are the same.
F11.load-errorneeds a real server failure: the recipe corrupts this run's ownprovider_connections.jsonand restores it. Always restore it (keep the.bak), or every later family on the run sees the error; never touch another run's state.- At phone width a long name squeezes the provider column to one letter (
d…); the full values stay in the API and the name'stitle. - Known issue OpenHands/software-agent-sdk#5497: after a key rotation, new conversations still run agent steps on the old key; only title generation uses the new one (
F11.rotate). - Known issue OpenHands/software-agent-sdk#5207: OpenRouter linked profiles can lose connection credentials at raw agent/condenser startup or reuse stale credentials after rotation; opaque reasoning can also be lost on persisted turns. End-to-end checks need an approved OpenRouter connection and a model returning reasoning_details, including the linked-profile switch and reload path; loopback failure does not prove them. (
F11.agent-uses-connection,F11.rotate).
F12 Model router (meta-LLM profiles)
25 behaviors · Read this family’s scripts
- Open from navigationF12.pageMapped behavior
- Command menuF12.pageMapped behavior
- Empty statesF12.empty-statesMapped behavior
- Template chooserF12.template-chooserMapped behavior
- Custom templateF12.template-customMapped behavior
- ValidationF12.editor-validationMapped behavior
- Add a connectionF12.add-connectionMapped behavior
- Create the first routerF12.create-first · F12.router-profilesKnown issue
- Duplicate nameF12.duplicate-nameMapped behavior
- "Don't create profiles" in a templateF12.router-profilesMapped behavior
- Create another router without new profilesF12.create-more · F12.router-profilesMapped behavior
- Row menu and activateF12.row-menu · F12.activateMapped behavior
- EditF12.editMapped behavior
- Cancel the connection dialogF12.add-connection-cancelMapped behavior
- Leave the editorF12.editor-cancelMapped behavior
- Run on first messageF12.run-first-message-toggleMapped behavior
- Routing in a conversationF12.route-first-messageMapped behavior
- DeleteF12.deleteMapped behavior
- Delete the active routerF12.delete-activeMapped behavior
- Light themeF12.light-themeMapped behavior
- Phone (`F12.phone`, also re-proves `F12.create-first` on a router-less page)F12.phone · F12.create-firstKnown issue
- Restart persistenceF12.listKnown issue
- CleanupF12 · setup / cleanupSupport step
- Router activation is honest on ACPF12.activateKnown failure
- Unreadable settings refuse router activationF12.activateKnown failure
- Load errorF12.load-errorBehavior contract
- UnsupportedF12.unsupportedBehavior contract
- CloudF12.cloudBehavior contract
Family notes & prerequisites for known issues
- Settings nav test ids embed the route: quote
'testid=sidebar-settings-/settings/meta-llm'as written. - The empty-state hint about LLM profiles only exists before any profile is saved: drive
F12.empty-statesfirst on a fresh run. - The first router you create is activated and turns Run on first message on by itself; later routers do neither. Any recipe that creates a router on an empty list changes both.
Run on first messageis ansr-onlycheckbox (keyboard reachable): click the label text insidetestid=meta-profile-run-at-conversation-startand read.checked/.disabledwithbrowser eval. The stored preference (misc_settings.app_preferences.run_router_at_conversation_start) is independent of what the disabled switch shows; with no active router it may still betrue. Turn it off before deleting the last router, or a later "first router" will not re-enable it because it is already on.- Router templates name 11 models (
gpt-5.4…claude-sonnet-4-5) that will not exist in a sandbox. With a provider connection present, a template preselects it, and saving creates all 11 as LLM profiles linked to that connection unless you pick Don't create profiles first (F12.create-moredoes). If a run created them, remove them withfor p in gpt-5.4 gpt-5.5 minimax-m3 claude-opus-4-6 claude-opus-4-7 claude-opus-4-8 claude-fable-5 kimi-k2.5 kimi-k2.6 deepseek-v3.2-reasoner claude-sonnet-4-5; do control-openhands api DELETE /api/profiles/$p --write; done(they live in the run's private state and only add rows to Settings → LLM). - Profile matching is case-insensitive and exact by name: table rows are
- <profile name>: description; existingdeepseek-flash/deepseek-proare not re-created, and the endpoint is derived as<provider lowercased>/<name>. - The classifier and the model table refer to LLM profile names, not model ids. A router whose classifier profile does not exist (for example a template's
minimax-m3without a connection) saves fine and only fails when a conversation tries to route. - The agent decides whether to call
route_task_to_model: a prompt that conflicts with routing (Reply with only the word pong.) made deepseek-flash skip the call even with the instruction present. Use a task-like prompt for the positive check and assert the system prompt viaevents/searchfor the instruction itself. conversation eventsdoes not print the system prompt; read it withcontrol-openhands api GET "/api/conversations/<id>/events/search?limit=1" --max-bytes 200000and grep the output.service stop agent-serverdoes not show this page's error state: the whole app switches to the Manage backends card (F02). Runcontrol-openhands restartafterwards.- The selection in the classifier and connection pickers is a combobox: open it with a click on the input, then click
role=option[name="..."];browser fillon the classifier sets a free-text value (allowed) instead of picking a profile. - At 390 px the row truncates the name (
QA_route…) and summary; read names withbrowser text, not the screenshot. - The Model table placeholder displays separate lines (
F12.template-custom). - Known issue OpenHands/software-agent-sdk#5878: Router files can be written under a literal
~directory when Agent Server was configured with leading-tildeOH_PERSISTENCE_DIR. Blocked on the normal absolute-path launcher fixture: needs a disposable server with private HOME/cwd and literal~/...or relative persistence configuration, then a router save and filesystem readback. Never point it at user state. (F12.create-first,F12.list).
F13 Agent profiles
22 behaviors · Read this family’s scripts
- ListF13.listMapped behavior
- No LLM profileF13.editor-no-llmMapped behavior
- Name rulesF13.name-validationMapped behavior
- ACP formF13.acp-formMapped behavior
- Create an ACP profileF13.createMapped behavior
- Pi and OpenCode presetsF13.acp-local-presetsBlocked
- Models from the agentF13.acp-model-discoveryKnown issueBlocked
- Edit and renameF13.editMapped behavior
- CredentialsF13.acp-credentialsKnown failureKnown issue
- Secrets scopeF13.secrets-scopeMapped behavior
- Stale LLM referenceF13.stale-llm-refMapped behavior
- OpenHands optionsF13.openhands-options · F13.createKnown issue
- Set as activeF13.set-activeMapped behavior
- Pill wins over a pinned LLMF13.llm-pill-precedenceMapped behavior
- Active profile drives the launchF13.active-drives-conversationMapped behavior
- MCP scopeF13.mcp-scopeMapped behavior
- Credential fields per presetF13.acp-preset-credentialsMapped behavior
- Menu keyboardF13.menu-keyboardMapped behavior
- DeleteF13.deleteMapped behavior
- PhoneF13.phoneMapped behavior
- ErrorsF13 · setup / cleanupSupport step
- BlockedF13.acp-conversation · F13.cloud-read-onlyKnown issueBlocked
- CleanupF13 · setup / cleanupSupport step
- Default wordingF13.list · F13.set-activeKnown failure
- Seeded default key propagationF13.active-drives-conversationMapped behavior
- Gemini auth file is not sufficientF13.acp-credentialsKnown failureKnown issue
- Published stale ACP binary on PATHF13.acp-conversationKnown failureKnown issueBlocked
- Suffixed profile keeps its identityF13.editKnown failure
Family notes & prerequisites for known issues
- The editor is not a route:
browser urlstays/settings/agentsandbrowser reloaddrops unsaved edits back to the list. The settings page header (settings-page-subtitle) is hidden while it is open. - Autocomplete dropdowns: clicking an input that already shows a value can open an empty listbox (the text filters it), and an option click then times out. The toggle-button opener does not always open the list either: on the Edit editor's
agent-profile-llm-selector(bottom of the form) the option click timed out 5 of 5 times right after opening the editor, and the model list'sCustomoption once detached mid-click after a preset change.browser chooseavoids the input-filtering problem, but an option may still remain unstable immediately after opening an editor. Reload and reopen before retrying; the suffix-identity check can use the already-selected active LLM without changing that dropdown. A listbox also closes if you spend a command (snapshot, eval) in between, so click the option right after opening. - A taken name marks the field invalid with an alert reading
An agent profile with this name already exists. …. has-text=defaultalso matches the active row'sDefaultbadge (Playwright's text match ignores case), so with several profiles'testid=agent-profile-row >> has-text=default'hits two rows; select the seeded profile with'testid=agent-profile-row >> nth=-1'(it sorts last) or by its badge.- Model lookups (
F13.acp-model-discovery) spawn the provider CLI on the agent-server machine through npx with the profile's allowed secrets; they send no prompt. A failed lookup is retried each time the preset is picked again; a successful one is cached for about five minutes per preset and secret set. - Switch rows are
sr-onlycheckboxes inside labels (keyboard reachable): click the label text ('testid=agent-settings-tool-list >> text=<tool>','testid=agent-settings-mcp-list >> text=<name>') and read.checkedwithbrowser eval. A barelabelselector segment is parsed aslabel=, not CSS. - The Default badge, the Set as active item and the
Switched to profiletoast all refer to the same active pointer; the wording differs from the LLM page (Set as default). - The OpenHands row's grey text is the LLM profile name, not the kind. A fresh run's
defaultshowsdefaultthere although no LLM profile of that name exists until it is edited (F13.stale-llm-ref). - Local seeded OpenHands
defaultlaunches through global agent settings so the Skills selection applies; its per-profile fields do not apply on that path. Named profiles use their saved settings. Home launches follow the LLM pill. On a backend advertising per-launch LLM override, a named profile pinned to another LLM keeps its tool, concurrency and MCP settings; readlaunched_agent_profileandagenton the conversation (F13.llm-pill-precedence). Only older backends without that capability use the legacy settings fallback when the profile and pill differ. - The ACP auth probe runs the provider CLI on the agent-server machine. If that machine has a Claude CLI login, Claude Code can show "already signed in". Use only an explicitly approved account for authenticated ACP checks.
- ACP credentials are global secrets, not profile fields: cancelling the editor saves nothing, but saving any ACP profile with a typed credential writes it to Settings → Secrets (F14) for every conversation.
- Choose secrets on an ACP profile also selects provider secret names that are not saved (
CODEX_AUTH_JSON,OPENAI_BASE_URL); they show as switches without descriptions. - The empty state (
agent-profiles-empty) and the load-error state (agent-profiles-load-error) are not reachable on a local backend: deleting the last profile re-seedsdefault, and with the agent-server stopped the app swaps to Manage backends after a reload, or keeps the cached list without one. - The refused-launch toast text comes from the Agent Server and changes between versions (
MCP server(s) not configured: <name>on 1.53.0): assert that one toast names the server and the prompt stays, not the exact wording. - Opening a row menu focuses its first enabled item. Arrows skip disabled Set as active; Escape closes the menu and returns focus to its trigger, while Tab closes it and continues normal tab order.
- The Add agent editor has its own agent description. Parallel tool calls label and description are translated.
- Known issue #16905: An enabled built-in OpenHands skill can be absent from a new Claude Code ACP session. The enabled/disabled instruction-delivery check needs an approved authenticated Claude Code account, its ACP subprocess and the configured Code Review automation; no provider session is authorized here. (
F13.acp-conversation). - Known issue #16296: Claude Code credential fields remain visible below the already-connected banner, leading users to think keys are required. The connected-state check needs an approved existing Claude CLI login on the agent-server host; a dummy credential does not prove that signed-in state. (
F13.acp-credentials). - Known issue #17051: Codex ACP can work in New Chat while Issue-to-PR automation fails with missing OpenAI API credentials. Reproduction needs an approved Codex subscription login plus a configured Issue-to-PR automation and its repository credentials; the report does not identify the saved automation/profile settings. (
F13.acp-conversation). - Known issue OpenHands/software-agent-sdk#5167: On a headless Docker host an already usable Codex ChatGPT login can still time out during ACP authenticate. Reproduction needs an approved ChatGPT login in the reported headless/read-only-auth-file deployment and its adapter; a desktop or bogus login cannot establish this conditional trigger. (
F13.acp-conversation). - Known issue OpenHands/software-agent-sdk#5995: Claude Code ACP first turns with
claude-opus-5-5can fail because the pinned adapter bundles an older Claude Code. Blocked: needs an approved Claude login/API key entitled to Opus5.5 and a real first turn; current SDK1.55 still pins the reported adapter0.63.0. No authenticated turn was attempted. (F13.acp-conversation,F13.acp-model-discovery). - Known issue OpenHands/software-agent-sdk#5899: The browser tool can be reported unusable when genuine Chromium exists only under
PLAYWRIGHT_BROWSERS_PATH. Blocked on this host: it has standard user Chrome. The distinguishing fixture needs a host/container with no standard/default-cache/PATH browser, plus a genuine custom-cache Chromium; never remove the user browser to create it. (F13.openhands-options; operational browser path F27).
F14 Secrets
12 behaviors · Read this family’s scripts
- Open the listF14.listMapped behavior
- Command-menu entryF14.listMapped behavior
- CreateF14.createMapped behavior
- Duplicate nameF14.create-validationMapped behavior
- Invalid nameF14.create-validationMapped behavior
- Empty valueF14.create-validationMapped behavior
- Edit keeps the valueF14.editKnown issue
- Delete with confirmationF14.deleteKnown issue
- Agent receives the secretF14.agent-accessMapped behavior
- Phone layoutF14.phoneMapped behavior
- Back discards the draftF14.form-backMapped behavior
- Rename keeps the valueF14.renameMapped behavior
- Replace the valueF14.edit-valueMapped behavior
- Agent requests a secretF14.agent-requestKnown failure
- Escape cancels deleteF14.delete-escapeMapped behavior
- Cipher mismatch refuses mutationF14.create · F14.edit · F14.deleteKnown failureKnown issue
Family notes & prerequisites for known issues
- Settings nav test ids embed the route, slashes included:
sidebar-settings-/settings/secrets. Quote the selector as written. - The value editor is a plain
textarea, not a password field: use dummy values only, and never ask the agent to print a real secret. - Edit forms intentionally show an empty value; that is not data loss.
- The invalid-name check is native browser validation. It shows a tooltip that screenshots do not capture, and it leaves any earlier
Secret already existsparagraph on screen. Assert withvalidationMessageand the API, not the paragraph. - The model is the weak link in the agent checks, not the product: asked to print a secret's length or last characters, deepseek-flash replies "I can't run that one" and runs nothing, and even for the equality check it may refuse to repeat
Truein its reply. Use the equality prompt and read the terminalObservationEvent;conversation eventstruncates message text to about 160 characters. - The conversation Overview has no Secrets entry point: its "..." menu (
conversation-overview-ellipsis) offers Workspace and Git sections only. - There is no empty state to reach safely:
secrets-emptyrenders only with zero secrets, which means deleting the launcher-seeded key (see below). - Secrets saved in Settings reach only conversations started after the save. Reuse an older conversation and the variable is missing. Only
request_secret(F14.agent-request) attaches a secret to a running conversation, and only on a local backend. request_secretis registered on every new OpenHands-agent conversation this frontend launches (not on ACP agents or older conversations) and appears in Show Agent Tools & Metadata (seeF07.agent-tools-modal). The agent learns the outcome from a hidden[secret-request] ...user message; read it withconversation events <id> --kinds MessageEvent, not from the chat.- At 390 px the name column truncates long names (
OPEN…); usebrowser texton the row rather than the screenshot to read a name. OPENHANDS_AUTOMATION_API_KEYis seeded by the launcher for automations; deleting it breaks F18/F19 runs in the same stack.- Known issue #17710: On the Cloud backend, deleting a secret reportedly adds a suffixed duplicate and leaves the original. Reproduction needs a disposable writable OpenHands Cloud account at the affected service; Local secret CRUD exercises a different transport. (
F14.delete,F14.edit).
F15 Condenser, agent context and verification settings
23 behaviors · Read this family’s scripts
- Open Condenser from the sidebarF15.condenser-pageMapped behavior
- All tierF15.condenser-all-viewMapped behavior
- Dirty stateF15.save-dirty-stateMapped behavior
- Save and reloadF15.condenser-saveMapped behavior
- Dependent fieldsF15.condenser-dependentsMapped behavior
- Basic save keeps hidden fieldsF15.view-scoped-saveKnown failure
- Invalid valuesF15.save-errorsMapped behavior
- Condenser KindF15.condenser-kindKnown failure
- Agent ContextF15.agent-context-pageMapped behavior
- Persistent memory persistsF15.agent-context-saveMapped behavior
- VerificationF15.verification-pageMapped behavior
- Critic and analyzer fieldsF15.verification-critic-fieldsMapped behavior
- Confirmation mode persistsF15.confirmation-mode-saveMapped behavior
- Confirmation stops the agentF15.confirmation-mode-effectMapped behavior
- Critic values persistF15.critic-saveMapped behavior
- Critic mode, threshold and iterationsF15.critic-tuningMapped behavior
- Tier follows the stored values after a saveF15.tier-after-saveMapped behavior
- Memory reaches the agentF15.agent-context-effectMapped behavior
- Leaving discards editsF15.unsaved-navigationMapped behavior
- Command menuF15.command-menuMapped behavior
- Direct URLsF15.direct-urlMapped behavior
- PhoneF15.phoneMapped behavior
- Schema unavailable (`F15.schema-unavailable`, blocked)F15.schema-unavailableBlocked
- Errors sweepF15 · setup / cleanupSupport step
- Background refetch keeps the draftF15.save-dirty-stateKnown failure
- Negative condenser input floorF15.save-errorsKnown failure
- Default Verification tabsF15.verification-page · F15.verification-critic-fieldsMapped behavior
- Datetime refreshed on Canvas launchF15.agent-context-pageMapped behavior
Family notes & prerequisites for known issues
- Switches are
sr-onlycheckboxes (keyboard reachable): toggle by clicking the label text scoped to the page, read.checkedwithbrowser eval. text=Enable Criticis a case-insensitive substring match and hits the help paragraphEnable critic evaluation for the agent.first, so the click does nothing. Quote it:text="Enable Critic"(same fortext="Enable Iterative Refinement").- The conversation-owned fields have no
verification.prefix:sdk-settings-confirmation_mode,sdk-settings-security_analyzer. Critic fields keep it (sdk-settings-verification.critic_enabled). - Saving is tier-scoped: Basic or Advanced saves reset every field the tier hides to its schema default (
F15.view-scoped-save). Make all edits on All when other non-default values must survive. - The page opens on the least detailed tier that shows every stored override (any minor override → All). Do not assume Basic after a reload.
- Condenser Kind None (
no_op) still shows the summarizer fields with defaults, although the stored condenser no longer has them, and edits to them are accepted (Settings saved) but dropped while None is stored. #18049 covers hiding fields that do not apply to the selected kind. - A server-side validation error is retried three times (about 1.5 s of
Saving...) before the toast, and the toast only saysSettings validation failedwithout naming the field (#17932). - Condenser Kind is served by the Agent Server's settings schema as a user field. Canvas shows its own choice labels and help text rather than raw
llm_summarizing/no_opvalues or reStructuredText. The dropdown (F15.condenser-kind) remains a user setting so additional kinds can be selected. OpenHands/software-agent-sdk#5495, the schema's developer-facing description, remains an upstream issue. - Toasts close after a few seconds; read them right after the click, or assert the stored value with
api GET /api/settings. - Under confirmation mode the first confirmed command sometimes returned
The terminal session was reset because the underlying tmux server/session disappeared...while several runs shared one tmux server (OpenHands/OpenHands#17946);launchnow isolates them, so treat a reset as a finding. The agent then asks to run it again; a confirmed command took up to two minutes to produce its observation. Confirm again and wait withconversation wait, not a fixed sleep. - The confirmation buttons have test ids (
action-confirm-button,action-reject-button) but their accessible names areConfirm action/Reject action, not the visibleContinue/Cancel:role=button[name*="Continue"]finds nothing. - Basic-tier saves on Verification reset Security Analyzer to
llm(it is an Advanced field). That is a convenient restore, and a trap if you meant to keepNone. - The memory instructions are only visible through the conversation's first event;
conversation eventstruncates text, so readapi GET /api/conversations/<id>/events/search?limit=1and search the JSON. - A checkout without #18035 shows the condenser minor fields with the schema's English text (
Max tokens,Keep first, raw choice values) and logs 14[i18n] Missing translationwarnings on the All tab. - The dropdowns' clear (×) button has no accessible name and, in this build, clicking it through
role=button >> nth=2left the value unchanged. - After every successful save the selected tab is recomputed from the stored values (
F15.tier-after-save), so a follow-upfillon an All-only field can time out because the page silently moved to Basic. Re-clicksdk-section-all-togglebefore each further edit. - Pressing Enter in a field does not save (no toast, API unchanged, Save stays enabled); only the Save Changes button submits.
- Fields revealed by a parent switch do not exist while the switch is off:
filloncritic_thresholdwith Iterative Refinement off waits for a missing element. - Rejecting a pending action (Cancel), the lock chip above the composer and the ⌘↩ / ⇧⌘⌫ shortcuts belong to
F06.confirmation-modeandF06.confirmation-shortcuts; this family only proves that the settings turn the prompt on. browser count 'role=status'also counts the backend status dot (backend-status-dot); usebrowser toastsfor toast texts.
F16 Application settings
20 behaviors · Read this family’s scripts
- Open from navigationF16.openMapped behavior
- Command-menu and URL entriesF16.openMapped behavior
- LanguageF16.languageMapped behavior
- Colour themeF16.color-themeMapped behavior
- Analytics consentF16.analyticsMapped behavior
- Cloud forces analyticsF16.analytics-cloudBlocked
- Consent reversal with an in-flight Automation writeF16.analyticsMapped behavior
- Sound notificationsF16.soundMapped behavior
- Getting Started checklistF16.checklistMapped behavior
- Title generation modelF16.title-modelMapped behavior
- Manage LLM profiles linkF16.manage-profiles-linkMapped behavior
- Deleted profile falls backF16.title-model-fallbackMapped behavior
- Voice input endpointF16.voice-endpointMapped behavior
- Git identityF16.git-identityKnown failure
- Git validation and defaultsF16.git-identity-validationMapped behavior
- Save button statesF16.save-statesKnown failure
- Keyboard and screen readersF16.keyboardMapped behavior
- Phone layoutF16.phoneMapped behavior
- Clear the title modelF16.title-model-clearMapped behavior
- Filter a dropdown by typingF16.dropdown-filterMapped behavior
- Browser vs backend scopeF16.browser-scopeMapped behavior
- Backend switch in placeF16.backend-switchMapped behavior
- After each groupF16 · setup / cleanupSupport step
- Hard Do Not TrackF16.analyticsMapped behavior
Family notes & prerequisites for known issues
- Two save models on one form: theme, checklist and voice input apply instantly and ignore Save; the rest is dropped silently if you navigate away before Save (filling
git-user-name-input, then clickingsidebar-settings-/settings/secretsand back, shows the storedopenhandsagain;browser dialogsis empty). Assert the instant ones without clicking Save, and never expect Save to enable for them. - The success toast uses the language that was active when you clicked Save, not the one you saved. In
F16.languagethe French Save toastsSettings saved, the Arabic Save toastsParamètres enregistrés, and the English restore toastsتم حفظ الإعدادات, sowait-text 'Settings saved'times out on the last two. Assert withbrowser text 'testid=submit-button'after a reload, or read the toast withbrowser toasts. - Some chrome strings stay English after a language switch: the sidebar Automate label in every language (the automation interface supplies it, not the translation file), and most of the command menu's own texts (placeholder
Search actions, pages, and settings..., the search box'sSearch commandsname, the group names and the item names) in French and 11 other languages. Only the Model Router and Agent Context items are translated (Routeur de modèlesandContexte de l'agentin French), because they reuse the settings navigation's titles. Do not treat the English ones as a language switch failure; the sidebar trigger'sSearch commandsis translated. - In Arabic (
dir="rtl") a switch that is on draws its thumb outside its track (onshow-getting-started-checklist-switchthe track spansx778–818 and the thumb 822–838). Assert switch state with.checked, not from a screenshot. - The switches are visually hidden native checkboxes: Use the label as the pointer target. Click the label text scoped to
testid=app-settings-screen, or use Tab/Space, and read.checkedthrougheval. role=option[name^=...]is not supported by the selector parser; userole=option >> has-text=<profile>for profile options whose names include the model.conversation startleaves the browser on the conversation page, which also has atestid=submit-button;goto /settings/appbefore the next settings step or clicks hit the composer.- Which profile actually generated a title is not visible in the UI, the conversation API or the stack logs;
F16.title-modelproves the preference is stored and a title appears, not which model wrote it. onboard --skipstores analytics off, so a fresh run starts with the switch unchecked even though the code defaults to on when the preference is missing.browser storagelistslocalStorage, andbrowser storage --sessionlistssessionStorage, where the voice-input key lives. With--valuesthat key prints as<redacted>, so the recipe reads its dummy value witheval. The key disappears in a new tab or browser session by design.- Deleting a profile through the LLM settings UI clears a matching title preference itself; only a profile removed outside the UI leaves a stale
title_llm_profilethat this page shows as Automatic. - The Title generation model combobox has a clear (×) button with no accessible name (
- buttonin the snapshot, visible as × at phone width). At desktop width it only takes clicks afterbrowser hoveron the input (F16.title-model-clear); otherwise use the Automatic option. browser evalwraps its argument as an expression: statements separated by;fail withSyntaxError: Unexpected token ';'; wrap them in(() => { ...; return x; })().- With
service stop agent-server, abrowser reloadof/settings/appshows the backend-unavailable screen (agent-server-onboarding-screen, Manage backends), not the form: stop the service only after the page is loaded, andrestartafterwards. - Known product bugs (repro candidates): git identity never reaches the agent (#17899); a failed save discards the user's edits (
F16.save-states) (#17927). - The harness builds with
VITE_DO_NOT_TRACK=1, so PostHog never starts:browser network --filter 'posthog|z\.openhands\.dev'reportstotal0, also after analytics consent is granted (#18086). A browser-only Do Not Track setting is outside this recipe. Consent reversal requires the explicit non-DNT build and loopback-only analytics configuration described above, served withlaunch --build never(F16.analytics). - The title model's clear button has no test id: the recipe's xpath relies on DOM nesting to skip the unnamed
Show suggestionsbutton. If both ever match, Playwright's strict mode fails the click instead of pressing the wrong one; report it as harness drift.
F17 Customize hub and MCP servers
31 behaviors · Read this family’s scripts
- Desktop entry pointsF17.customize-redirectMapped behavior
- Desktop sub-navigationF17.desktop-subnavMapped behavior
- Tablet selectorF17.tablet-selectorMapped behavior
- Phone hubF17.mobile-hub · F17.phoneMapped behavior
- Widths around the breakpointF17.breakpoint-sweepMapped behavior
- Page and empty stateF17.page-statesMapped behavior
- SearchF17.searchMapped behavior
- Section filterF17.section-filterMapped behavior
- Open and close the install modalF17.library-catalogMapped behavior
- Remote entry, masked keyF17.install-remoteMapped behavior
- OAuth entryF17.install-oauthKnown issue
- Entry that cannot be installedF17.install-unsupportedMapped behavior
- Install fails, modal staysF17.install-errorMapped behavior
- Install a STDIO entryF17.install-stdioMapped behavior
- Argument fieldsF17.install-argsMapped behavior
- Secret selection before installF17.save-as-secretMapped behavior
- Save as secretF17.save-as-secretMapped behavior
- Editor validationF17.custom-validationMapped behavior
- Test connectionF17.test-connectionMapped behavior
- Add the serverF17.custom-addMapped behavior
- Custom remote serverF17.custom-add-remoteMapped behavior
- Card healthF17.server-healthMapped behavior
- DeleteF17.delete-serverMapped behavior
- EditF17.custom-editMapped behavior
- Stored secrets are reused, not their placeholderF17.stored-secret-reuseMapped behavior
- One request per mutationF17.single-request-mutationsMapped behavior
- Credential probeF17.credential-probeKnown failure
- One error per stale mutationF17.delete-server · F17.enable-disableKnown issue
- The agent uses itF17.agent-uses-serverKnown issue
- Enable and disableF17.enable-disableKnown issue
- Phone modalsF17.phoneMapped behavior
- Cloud backendF17.cloud-nav · F17.native-git-tabsBlocked
- CleanupF17 · setup / cleanupSupport step
- Health belongs to a backendF17.server-healthKnown failure
- Incomplete sibling must not hide working toolsF17.custom-add · F17.agent-uses-serverKnown failureKnown issue
- Unreachable MCP degrades initializationF17.agent-uses-serverKnown issue
- MCP timeout leaves initializationF17.agent-uses-serverKnown issue
Family notes & prerequisites for known issues
- Server errors on MCP mutations show one toast with the server's message, or
An error occurredwhen the body has none. A custom server's Save Server or Add Server action whose pre-save connection test fails keeps the editor open. To check backend loss, stop the owned Agent Server with the editor open, click Save, then restore it withcontrol-openhands restart; background settings polls can add separate error toasts, so count only the toast caused by the click. A failed add, edit or delete is retried three times (withRetryinsettings-service.api.ts, 0.5 s and 1 s apart) before its single toast; that retry behavior is open #17932. - Desktop
/customizeis a client-side redirect:browser urlmay still read/customizefor a moment; usewait-url '/mcp(\?|$)'. - From 768 to 1023 px the sidebar rail stays and the phone top bar is gone. The compact Customize selector above each detail page provides sibling navigation; the rail's Customize link (
sidebar-skills-link, unscoped at this width) still returns to the hub. - On a phone the drawer and the hidden desktop rail both render
sidebar-skills-link; scope it withtestid=sidebar-mobile-drawer >> ...or the click fails with a strict-mode error, even thoughbrowser testidslists it once. - Editor dropdowns are comboboxes: click
server-type-dropdownorauth-mode-dropdown, thenrole=option[name="..."]. Server types readSSE,STDIOandSHTTP(not "Streamable HTTP"); auth modes readNone,Bearer token,HeaderandOAuth. The type dropdown exists only when adding. - The timeout field is
type="number":browser fillrefuses letters, soTimeout must be a valid numbercannot be reached from the UI. - A red test message stays on screen when a later validation error appears, so
css=p.text-feedback-errorcan match two paragraphs; take>> nth=0(the validation error comes first). - Install-modal required fields use native browser validation (a tooltip, no paragraph): assert
validationMessage. - The installed and library toggles are
role=switchbuttons: readaria-checked, notaria-pressed. - MCP stdio servers start with a minimal environment. Behind a TLS-intercepting proxy, without trust settings in the run's private
HOME,uvxcatalog installs fail withConnection closed(<run>/private/stack.logshowsUnknownIssuer) andnpxones withConnection timed out. That is the sandbox, not the product.launchnow seeds the trust files fromSSL_CERT_FILE/NODE_EXTRA_CA_CERTS, so a fresh run installs fine andF17.install-errormust move them aside; once a package is in the run's uv cache it installs even without them. - An installed card's health row swallows clicks (so the probe button does not open the editor). On a card without a catalog description (
qa_broken) that row is the card's centre, so a plain card click opens nothing; a catalog description moves it down. Open the editor by the card's name ormcp-server-detail-<id>line, or focus the card and press Enter. conversation startleaves the browser on the conversation page; every MCP-page command after it needsbrowser goto /mcpfirst, or the per-card selectors silently wait on a page that has none.@modelcontextprotocol/server-everything sseprintedServer is runninghere but never answered on its port; use thestreamableHttpmode for the remote-server fixture.- A server without a catalog credential probe reads
Reachable — credentials not verified, neverConnected — credentials verified (N tool(s)), even without credentials. Health after a save is seeded from the pre-save test and is lost on reload (Not checked yet). - Adding a custom server shows no toast; only catalog installs and deletes toast. Assert the card after reload.
- Catalog installs are add-only: a second Time install becomes
time_1. STDIO servers match the catalog by command plus leading args rather than name, sotime_1and a custom server running a catalog command under its own name (qa_time) retain the description, badge and search keywords. A server that only borrows a catalog name does not (F17.install-stdio,F17.custom-add). Twelve provider-OAuth-only library entries, such as Sentry, HubSpot and Cloudflare OAuth, open an empty modal whose Install does nothing (F17.install-unsupported, #17922). - The section filter's trigger and menu are named
Filter MCP servers. - Header and environment-variable format errors have distinct copy.
F17.custom-validationexpectsHeaders must follow KEY=value formatfor headers andEnvironment variables must follow KEY=value formatfor env lines. Feedback uses readable theme classestext-feedback-errorandtext-feedback-success. - A catalog stdio server runs with the Agent Server's minimal environment: behind a TLS-intercepting proxy its own HTTPS calls fail (
fetch failed) even when npx could download it, and the install modal has no field forNODE_EXTRA_CA_CERTS; use the custom editor with the same command to see the provider's real answer (F17.credential-probe). TheCredential check failed: fetch failedwording itself is #18161: the Slack interpreter turns anyis_errortool result into a credential failure, though the server connected and listed its tools. - GitHub's hosted MCP endpoint answers an invalid token with HTTP 401 at connect, before tools are listed, so its
get_meprobe never runs and the modal shows the connection wording (Connection failed: HTTPStatusError … 401 Unauthorized), notCredential check failed; filed as OpenHands/software-agent-sdk#5607, since the test endpoint reports the 401 aserror_kindunknown. - The shell-gated
qa_vaultfixture exits before the MCP handshake, which the Agent Server reports either at once asConnection failed: McpError: Connection closedor only at its deadline asConnection timed out. Check the URL and try again.; neither is theCould not start the server commandwording, which needs a command that cannot be spawned at all. Wait ontext=Connection, which matches both and notConnected — …. browser network --bodiesshows what the page sent, never a secret: a value under a key that names a credential (key, token, secret, auth, pass, session, sig, credential) and every value of anenvorheadersmap becomes<redacted N chars>(N the real length), and a URL in any other string (a server'surl) keeps its host and path but loses its userinfo and the values of its secret-named query parameters (https://<redacted 2 chars>:<redacted 8 chars>@host/mcp?api_key=<redacted 17 chars>), while the settings API's**********placeholder is kept as is, so a row tells "placeholder sent" from "a value sent". The MCP editor sends neither for an untouched secret: Test connection swaps the placeholder for the stored encrypted value (aGET /api/settingsinencryptedmode first; Fernet tokens, so 120 chars for a 19-char token, 140 for 40, 268 for 142) and Save leavesenvout of its sparse PATCH altogether (F17.stored-secret-reuse). Without--bodiesno row carries abodyfield, and only app-origin writes keep one.- A browser verb's client call waits 120 s, or 10 s longer than the verb's own
--timeoutor--observe-mswhen that is longer, sobrowser wait 'testid=mcp-install-modal-error' --timeout 150000runs its full deadline and a miss ends with Playwright's timeout and a failure screenshot (before this, every call was aborted at 120 s withTimeoutError: The operation was aborted due to timeoutwhile the page kept going). For a first Slack install use a plain click, then thatwait;--observe-msis for a few transient states, not a minute-long outcome. - Known issue #17941: turning off an enabled card toggle can drop the click when the pointer moves in and presses at once (
F17.enable-disable). - Known issue #15421: A configured Linear MCP can be ignored while an explicitly disabled Linear skill is used instead. The new-chat and automation paths need a working authorized Linear MCP connection, a concrete issue ID and an approved model; the report's automation ZIP is also needed to replay its exact automation settings. (
F17.agent-uses-server). - Known issue #15430: An OAuth MCP callback in Docker can redirect to an unexposed dynamic localhost port. Completing the callback needs a Docker stack and an approved OAuth MCP provider/account (the report uses GitLab); a local unauthenticated Test connection cannot reach the redirect. (
F17.install-oauth). - Known issue OpenHands/software-agent-sdk#5375: A successful GitLab OAuth login can be followed by an invalid localhost redirect URI on the first ticket-to-code-change MCP action. Reproduction needs the authorized self-hosted GitLab MCP endpoint/account and the ticket-to-code-change plugin/workflow; the reported endpoint is not a public fixture. (
F17.install-oauth,F17.agent-uses-server).
F18 Skills catalog
22 behaviors · Read this family’s scripts
- Open from the sidebarF18.pageKnown issue
- Command-menu entryF18.pageKnown issue
- SearchF18.searchMapped behavior
- Back and forwardF18.search-historyMapped behavior
- FacetsF18.facetsMapped behavior
- Source and Type facetsF18.facetsMapped behavior
- Deep linkF18.facetsMapped behavior
- Card and pill overflowF18.cardMapped behavior
- Keyboard openF18.cardMapped behavior
- Copy the source pathF18.copy-sourceMapped behavior
- Toggle a built-in skillF18.toggleMapped behavior
- Toggle a personal skillF18.toggle-localMapped behavior
- Skill reaches chatF18.skill-in-chatKnown issue
- Project skill in a workspaceF18.project-skillKnown issueBlocked
- Deleted personal skillF18.skill-deletedMapped behavior
- Both personal skill foldersF18.personal-skill-dirsMapped behavior
- Save failureF18.toggle-errorMapped behavior
- Detail modal and switchF18.detail-modalMapped behavior
- Close the modalF18.detail-closeMapped behavior
- Pill overflow in the modalF18.detail-pillsMapped behavior
- Use skillF18.use-skillMapped behavior
- Add skill instructionsF18.add-skill-modalMapped behavior
- Install bannerF18.install-bannerMapped behavior
- Same-name source filteringF18.facetsKnown failure
- Filters modal on a phoneF18.filters-modalMapped behavior
- Phone layout and hubF18.phoneMapped behavior
- Cloud linkF18.cloud-linkBlocked
- RestoreF18 · setup / cleanupSupport step
- Colliding skill names do not leave ghost cardsF18.card · F18.facetsKnown failure
- Skill state survives a delayed sampleF18.toggleMapped behavior
- Backend switch refreshes skill dataF18.pageKnown failureKnown issue
- Persistence folder skill loadsF18.personal-skill-dirsMapped behavior
Family notes & prerequisites for known issues
sidebar-skills-linkis labelled Customize and lands on/mcpon desktop (/customizeredirects); Skills is one more click. Test ids embed the route: quote'testid=sidebar-extensions-/skills'.- A
browser clickon an enabled card toggle is lost when the pointer was not already over it:pointerenterswaps the checkmark icon for the X icon between mousedown and mouseup, so Chrome fires no click and noPATCH /api/settingsgoes out (#17941).browser hoverthe toggle first (or click twice). Turning a skill on is not affected. Recorded asfailonF18.toggle. - The card toggle and the facet rows are
role=switch/role=checkboxbuttons: readaria-checked. The modal switch is ansr-onlycheckbox (keyboard reachable): click the row text and read.checkedwithbrowser eval. - Typing writes
?q=withreplaceafter a 300 ms debounce, so readbrowser urla second later; facet clicks push a history entry immediately. - Facet counts are disjunctive: a row counts skills matching the other groups' selections, so Disabled reads
0(and is disabled) while Recommended is checked. - Groups with fewer than two values are hidden (Source and Type on a fresh run) unless the URL selects one of their values.
- The run's
HOMElives under/tmp, so a skill in~/.agents/skillsis filed under Source This project (source=project), not Personal; with a real/home/<user>or/Users/<user>home it would be Personal. conversation eventsrows show a userMessageEvent's activated skills asskills: [...](since #18162).api GET '/api/conversations/<id>/events/search?limit=5' --max-bytes 2000000shows the rawactivated_skills, but only when the user row is among those five events. On 2026-10-08 it was not: the first five were the system prompt and state updates.- Skill lists are cached for 10 minutes:
browser reload(orgoto) after the agent creates a skill file, or the new card does not appear. navigator.clipboard.readText()throughbrowser evalhangs (no clipboard permission in the page); read what a copy button wrote withcontrol-openhands browser clipboardand assert the button'saria-labeltoo. The app runs on127.0.0.1(a secure context), so the unguardedclipboard.writeTextcalls cannot be tested for insecure-origin failures here.- With the Agent Server stopped, reloading
/skillsshows the "Manage backends / Disconnected" screen instead of the page: load the page first, then stop the service. After the failed save the card keeps showing the new state until a reload (#17941). - Escape from the modal's focused
+Noverflow trigger closes only the popover and restores trigger focus; the next Escape closes the detail modal. The card popover uses the same Escape behavior. - The Add skill example, its Copy button and the add-skill Use skill message share the
.../skills/code-reviewpath. - Skill changes apply to new conversations only; an open conversation keeps the skills it started with.
conversation events --grepsearches whole events, the user's message text included: a trigger that contains the skill name (qa-gone-pingforqa-gone) matches the userMessageEventeven when the skill is not loaded. Give fixture skills a trigger that does not contain their name, or grep for<name>qa-gone</name>.fixture skill --repowrites the projectSKILL.mdand records it in the repo only with--commit(committed.sha; a re-run reportsunchanged); a New Worktree conversation checks out the repo's commits, so pass--commit. Workspace skills are loaded per conversation and never appear on/skills.- Without an LLM key the skill set is still observable: the
SystemPromptEvent(available skills), the userMessageEvent(activated_skills) and the chat's Skill Ready row (generic-event-message-title; Expand lists the skills underTriggered Skill Knowledge:) all exist before the first model call, after which the conversation ends inerror. - Known issue #16298: A Slack-monitor setup can leave the agent without the expected skill. The report omits the concrete monitor setup and loaded skill name/version; reproducing the runtime also needs an approved model and a configured Slack integration. Listing the bundled catalog alone cannot settle it. (
F18.skill-in-chat). - Known issue #15458: The global Skills page can list AGENTS.md files from cloned automation-run worktrees. The report says the discovery trigger is unknown; replay needs the affected automation workspace/discovery-root layout or captured request parameters, rather than only a normal project-skill fixture. (
F18.page,F18.project-skill).
F19 Plugins and plugin launch
25 behaviors · Read this family’s scripts
- Open the pageF19.pageMapped behavior
- Command-menu entryF19.pageMapped behavior
- SearchF19.searchMapped behavior
- Status filterF19.status-filterMapped behavior
- Detail modalF19.detail-modalMapped behavior
- FilesF19.files-browserMapped behavior
- Install from a cardF19.install-cardMapped behavior
- Enable switchF19.enable-toggleKnown issue
- Enabled plugins auto-loadF19.enabled-autoloadMapped behavior
- UpdateF19.refreshKnown failureKnown issue
- Start a conversation from an installed pluginF19.start-conversationMapped behavior
- UninstallF19.uninstallMapped behavior
- Install from the modalF19.install-modalMapped behavior
- Cancel Add pluginF19.add-plugin-cancelMapped behavior
- Add plugin form and errorF19.add-plugin · F19.add-plugin-errorMapped behavior
- Add plugin from GitHubF19.add-pluginMapped behavior
- Installed coordinatesF19.installed-coordinatesMapped behavior
- Local pluginF19.local-pluginMapped behavior
- Start a conversation from the catalogF19.start-conversation · F19.launch-trustMapped behavior
- Review screenF19.launch-reviewMapped behavior
- ParametersF19.launch-parametersMapped behavior
- Dev formatF19.launch-dev-paramsMapped behavior
- Error statesF19.launch-errorsMapped behavior
- Creation failureF19.launch-creation-failedMapped behavior
- Non-ASCII deep linkF19.launch-unicodeMapped behavior
- PhoneF19.phoneMapped behavior
- Errors sweepF19.pageMapped behavior
- Launch trust shows actual hostF19.launch-trustKnown failure
- Unicode parameter round-tripF19.launch-unicodeKnown failure
- Cached source rejects an unknown refF19.add-pluginKnown failure
- Update retains a requested pinF19.refreshKnown failureKnown issue
- A malformed optional plugin does not block the first messageF19.enabled-autoloadKnown failure
- Disabled plugin reconciles on resumeF19.enabled-autoloadKnown failure
- Unavailable plugin source is a handled Update errorF19.refreshKnown failureKnown issue
Family notes & prerequisites for known issues
- The card switch swaps its icon on hover. A plain
browser clickthat moves the pointer onto it from elsewhere (for example right after clicking a filter segment) is often swallowed (#17941): noPATCH /api/plugins/installed/<name>shows inbrowser network. Runbrowser hoveron the switch first, then click, and assertaria-checkedand the API, not the click result. - Installed plugins lose their source and their enabled state, intermittently (OpenHands/software-agent-sdk#5496). The Agent Server rewrites
<run>/private/plugins/installed/.installed.jsonwith a plain truncate-and-write on every load (SDKInstallationMetadata.save_to_dir), so a concurrentGET /api/plugins/installed(page loads fire several) can read an empty file: it logsFailed to load installed extension metadata … Invalid JSON: EOF while parsingandDiscovered untracked extension, then saves every plugin with"source": "local","enabled": trueand a freshinstalled_at. It hit catalog installs in most trials and a disabled plugin on 2 of 3 page revisits; GitHub installs kept their source in this run. Once it hits, the card showslocal, Update fails with a 500, Start Conversation builds an unusable/launchlink, and a disabled plugin silently auto-loads again. Prove the launch path from a card that is not installed, and re-read the API after every navigation. - A failed plugin install, update or uninstall shows one toast with the server's reason (enable uses the same handler; its failure is not driven here). A response with no reason in it, such as the ingress's 502 while the Agent Server is stopped, shows the generic
An error occurred; read the cause in the run'sprivate/stack.log. - Installing a plugin whose name is already installed points the user to Update or Uninstall, as Apps do (
F20.install-duplicate): with the catalogmagic-testinstalled, Add plugin withgithub:OpenHands/extensionsand Pathplugins/magic-testanswers 409 (browser network --filter 'plugins/install') andbrowser toasts --historyholds one toast,This plugin is already installed. Open its card to Update or Uninstall it., instead of the server'sforce=truehint; the modal stays open with the typed values (browser screenshot --feature F19.add-plugin-error --name duplicate-409). Other install errors still toast the server's reason (F19.add-plugin-error). The 409 adds onehttp-errorand oneconsole.errortobrowser errors --app-only. - Uninstall acts immediately, with no confirmation (MCP server delete and App uninstall confirm).
/launchwith amessagestarts the agent as soon as Start Conversation is clicked. Prefer links without a message and sendalakazamyourself; acity-weatherlaunch with a message makes the agent call an external weather API (stop it withtestid=stop-button).- Edited launch parameters cannot be observed after creation: the conversation's client metadata (
localStorage['openhands-agent-server-conversation-metadata']) strips them and the Agent Server does not return a conversation's plugins. Proving delivery needs request-body capture (harness gap). conversation startand launches leave the browser on a conversation page, which has its ownchat-input;browser goto /pluginsbefore the next card step.- Build deep links with URL-encoded base64 (
%2B,%2F,%3D): a raw+decodes to a space and gives the invalid-format error. Non-ASCII text must not be used in payloads (atobdecodes bytes as Latin-1). - The page loads three queries (marketplace, installed, local) behind skeleton rows; wait for
testid=plugins-toolbarbefore counting cards. With no plugins at all the page showsNo plugins found.(plugins-empty), which the bundled catalog makes unreachable; on a Cloud backend Add plugin and card actions are disabled (not driven: no Cloud account). - Local plugins under
~/.agents/pluginsappear on the next page load without a restart; the Agent Server'sHOMEis<run>/private/home. - Known issue OpenHands/software-agent-sdk#5985: Update can re-enable a disabled plugin when an installed-list request overlaps the force-reinstall directory swap. A live check needs an owned disabled plugin and a real concurrent list that lands in that window; the report's monkeypatched
copytreeschedule is not Canvas live proof. No overlap has been proved in this pass. (F19.refresh,F19.enable-toggle).
F20 Canvas apps
24 behaviors · Read this family’s scripts
- Sidebar entry and empty pageF20.entry-points · F20.pageMapped behavior
- Command-menu entryF20.entry-pointsMapped behavior
- Add form and its closersF20.add-modalMapped behavior
- Install error, local pathF20.install-errorMapped behavior
- Install error, Git sourceF20.install-errorMapped behavior
- Install the demoF20.installMapped behavior
- CardF20.cardMapped behavior
- Trust confirmationF20.enable-confirmMapped behavior
- Rail entryF20.rail-entry · F20.rail-labelMapped behavior
- Render the pageF20.page-renderMapped behavior
- App backend viewF20.app-backend-viewKnown issue
- Active and collapsed rail entryF20.rail-activeMapped behavior
- Unavailable pageF20.page-unavailableMapped behavior
- PhoneF20.phoneMapped behavior
- UpdateF20.refreshMapped behavior
- Survives a restartF20.persist-restartMapped behavior
- Update with the backend downF20.refreshMapped behavior
- DisableF20.disableMapped behavior
- UninstallF20.uninstallMapped behavior
- Local source plus PathF20.installMapped behavior
- Git tree URLF20.git-tree-urlMapped behavior
- Duplicate installF20.install-duplicateMapped behavior
- Busy lockF20.busy-lockMapped behavior
- Ref and Path with the `github:` shorthandF20.git-ref-pathMapped behavior
- List error with RetryF20.load-errorBlocked
- Unsupported backendsF20.unsupportedBlocked
- Malformed tree-URL escapesF20.git-tree-url · F20.install-errorKnown failure
- Extension page home pinF20.rail-entryKnown failure
Family notes & prerequisites for known issues
- The card's refresh button (
canvas-extension-refresh-<name>) is labelled Update, not "Refresh". - The trust confirmation has no title and reuses the shared
confirmation-modal; its body repeats the amber notice. Space on the disabled app's Enable switch focuses Cancel. Tab and Shift+Tab wrap between Cancel and Enable trusted app; Escape and Cancel close it and restore focus to the still-disabled Enable switch. nav_labelis dropped by the Agent Server:GET /api/canvas-extensions/installedreturns pages with onlyid,titleandpath(Agent Server 1.50.1), so the rail shows the page title (OpenHands/software-agent-sdk#5501). KeepF20.rail-labelfailing until the backend returns it.- Install and update errors show the server's reason as sent, even when it says
Failed to fetch extension from <url>(an unreachable Git source). A response with no reason in it, such as the ingress's502while the Agent Server is stopped, shows the genericAn error occurred. Only a request that gets no response at all showsDisconnected (check URL or network)…; nocontrol-openhandsverb takes the ingress offline, so that state is not driven here. - The page states (empty, error, unsupported) and the
/extensions/...unavailable card have no test ids; assert on text withbrowser snapshot. - The Agent Server fetches Git sources with a shallow clone and appends
.gitto the repo URL: a test Git server must speak smart HTTP and answer bothqa-repoandqa-repo.git. - The Git bullets read the public upstream repo, so they depend on its
mainstill holding the identical fixture; the precondition'sdiff -rguards that. A Git install or Update clones in about 0.4 to 2 s here (Updates measured about 0.4 to 1.5 s on 2026-10-06), long enough for the busy-lock checks when they run in the same shell line as the click and read both controls in oneeval; on a slower network raise thewaittimeouts, not the expectations. - A duplicate install answers
409with the Agent Server's API hint (Canvas extension already installed. Use force=true to overwrite.); the form has no force option, so the toast replaces it with the Update/Uninstall advice. Plugins give the same advice since #18110 (F19 Gotchas). - Busy states with a local-path source last about 50 ms:
--observecatchesInstalling…, but checking that controls are disabled during Update needs a Git source (an upstream Update lasts about 0.4 to 2 s). control-openhands launchpasses the launcher only a fixed list of environment variables (path, locale, proxy) plus its own flags:OH_AGENT_SERVER_VERSION=<old>in the environment is ignored (the run still gets the pinned server); use--sdk-ref v<version>. Any server older than 1.47.0 is gated by Canvas before/appsrenders.- Stopping the Agent Server makes the next full page load show the Manage backends gate; always
restartanddoctorafterwards. - A trailing
browser errors --app-onlysweep shows a400per failed install by design; count only other errors. App backend view unavailableon the demo page is the expected text whileGET /server_infolists nocanvas_app_backend_bridge_v1capability (Agent Server 1.53.0); it does not mean the app failed to load. Cloud backends and the no-backend state never get a backend view either.- Known issue OpenHands/software-agent-sdk#5648 (
F20.app-backend-view): app-backend WebSocket subprotocols are reported dropped. Recheck on a Linux Agent Server with configured public ingress and reviewed platform-matching backend artifacts, using a genuine admitted app-backend session and subprotocol negotiation. SDK 1.55.0 supports only Linux app-backend artifacts, so a native macOS server cannot drive this branch. A default demo without the bridge capability cannot exercise the proxied WebSocket path. - Known issue OpenHands/software-agent-sdk#5935 (
F20.app-backend-view): an explicitOH_APP_BACKEND_PUBLIC_URL_IS_NONE=1does not clear a bridge URL set in the Agent Server JSON configuration. Canvas can therefore be offered an app-backend view at the unwanted configured ingress. Recheck an owned bridge-capable server with a JSON public URL and that environment-null override, then inspect/server_infoand the real app page; the default launcher has neither conflicting configuration source. - Known issue OpenHands/software-agent-sdk#5914 (
F20.app-backend-view): app-backend HTTP responses can carry both the backend's and the Agent Server'sDateandServerheaders, producing an invalid joined date and disclosing the backend stack. Recheck a reviewed HTTP app backend on a supported Linux Agent Server that sends these headers through a real admitted app-backend session. A default demo page without the bridge capability or a direct backend request cannot establish the proxied response.
F21 Automations dashboard and actions
35 behaviors · Read this family’s scripts
- Sidebar entryF21.sidebar-entryMapped behavior
- Command menuF21.command-menuMapped behavior
- Pin as homeF21.pin-homeMapped behavior
- Sub-page navigationF21.subpage-navMapped behavior
- Backend unavailableF21.backend-unavailableKnown issue
- List errorF21.list-errorKnown issue
- List loadingF21.list-loadingMapped behavior
- Health loadingF21.health-loadingMapped behavior
- Missing manifestF21.manifest-404Known failure
- Empty stateF21.empty-stateMapped behavior
- Add Automation menuF21.add-menuMapped behavior
- Recommended rail on the empty dashboardF21.empty-railMapped behavior
- Saved draftsF21.saved-drafts · F21.searchMapped behavior
- Arrange two automations (import, F22)F21 · setup / cleanupSupport step
- Grid cardsF21.card-gridKnown issue
- Kebab menuF21.kebab-menuMapped behavior
- Turn onF21.toggleMapped behavior
- Run now from PlayF21.run-nowMapped behavior
- List viewF21.view-toggle · F21.list-rowMapped behavior
- Hover previewsF21.row-tooltip · F21.summary-hovercardMapped behavior
- Sparkline deep linkF21.sparkline-deeplinkMapped behavior
- SearchF21.searchMapped behavior
- Filtered empty and Clear filtersF21.filtered-emptyMapped behavior
- FiltersF21.filtersMapped behavior
- Turn offF21.toggleMapped behavior
- Edit from the dashboardF21.editKnown failure
- SortF21.sortMapped behavior
- ExportF21.exportMapped behavior
- Open the detail pageF21.open-detailMapped behavior
- Git Sync buttonF21.git-sync-buttonMapped behavior
- Needs attention, kebab Run nowF21.overview-tiles · F21.run-now · F21.filtersKnown issue
- Run now errorF21.run-now-errorKnown failure
- Delete with confirmationF21.deleteMapped behavior
- Load moreF21.load-moreMapped behavior
- PhoneF21.phone · F21.subpage-navMapped behavior
- ErrorsF21 · setup / cleanupSupport step
Family notes & prerequisites for known issues
- Both sub-page navs are always in the DOM (one hidden by CSS). Unscoped
testid=automations-navigation-templatesis a strict-mode violation; scope it withtestid=automations-navbar-desktop >>ortestid=automations-navbar-mobile >>. - The pin toggle is invisible until the Automate item is hovered on a fine pointer:
browser hover 'testid=sidebar-automations-link'before clicking it. The pin is stored per backend and org inlocalStorage(oh:pinned-home-route:<backend>:<org>); unpin before leaving the run. - The Filters popover's status and trigger choices do not apply to the Drafts group: with status Active and trigger Event-driven, a cron draft stays listed and the filtered empty state does not show (search does filter drafts). Intent undocumented in #17242.
- The setup page's success toast (
Automation updated) covers its toolbar's Test, Save and Close and does not time out while the pointer rests on it; a click there fails with "subtree intercepts pointer events". Move the pointer away (browser hoveron a form field), wait about 5 s, then click. testid=dropdown-triggeris reused by the backend selector, the Filters button and every inner dropdown. Always scope it (testid=automations-filters >> testid=dropdown-trigger >> nth=0for the Filters button,testid=automations-filter-status >> testid=dropdown-triggerfor a field).- The Filters popover stays open while choices change and closes only on a click outside it or on the Filters button; Escape does not close it. Open, it covers the right part of the list (in list view the first rows' Play buttons): close it with a click on
role=heading[name="Dashboard"]before clicking row or card controls. - A card whose automation was deleted elsewhere stays on the dashboard after its Run now fails with
Automation not found. Expected: the card drops out once the dispatch returns 404. Known failure: nothing refetches the list after the failed dispatch, so the card stays until a reload or another list refetch (still there 2 minutes later) (#18062). - The delete confirmation has no test ids; scope it as the named dialog
role=dialog[name="Delete automation"]. It opens with focus on Cancel. - Delete closes the dialog at once and shows no success toast; confirm with a reload. Turn off on the dashboard never asks for confirmation (home cards do).
- The kebab menu has no test ids;
role=list >> has-text=Exportis the reliable scope. A card's own Run now has the same accessible name as the kebab item, so scope Play to the card. - Imported automations are always disabled (
Import automationsays so), and Run now is disabled until you Turn on. Use the yearly cron0 0 1 1 *or an event trigger so an enabled fixture never fires by itself, and turn it back off. - Run now uses the active LLM profile when the automation's model is
Active profile. A successful run creates a conversation titled<automation name> — <UTC timestamp>that stays after the automation is deleted. Delete it separately (control-openhands conversation list, conversations family) to leave the run clean. - A timeout of 1 s does not fail fast: the run sat in
Installing dependenciesand failed withTimed out: command timed out or was killedabout 3-4 minutes after dispatch. Budget for that when you need a failing run for Needs attention. - The Automations tile counts only loaded pages: with 51 automations it reads
50until Load more is clicked, although the APItotalis 51. - The row health dot and label reflect the latest run only; a disabled automation with no runs reads
No activity yet, notDisabled. - In grid view a cron automation without
schedule_humanshows the pillcron, while list view shows the raw expression (0 0 1 1 *). - The view mode persists in
localStorage(openhands-automations-view), and the toggle is disabled when the org has no automations. Switch back to Grid before deleting the last automation, or the next run starts in List. - Filters, search and sort are page state only: a reload resets them.
service stop automationstops only this run's automation service;restartbrings the whole stack back with the same state and the browser on the same page. Runcontrol-openhands doctorafterwards.- The Automation dispatched toast lasts only a few seconds: run
browser wait-text 'Automation dispatched'right after the click, not after a long--observewindow. browser screenshot --full-pageat phone width does not capture below the fold, because the page scrolls inside the main pane; screenshot sections or usebbox.- Known issue OpenHands/automation#246 (
F21.backend-unavailable,F21.list-error): The report says only that local automation returns 404. It omits the URL, UI action, release and launcher/service setup, so a normal successful dashboard visit would not reproduce or resolve its unknown branch. Ask for those exact prerequisites before writing a failing recipe. - Known issue OpenHands/automation#347 (
F21.card-grid,F21.overview-tiles): per-automation run-summary reads lack an aggregate contract, and the report describes a 30 s shared-resource stall with HTTP 500 plus SQLite pool settings that do not apply. A failing recipe needs the original database/lock workload and redacted service-log/HAR timing evidence, which the report withholds. Successful summary reads under the Canvas request throttle do not establish those backend contracts.
F22 Creating automations: templates, setup and import
29 behaviors · Read this family’s scripts
- Templates pageF22.templates-pageMapped behavior
- Cards and pillsF22.template-cardMapped behavior
- SearchF22.templates-searchKnown issue
- Card opens setup, prerequisitesF22.template-launch-setup · F22.setup-prerequisitesMapped behavior
- ValidationF22.setup-form-validationMapped behavior
- Setup form colours (`F22.setup-form-validation`, #18330)F22.setup-form-validationMapped behavior
- Action kindsF22.setup-action-kindMapped behavior
- Agent profileF22.setup-agent-profileMapped behavior
- Review and createF22.setup-review-confirmKnown issue
- Plugin action and timezoneF22.setup-plugin-createKnown issue
- Upload tarball action, with an agent profileF22.setup-tarball-create · F22.setup-agent-profileKnown issue
- CloseF22.setup-closeMapped behavior
- Bundle entry, min lengthF22.setup-bundle-create · F22.setup-form-validationMapped behavior
- Repository listF22.setup-repository-listKnown issue
- Blocking prerequisiteF22.setup-prerequisitesMapped behavior
- Not available and fallbackF22.setup-unsupported · F22.setup-fallback-conversationMapped behavior
- Unknown idF22.setup-unknown-idMapped behavior
- Responder choiceF22.responder-deployment-choiceMapped behavior
- Responder launch with Slack installedF22.responder-local-launchMapped behavior
- Install queueF22.template-mcp-install-queueBlocked
- Prompt launchF22.template-launch-conversationBlocked
- Open and save a draft (`F22.agent-assisted-setup`, desktop and phone)F22.agent-assisted-setupMapped behavior
- Credential-free script testF22.agent-assisted-setupMapped behavior
- Resume at phone widthF22.agent-assisted-setupMapped behavior
- Agent fills a prompt form (`F22.agent-assisted-setup`, desktop)F22.agent-assisted-setupMapped behavior
- Desktop Hide/Show and phone viewsF22.agent-assisted-setupMapped behavior
- Fresh phone prompt and genuine Run nowF22.agent-assisted-setupMapped behavior
- Agent-created plugin (`F22.agent-assisted-setup`, desktop and fresh phone)F22.agent-assisted-setupMapped behavior
- Genuine prompt/plugin draft TestF22.agent-assisted-setupKnown failure
- Setup fixture cleanupF22.agent-assisted-setupMapped behavior
- Import pickerF22.import-pickerMapped behavior
- Bad filesF22.import-validationMapped behavior
- Preview and cancelF22.import-previewMapped behavior
- ImportF22.import-confirmMapped behavior
- Choose fileF22.import-choose-fileMapped behavior
- Drop a fileF22.import-dropzoneMapped behavior
- PhoneF22.phoneMapped behavior
- CleanupF22 · setup / cleanupSupport step
- Malformed catalog entryF22.template-card · F22.templates-pageKnown failure
Family notes & prerequisites for known issues
- Expected: a completed draft test updates the open Test runs row to Successful automatically. Known failure (reproduced again 2026-10-13 on a desktop prompt draft: run COMPLETED at 08:13:39, row still Pending after a further 45 s wait; verified 2026-10-10, fresh Local stacks, Agent Server 1.54.0/automation 1.19.3): callback-only script tests and genuine DeepSeek prompt/plugin tests report COMPLETED while the open row stays Pending. The desktop prompt stayed Pending through a 45-second wait; the phone plugin capture was more than 201 seconds after completion. Reload and View test runs recover Successful (#18263). Ordinary final-automation Run now polling passes; reload recovery does not waive the draft-Test failure.
- The Save toast can cover the setup toolbar Test button; use the lower
automation-setup-draft-testand verify the actual run outcome. The toast does not time out while the pointer rests on it, so move the pointer away (browser hoveron a form field) before clicking the toolbar again. - The setup page's docked composer keeps no draft: it opens empty even when the Home composer has an unsent draft (
sessionStorageoh:home-prompt-draft), a prompt sent from it never becomes the Home draft, and leaving it keeps an existing Home draft. Unsent text typed there is lost when the user leaves the page. - In the desktop split view (form beside the conversation) the Frequency strip scrolls horizontally inside the narrower form and the selected Custom button sits off-screen; scroll it into view before reading it.
- Dashboard draft Delete asks in the named dialog
role=dialog[name="Delete draft?"](F21.saved-drafts). Deleting a draft also removes its materialized test automation. - A card click and a deep link are different paths: from the grid, GitHub/Slack-only responders (
qa-changes,github-agents-md-maintainer,slack-channel-monitor, …) first show the responder choice and then the GitHub/Slack install dialog, so their setup form is reachable locally only by URL (/automations/new/<id>). - A card's
N MCPs to connect before launchpill counts optional integrations too: Custom automation shows1 MCPs to connect before launchfor GitHub, yet opens its setup at once because GitHub is optional there (#17959). - The featured-section copy says picking a card opens "a pre-filled conversation"; most featured cards open a setup form instead.
- The setup dialog's comboboxes (Action, Agent profile, Timezone, LLM profile) are autocomplete inputs: click the field and pick the option in the same breath, scoped as
role=listbox >> role=option[name="…"]. Abrowser snapshotbetween the two closes the listbox (reproduced twice), and the option click then times out after 30 s; click the field again. - Service preflight runs 400 ms after a blur, not on every keystroke;
browser press Tabthenbrowser waitfor the-errorelement. - Confirm and create creates the automation enabled; only imports arrive disabled. Use a yearly cron (
0 0 1 1 *) so nothing fires during the run. - The Daily news digest entry names its automation
Daily news digest(noQA_prefix); remember it in cleanup. - The Agent profile combobox exists only while the chosen action creates through
/v1(Upload tarball, bundle entries): the automation service rejectsagent_profile_idon/v1/preset/promptand/v1/preset/plugin, so the Prompt and Plugin actions hide it and switching to them clears a chosen profile. Leave it onDefaultexcept in the Upload tarball bullet. A cleared choice is stored as an empty id and shown asDefault(#18111). - The automation detail page has no
mainlandmark: read its title withbrowser text 'role=heading[level=1]', not'role=main >> …'. - The import success toast is the only path to View automation and disappears after about 5 s.
- Continue with local setup silently creates the
OPENHANDS_URLsecret (value: the app origin) the first time; F14's list then has an extra row. - The Install button in a template's install dialog verifies the MCP connection before saving, so dummy credentials cannot complete the queue; nothing is saved on failure.
- Creating the first automation ticks Schedule a task in the sidebar Getting-started checklist (F02); a run that checks the checklist should do so before this file.
- Known issue #17959: a template search with no matches leaves a blank area with no message (
F22.templates-search). - Known issue #17436 (
F22.setup-review-confirm): Prompt-preset automations created after the Canvas 1.17.0 upgrade fail on the first conversation events request while older tarballs work, so the UI shows Failed runs. Recheck with a real LLM key and the reported automation 1.11.1/Agent Server 1.46.0 deployment plus pre-upgrade and finish-tool-wired tarballs; retain this version-specific report separately from the plugin-preset Cloud failure in #16611. - Known issue #15509 (
F22.setup-tarball-create): A native Windows event-triggered automation fails while uploading its workspace tarball withPath must be absolute. Recheck a Windows local stack and real event delivery, then observe its failed run/upload; a POSIX tarball upload is not a Windows path-validation check. This run has neither Windows nor the webhook fixture. - Known issue #16611 (
F22.setup-plugin-create): a minimal plugin-preset Cloud automation fails on its in-sandbox conversation/events request with HTTP 500, while the identical prompt preset works. Live prerequisites: an authenticated Cloud account, a real model key, and a reviewed no-op plugin fixture for the paired cases. The reported cost-zero error is visible in run logs, but a local prompt-only check cannot establish the Cloud plugin-loading behavior. - Known issue OpenHands/software-agent-sdk#5729 (
F22.setup-repository-list): prompt and plugin preset workers callRemoteWorkspace.clone_repos, which asks for lowercase provider-token secret names. A private repository can therefore fail to clone when only the documented uppercaseGITHUB_TOKEN(or GitLab/Bitbucket equivalent) exists. Recheck an owned preset with a private repository and only its uppercase secret, using an authorized disposable repository or a reviewed token-gated local Git fixture; a public repository and the Canvas Agent Server's separate Git-provider service do not exercise that lookup.
F23 Automation detail, runs and editing
41 behaviors · Read this family’s scripts
- Open from the dashboardF23.open-detail · F23.headerMapped behavior
- Other ways inF23.open-detail · F23.back-linkMapped behavior
- States: loading and not foundF23.loading · F23.not-foundMapped behavior
- Backend unavailableF23.backend-unavailableMapped behavior
- Load errorF23.load-errorMapped behavior
- Turn on with the switchF23.toggleMapped behavior
- Run now and live statusF23.run-now · F23.run-status-polling · F23.activity-logKnown failureKnown issue
- Linked conversationF23.run-linked-conversationKnown issueBlocked
- Run deep linkF23.run-deeplinkMapped behavior
- Logs dialogF23.run-logs-modalKnown failureKnown issue
- Export the logF23.activity-log-exportMapped behavior
- Export and TarballF23.export · F23.tarballMapped behavior
- Turn off and the paused bannerF23.disabled-reason · F23.toggleMapped behavior
- Edit fields and closingF23.edit-open · F23.edit-closeMapped behavior
- ValidationF23.edit-validationMapped behavior
- No-change SaveF23.edit-saveMapped behavior
- Weekly schedule, model and timeoutF23.edit-schedule · F23.edit-saveMapped behavior
- Cleared timeF23.edit-time-clearedKnown failure
- Custom cronF23.edit-cronMapped behavior
- Failed run, its row and Debug with OpenHandsF23.run-status-polling · F23.run-no-conversation · F23.run-logs-modal · F23.debug-with-openhandsKnown failureKnown issue
- Task outcome badgeF23.run-task-outcomeMapped behavior
- Event automationF23.prompt-collapse · F23.configuration-event · F23.plugins-repo · F23.exportKnown issue
- Event trigger in EditF23.edit-event-readonlyMapped behavior
- PhoneF23.phoneMapped behavior
- Run now and save errorsF23.run-now-error · F23.edit-save-errorKnown failure
- Load more runsF23.activity-log-moreNot run
- Script automationF23.script-sectionMapped behavior
- Edit-mode Test and unsaved editsF23.edit-test · F23.edit-dirty-stateMapped behavior
- DeleteF23.deleteMapped behavior
- ErrorsF23 · setup / cleanupSupport step
- UTF-8 script memberF23.script-sectionKnown failure
- Live free-form phaseF23.run-status-polling · F23.activity-logKnown failureKnown issue
- Custom nested setup (`F23.script-section`, `F23.run-logs-modal`; creation in F22)F23.script-section · F23.run-logs-modalKnown failureKnown issue
- Selected profile on a prompt presetF23.configuration · F23.run-linked-conversationKnown failureKnown issueBlocked
Family notes & prerequisites for known issues
- The automations QA checklist (F28) expects edit-mode Test to run the current form state; the panel calls
dispatchAutomation(<id>), which runs the saved automation.F23.edit-testrecords current behavior; whether it should change is a product decision, not a map correction. - The Logs dialog's panel keeps long content reachable (
F23.run-logs-modal, #18175 / #18173). Re-verified 2026-10-13 (revision2bdc0e9d, SDK 1.54.0, automation 1.19.3) with a 30-lineoutcome_summaryat 1440×1000, 390×844 and 390×500: the panel istestid=run-logs-body(max-h-[80vh],overflow-y: auto) with a sticky header (Logs + X stay visible); the Output box no longer scrolls on its own, the whole panel does, and its end (=== RESULT === ALL_OK) is reachable at the bottom. Verified 2026-10-10 on an independent fresh Linux Local stack at product revision5a8c3832154b14d2dad651801c0ab3f74c96f02e, SDK 1.54.0 and automation 1.19.3: a genuine DeepSeek finish produced a 4,596-characteroutcome_summaryand 1,079-character metadatamessage; summary/metadata endings, Output/Error tabs and the true stdout end were reachable at 1440×1000, 390×844, 1440×500 and 390×500. The header/X remained visible, closing did not navigate, and phone had no horizontal overflow. Preserve those long-content and short-height checks when retesting. The verified scope is pinned Linux Local; macOS, Cloud and legacy/custom finish schemas need their own checks.browser bbox 'role=dialog'measures the full-screen wrapper, not the panel: measure the panel withbrowser eval. - The detail page has no
mainlandmark:browser snapshot 'role=main'times out. Snapshot the page, or scope by section headings (role=heading[name="Configuration"] >> xpath=ancestor::div[2]). - The kebab menu has no test ids;
role=list >> has-text=Tarballscopes the detail kebab (the dashboard kebab has no Tarball, so F21 useshas-text=Export). - Kebab Edit (detail and dashboard) opens
/automations/setup?automationId=<id>. The edit page's Save and Test report API failures with the API's message (seeF23.edit-validation,F23.edit-save-error), and itsAutomation updatedtoast covers Test/Save/Close until the pointer moves away. - Known defect: clearing At on a preset schedule and saving stores midnight with no message (#17948 item; with the old modal it was silently ignored).
- On a local backend the Logs dialog reads every run's output from the server-level
/api/bash/bash_events/search, with or without a conversation. It caches what it fetched: reload before checking its requests withbrowser network. - Known defect: prompt runs also have a
bash_command_id, so every row shows the logs icon, and a prompt run that ended without a conversation is labelled as a script run (F23.run-no-conversation) (#17948). - The automation service (1.19.0 here) keeps repos and plugins only under
preset_metadata; the UI reads them from there. Repositories showowner/repowithout the host (a GitLab URL reads like a GitHub one), a repo without a ref gets no badge, and Export keeps only the first repository (all plugins). The Notification field reads a top-levelnotificationthat the service has no field for, so it never renders on a local stack (#16644 tracks removing or mapping it). - The Schedule field shows the raw cron (
0 9 * * *) and no timezone: the service returns noschedule_humanand no top-leveltimezone, so the Edit dialog also omits itsTimezone:hint. run-phasenever appeared in the log here (phase_codestaysnullon the local service), so the phase chip is not reachable on this stack.- An LLM profile that does not exist (
model: "qa-no-such-profile") does not fail the run: it ran and succeeded with the active profile. Use timeout1to get a failed run; it takes several minutes to fail. Load morein the log (F23.activity-log-more) needs more than 20 runs of one automation; at about 35 s and one model call each it is left out of a normal pass (not-run).- The script section needs a tarball automation. The account-free way to get one is F22's Daily news digest bundle entry (it uploads its bundle and creates the automation); the custom-automation Upload tarball action takes
control-openhands fixture tarball. Its kebab Edit shows generated starter Python instead of the saved bundle (#18341, see F21.edit); a cold load of/automations/setup?automationId=<id>shows the Existing code bundle summary. - Starting… on Run now lasts only for the dispatch request (under 50 ms locally);
--observedoes not catch it. - The run row is a plain
<a href>, so opening a run's conversation reloads the whole app (adocumentrequest inbrowser network), unlike sidebar navigation. - A 404 detail request is retried three times before Automation not found shows (about 7 s of skeleton) (#17948); wait with
wait-text, notcount. browser fillon the Timeout spinbutton with letters fails in Playwright and, after its 30 s retry, the dialog was found closed; use numeric values (1.5,0,1801) to reach the timeout errors.- The Tarball download is named
<name>.tar(spaces become_) but is gzip-compressed (#17948);browser downloads --inspectdoes not list tar entries, so inspect it withtar -tzf. - Debug with OpenHands starts a real agent with the
openhands-automationskill and the automation API key. It acts on live automations: here it looked upQA_F23 Failby name (a newer fixture with the same name), PATCHed its timeout back to 600 and dispatched it, which adds runs and conversations. Stop it once it has started: on its pagecontrol-openhands browser click 'testid=stop-button', thencontrol-openhands conversation wait <id> --until paused,finished,idle --timeout 45(paused). - A successful run leaves a conversation
<name> — <UTC timestamp>that stays after the automation is deleted (conversations family owns deleting it). - Known issue #15465 (
F23.configuration-eventF23.activity-log): An automation configured for Agent Canvas release events never runs automatically, although Run now works. Recheck a real signed GitHub/Forgejo release webhook through an externally reachable responder into a disposable automation and inspect its activity log; local manual dispatch cannot verify event delivery. No external repository webhook credentials or controlled release-event fixture are available. - Known issue OpenHands/software-agent-sdk#5279 (
F23.run-linked-conversation): An automation that attaches to an existing remote conversation can complete with no conversation link in its run, because the workspace callback does not register the attached id. Recheck a Cloud automation script that callsRemoteConversation.attachon an owned stable conversation and exits through the real workspace completion callback, then inspect the Activity Log link. Blocked without that authenticated Cloud workspace/callback context; a plain local GET is not callback proof. - Known issue OpenHands/software-agent-sdk#4705 (
F23.run-status-polling,F23.run-logs-modal): GitHub MCP tool events can omitinputSchema, causing an automation's RemoteConversation decoder/run log to report failure while the agent continues, so task and automation statuses disagree. Recheck a real GitHub-MCP-enabled run using the affected client/server versions and its retained tool-definition event; the issue does not give those versions. A generic MCP fixture does not establish the reported GitHub/version branch, and genuine run comparison needs a model key. - Known issue OpenHands/software-agent-sdk#4260 (
F23.run-linked-conversation,F23.run-logs-modal): Cloud PR-review automation can remain at review in progress and time out without posting a review; its event webhook also fails to serialize SecretStr, breaking the UI stream even on successful reviews. Keep the stream-serialization failure distinct from the empty-response/600-second run-budget failure. Recheck with an owned Cloud reviewer/webhook deployment, authorized disposable review target and real model credentials; a local script run proves neither production path. - Known issue OpenHands/automation#286 (
F23.run-status-polling): Multi-worker/replica automation deployments can run duplicate watchdogs that query the same sandbox and hit rate limits, falsely failing runs. Recheck the real deployment's worker/replica configuration with an owned long-running Cloud run and sandbox verification traffic; this single-worker local stack cannot prove distributed scheduler/watchdog ownership. - Known issue OpenHands/automation#219 (
F23.run-status-polling): Starting a Cloud automation at the user's sandbox cap can pause an existing interactive session instead of reaching the graceful Skipped–Limit Reached path. Recheck only on an owned disposable Cloud account at its recorded cap, with a live interactive fixture and a new automation run, then observe both run and conversation states. This run has no Cloud account/cap fixture; do not evict a production session as a test. - Known issue OpenHands/automation#113 (
F23.run-linked-conversation): Scheduled plugin jobs can start conversations visible in the archived list while the automation run UI says no conversation started. Recheck the affected automation/run ids, archived conversation ids and deployment version, using the real callback relationship; these identifiers and version are not provided. This is a reported missing-link state, not proof that no agent ran. - Known failure OpenHands/automation#514 spans Home cancellation (
F03.cancel-in-flight-run) andF23.activity-log/F23.run-logs-modal: on 2026-10-12 a genuine Home Cancel run changed the owned bounded local worker's row to Cancelled, while its Python entrypoint remained alive in the owned launcher ancestry. The F03 driving bullet owns upload/create/cancel steps and retained evidence. The worker later reached its 180 s bound and exited; a cancelled status alone does not prove process cleanup. - Known issue OpenHands/software-agent-sdk#4388 (
F23.run-status-polling,F23.run-logs-modal): incremental SDK Bash output polling can return empty pages before newer chunks whenorder__gtis applied after the file-page boundary. Canvas's frontend log reader does not send that filter, but automation launch preparation and prompt/plugin preset repository clones use(Async)RemoteWorkspace.execute_command, whose output poller does. Recheck a bounded genuine preset/setup or repository-clone command that emits enough chunks to cross the 100-event boundary, correlating its final BashOutput and real run result; a frontend Logs read or a one-output command does not cover the incremental branch. - Known issue OpenHands/software-agent-sdk#5937 (
F23.run-status-polling,F23.run-logs-modal): prompt/plugin preset workers attachAUTOMATION_CONVERSATION_IDfor continued conversations and then callRemoteConversation.run(). If that same conversation is already running a tool for more than 30 s, the join request can time out and fail the automation worker while the agent continues. Recheck an owned continued-conversation automation with a genuine already-running long tool and correlate worker error, agent status and final run result; a fresh conversation or one normal firstrun()does not exercise the join. No model execution is authorized in this pass. - Known issue OpenHands/software-agent-sdk#5938 (
F23.run-status-polling): prompt/plugin preset workers register an event callback that forwardsActionEvent.summaryas the live phase. After an events-socket reconnect, REST-reconciled events reach SDK state but are not replayed to that callback, so summaries emitted in the gap can be missed. Recheck an owned real preset worker through a bounded reconnect window while a genuine action is recorded; compare callback-driven phase with stored events. Current Canvas phase rendering has its separate #17121 gap, and the worker's completion metadata is not claimed lost merely because this callback missed an event.
F24 Automation Git Sync
26 behaviors · Read this family’s scripts
- Open from the dashboardF24.open · F24.loadingMapped behavior
- Unconfigured cardF24.overview-unconfiguredMapped behavior
- Dirty trackingF24.form-dirtyMapped behavior
- Unreachable repositoryF24.check-failureMapped behavior
- Failing cycleF24.sync-failureMapped behavior
- Configure and Save and syncF24.save-and-syncMapped behavior
- Sync a changed automationF24.sync-nowKnown issue
- Commit authorF24.authorMapped behavior
- Encryption keyF24.encryptionMapped behavior
- Access tokenF24.tokenMapped behavior
- IntervalF24.intervalMapped behavior
- Pause and resumeF24.pauseMapped behavior
- Trigger while disabled elsewhereF24.sync-disabled-errorMapped behavior
- Repository linkF24.repo-linkMapped behavior
- Interval cycleF24.background-syncMapped behavior
- Sync a deletionF24.sync-deleteMapped behavior
- Empty branch and pathF24.field-defaultsMapped behavior
- ssh remote linkF24.repo-link-sshMapped behavior
- Clear the repositoryF24.clear-repoMapped behavior
- Phone layoutF24.phoneMapped behavior
- Automation service downF24.backend-downMapped behavior
- Old backendF24.unsupportedMapped behavior
- No permissionF24.no-accessBlocked
- Repository taken by another orgF24.conflictBlocked
- Status errorF24.error-stateMapped behavior
- Clean upF24 · setup / cleanupSupport step
Family notes & prerequisites for known issues
- Configuring a repository is what turns sync on: the backend's pause switch defaults to on, so the first save of a URL flips the pill to
Enabledeven though the switch was never touched, and clearing the URL turns it off again. The help text under the switch says so (Sync is on as soon as a repository is configured. ...). A pause is the exception: it survives clearing and re-entering the URL, so the pill staysDisableduntil the switch is turned back on. - A local path (or
file://URL) is a valid remote, which is what makes this family drivable without credentials. Use a branch other than the fixture's checked-outmain: git's defaultreceive.denyCurrentBranchrefuses pushes to a non-bare repo's checked-out branch (not driven here; every recipe usesqa-sync). - The reachability check runs only when repository URL, branch or token changed (
git ls-remote, 20 s timeout). Interval, path, author, encryption key and the enable switch save without it. A check that cannot run at all (old backend, network error) never blocks a save. - The second Save after a failed check saves the same values without checking again; editing any checked field re-arms the check.
- The activity row (
git-sync-activity-row,data-staterunning/succeeded/failed) is page state: it disappears on reload and does not appear for a background cycle that starts and ends between two idle polls (15 s). Assert background cycles through the commit hash, not the row. - Feedback colours are semantic tokens (#18346): the check-failure block, the Last sync error banner and a
Sync failedrow use the danger surface and feedback-error text (rgb(231, 106, 94)on OpenHands-Neutral,rgb(192, 40, 45)on white under Light+), andSync completeuses success (rgb(165, 231, 94)Neutral,rgb(15, 115, 77)Light+); verified 2026-10-13 on desktop. Read them withbrowser evalofgetComputedStyle(...).coloron the text elements insidegit-sync-check-failure,git-sync-error-bannerandgit-sync-activity-rowafter switching themes on/settings/app(F16.color-theme). - Toasts (
Git Sync settings saved.,Enable Git Sync before triggering a sync.) last a few seconds: read them withbrowser wait-textimmediately after the click, never after a long--observewindow. - Save's label cycles
Save Changes→Checking repository...(only when a checked field changed) →Saving...→Save Changesin about 100 ms against a local repo;--observe 'testid=git-sync-save-button'records it. - Setting, rotating or clearing the encryption key re-exports the automation even when its definition is unchanged. Each key-only save sets
dirty_countto1; the next sync creates a commit with ciphertext after set, different ciphertext after rotation and plaintext after clear. Read the dirty count and exported file before any automation PATCH; a separate dirty export tests a different contract. - Nothing on the page says whether a token is stored: the token placeholder is always
Leave blank to keep the current token, and the author fields always reload blank. Prove author changes from the commit (git log --format='%an <%ae>'). - The card's Repository value drops embedded credentials, as link text and as plain text: an http(s) URL loses its whole
user:token@(a token alone in the user slot too), other schemes keep the user and lose only the password (ssh://git@host:2222/...), and the rest stays as configured. The Repository URL input andGET /api/automation/v1/git-sync/statusstill carry the credentials, so a screenshot of the form shows them. Never type a real token into the URL. - The page has no Automate sub-navigation (Dashboard / Templates) and no command-menu entry; leave through Back to Automations (
role=link, not a button). - Deleted automations stay in Pending changes until a cycle pushes the removal; after cleanup with sync off the card can read
Pending changes 2. Sync a deletion pushes it while the repository is still configured. - An untouched Enable Git Sync switch follows the server: after another admin pauses sync, the next idle poll flips both the pill and the switch off, so turning it back on is one label click plus Save.
F24.unsupporteduses--automation-reffor the old Git tag; without access to that source it stays blocked. The current CLI also supports--automation-version Vfor a PyPI release (verified with 1.19.3 on 2026-10-10). Backend overrides come from these explicit launch flags; shellOH_AUTOMATION_VERSIONis not forwarded.- Arrange with
api ... --writeonly to mark automations changed or to simulate another admin; the save, check and sync steps must go through the form. - Known issue OpenHands/automation#586 (
F24.sync-now): a YAML-only repository edit can replace an unchanged uploaded script bundle because canonical gzip bytes retain their creation second. Recheck a disposable Git Sync repository and script automation, change only YAML, arrange the canonical rebuilds across different seconds, and compare the real saved upload reference before and after sync. Equal decompressed contents or a serializer-only probe do not prove that Canvas reuses its upload.
F25 Backends, Cloud and sharing
33 behaviors · Read this family’s scripts
- Open the selectorF25.selector-dropdownKnown failure
- Add Backend modalF25.add-backend-modalMapped behavior
- Advanced hostF25.cloud-advanced-hostMapped behavior
- Device flow errorF25.cloud-device-flowMapped behavior
- Device flow awaiting and CancelF25.cloud-device-flowMapped behavior
- Agent-server guidanceF25.agent-server-guidanceMapped behavior
- Connect rules and errorsF25.add-agent-serverKnown issue
- Add the second backendF25.add-agent-serverKnown failureKnown issue
- Switch with the overlayF25.switch-backendKnown issue
- Pinned URLF25.backend-pinned-urlMapped behavior
- Per-tab backendF25.per-tab-backendMapped behavior
- Manage list and closingF25.manage-backendsMapped behavior
- Select from ManageF25.manage-selectMapped behavior
- Edit validation and errorsF25.edit-backendMapped behavior
- Escape in EditF25.edit-escapeKnown failure
- Edit and saveF25.edit-backendMapped behavior
- Health statusF25.health-statusKnown issue
- Recovery gateF25.recovery-gateMapped behavior
- Remove the active backendF25.remove-backendMapped behavior
- Add from Manage, Edit Cancel and XF25.manage-add · F25.edit-cancelKnown failure
- Collapsed railF25.collapsed-entryMapped behavior
- PhoneF25.phoneMapped behavior
- Providers tabF25.providers-tabKnown failure
- DigitalOcean sign-inF25.digitalocean-sign-inKnown failure
- Managed Agents with an accountF25.digitalocean-agents · F25.digitalocean-backend-removalBlocked
- Cloud backendF25.cloud-device-flow · F25.cloud-org-rows · F25.cloud-settings-link · F25.share-publicly · F25.cloud-sandbox-statesKnown issueBlocked
- Device verify pageF25.device-verify-pageMapped behavior
- Shared viewF25.shared-conversation-viewMapped behavior
- No Public Share locallyF25.share-publiclyBlocked
- CleanupF25 · setup / cleanupSupport step
- ErrorsF25 · setup / cleanupSupport step
- Same-origin credential readabilityF25.manage-backends · F25.add-agent-serverKnown failureKnown issue
- Manually registered same-origin key rotationF25.add-agent-server · F25.recovery-gateKnown failureKnown issue
- Non-loopback default backend nameF25.selector-dropdownKnown failure
- Cloud log back inF25.cloud-log-back-inBehavior contract
- Cloud org suspendedF25.cloud-org-suspendedKnown issueBlocked
- Locked cloudF25.locked-cloudKnown issue
Family notes & prerequisites for known issues
- Export the second run as
OH_VERIFY_RUN_2and pass it with--run; never export it asOH_VERIFY_RUN, or the browser commands look for a browser that run does not have.OH_VERIFY_RUN= control-openhands launch --new ...keeps the launch from reusing this run. - The second backend asks its own telemetry consent the first time it becomes active, over whatever page you are on;
onboard --skipanswers it. Consent is stored per backend, so a laterrestartof the second run does not ask again. browser fill <sel> --value-file FILEtakes no positional value; it keeps the key out of the shell history and the evidence. Edit forms show the stored key masked, butbrowser snapshotof the Edit form prints it in clear: do not save that snapshot as evidence with a real key.- Manage-row test ids use the backend name (
manage-backends-row-QA_Second), so they change after a rename and are not unique when two backends share a name; the Cloud Log back in id uses the backend id instead (manage-backends-login-<id>-login-button). - Selector options are named
<status> <name>(Connected Local,Disconnected QA_Renamed): select them withrole=option[name="Connected <name>"]. - After a navigating option click,
--expect-urlmust allow?backend=...: end regexes with(\?|$). browser wait-tab <regex>matches any open page, including the current one, unless--newleaves out the tab the daemon is on: for a second tab at the same URL (/conversationsfrom New Chat) usewait-tab '/conversations$' --new, or readbrowser tabsand switch withbrowser tab <i>.browser tab new /conversationsopens a plain second tab (no opener, empty sessionStorage), the state a user reaches by opening the app again. Close extra tabs highest index first, or the indexes shift under you.browser tab newswitches the daemon to the tab it opened, so await-tab <regex> --newrun right after it reports the tab you came from (index0with two tabs);browser tab 0first when you want the new tab's index fromwait-tab. Atab newand aclick --modifiers Controlon New Chat reach the same state (selector from the localStorage fallback, sessionStorage itemnull).- A tab opened with
click --modifiers Controlstarts with an empty sessionStorage, so it boots from the localStorage fallback (the backend last chosen in any tab) unless its URL carries?backend=. Opening a?backend=link writes that backend to localStorage too: a per-tab check that relies on "last choice" must run before opening pinned links. - The Add Backend Agent-server form has no inline "required" messages; it only disables Connect. The messages exist in the Edit form.
- Footer clicks from the collapsed popover or the phone drawer open the modals a moment later:
browser waitfor them instead ofcount. - The device-flow popup survives errors: every failed attempt leaves an
about:blanktab (#17953). Cancel closes it; after an error close it withbrowser close-tab. - With the default host the device flow talks to the real
app.all-hands.dev(POST /oauth/device/authorize, then token polling). Starting and cancelling is harmless; approve a code only in the Cloud backend bullet, with an account you may use. - While the second stack's agent server is stopped or restarting, its ingress answers without CORS headers, so the browser logs
Access to fetch at '<second-url>/api/settings' ... blocked by CORS policy(also/server_info,/api/conversations/search,/api/llm/models/verified). That is the dead upstream, not a CORS bug; a healthy second stack sendsaccess-control-allow-originfor this origin. - Expected: Escape never clears the backend selector. Known failure (reproduced 2026-10-09, 2026-10-12, 2026-10-13 and 2026-10-14, #18233): Escape on the focused backend selector while its menu is closed (a second Escape after the one that closes the menu, and sometimes the Escape that closes Manage Backends opened from it) clears the selection: the closed selector shows the active backend's name as an italic placeholder (
browser value 'testid=backend-selector >> role=combobox'is"") and its status dot is gone, sobrowser wait 'testid=backend-selector >> role=status[name="Disconnected"]'times out although the backend is down; a reload restores it. Reload before a closed-selector status check, as the Edit bullet does. Repro:browser click 'testid=backend-selector',browser press Escapetwice (#18233). On 2026-10-12bug proofverified fix PR #18238 at 77de0ad24 against main f07aebdf5 (twoxfail, twoxpass, desktop).control-openhands bug run F25.selector-dropdownreplays it (desktop, after a reload with the mouse off the selector: a reload under a mouse left on it opens its menu and empties its field, which would look like the bug) and reportsxfailwhile the bug lasts:
sh known-bug F25.selector-dropdown escape-closed
control-openhands browser viewport desktop
control-openhands browser goto /
control-openhands browser hover 'testid=root-layout'
control-openhands browser reload
control-openhands browser wait 'testid=backend-selector >> role=status[name="Connected"]' --timeout 15000
control-openhands assert --field value --equals Local -- browser value 'testid=backend-selector >> role=combobox'
control-openhands browser click 'testid=backend-selector'
control-openhands browser press Escape
control-openhands browser press Escape
control-openhands browser screenshot 'testid=backend-selector' --feature F25.selector-dropdown --name escape-closed
control-openhands assert --field value --equals Local --bug-shows '' -- browser value 'testid=backend-selector >> role=combobox' # bug
- Local and remote backends are probed every 30 s (settings + server_info), Cloud backends every 5 min (#18128), so allow up to 40 s for a local dot to change.
browser network --clear, wait about 70 s, thenbrowser network --filter server_infoshows two probes per local origin 30 s apart. While the active backend is down, any reload lands on the recovery gate: drive the disconnected rows on the page that was already loaded. /oauth/device/verifyis a Cloud page that also ships in Canvas: on a local stack its POST target does not exist, so Authorize always ends inError. The "Authentication Required" state is unreachable (useIsAuthedalways resolvestrue)./shared/conversations/<id>on a local backend also raises a raw toastHTTP request failed (404 Not Found): {"detail":"Not Found"}next toConversation not found(#17953).- Known failure (repro candidate, not an exemption):
F25.edit-escapecloses the Manage modal underneath and drops the Edit draft (Cancel and X close only Edit,F25.edit-cancel) (#17953). - The add bullet's
network --external --filter 'ids='check guards an earlier race: #18390 tracks the same first-activation symptom; on a backend's first activation from/conversations/<id>, about 1 attempt in 5 asked the new backend for the old conversation id. It did not happen in 15 first activations at 4eff80237: each timeQA_Secondwas removed, its consent unset withcontrol-openhands api PATCH /api/settings --run "$OH_VERIFY_RUN_2" --write --data '{"misc_settings_diff":{"app_preferences":{"user_consents_to_analytics":null}}}'(arrange only) and the backend added again from/conversations/<id>. A backend that lacks an id answers[null], which now reads as "not found" (only theThis conversation does not exist…toast), not as incompatible data. No merged change was shown to fix the race itself (#18009 only changed how a[null]answer reads; #18024 only moved the redirect into a shared hook, still called afteraddBackend), so a hit (anids=request to<second-url>) is a bug to file. At 95115e84f6dd it hit on 1 of 2 first activations from/conversations/<id>(oneGET <second-url>/api/conversations?ids=<id>answered200, with noThis conversation does not exist…toast after it). The hit followed a failed Connect in the same modal (an empty key,Invalid API key) before the successful one; the clean retry, which connected once, had none, so a repro should try both sequences. On 2026-10-08 at d2c89252d it did not reproduce in 17 first activations (8 clean, 9 failed-then-clean, some under CPU load and some human-paced): everyids=capture was empty, and no merged change touched the activation logic since the hit, so it stays a watch item rather than a filed defect. Record the Add bullet asfailwhen the request appears, even though the redirect and the selector look right. Known failure (reproduced 2026-10-13, #18390): two independent first activations hit it that day, each the run's first activation ofQA_Secondafter a clean Connect. On 2026-10-13 at 2bdc0e9d6 it hit on 1 of 6 first activations from/conversations/<id>: the first one of the run (GET <second-url>/api/conversations?ids=<id>200, no toast), a clean Connect in a modal opened after earlier failed Connects in other Add Backend openings; the next 5 (2 failed-then-clean, 3 clean, plus one Manage → Add) had none. - Add Backend and Manage Backends take and keep keyboard focus, and Edit backend takes it on open (
ModalBackdrop; at phone width open the selector with'testid=sidebar-mobile-drawer >> testid=backend-selector', since the bare test id matches two selectors). At desktop width focus returns to the selector input when they close (at phone width Add Backend's X closes the drawer too and focus falls to the page body), so an Escape pressed after closing lands on the selector and can trigger #18233 below. - Toasts are not page or HTTP errors, so
browser errors --app-onlymisses them: readbrowser toasts --historyafter every add or switch, before anything reloads the page (the history starts with each page load). F25.locked-cloudneedsscripts/static-server.mjs --lock-to-cloud <url>, which neitherbin/agent-canvas.mjsnorcontrol-openhands launchcan pass today; even with it, reconnecting needs a Cloud account.- The Cloud tab title truncates to
OpenHan…at 390 px when the Agent-server tab is selected; the layout still fits. With the Providers tab present all three titles are cut to three letters. - A token DigitalOcean rejects surfaces as the bare
401 Unauthorized, with no hint that the token is wrong or lacks scopes. - Known issue #18029 (
F25.locked-cloud): A returning user in a locked Cloud deployment can reach the no-backend placeholder and fail to start conversations despite a healthy configured backend. The report proposes a stale document or alternate origin but does not capture which occurred. Recheck against the affected locked deployment with a Cloud session, its exact origin, cache response headers and injected host state; the normal local launcher does not reproduce this deployment condition. - Known issue #17390 (
F25.cloud-sandbox-states): Every sent Cloud message can fail withtoken_not_found_in_dbfrom the model proxy. Recheck with the affected Cloud account/session and a minimal no-tools prompt; capture the error type with provider token text and hashes redacted. The report supplies no deployment version or deterministic token-provisioning sequence, and this run has no Cloud account. - Known issue #17163 (
F25.cloud-sandbox-states): A Free Cloud account can lose access to previously usable models with HTTP 403 and a team-restriction message despite no team being created. Recheck with the affected account and its model entitlement/org history; local credentials cannot prove Cloud eligibility and this run has no such account. - Known issue #16874 (
F25.cloud-sandbox-states): A failed resume of a paused Cloud sandbox was reported to consume a one-shot guard and leave chat disconnected until remount. Current source uses a retrying resume hook, so recheck the original failure and a second pause in one route mount before concluding resolution. Blocked without a real paused Cloud sandbox and a controlled one-request backend/network failure; source changes alone are not a live pass. - Known issue #15676 (
F25.cloud-sandbox-states): Refreshing an approximately 24-hour-old Cloud conversation on Vercel can fail to resume/reconnect. Recheck an authenticated affected Cloud deployment with an aged sandbox/session and exact console/network error; the report omits its commit and failure text, and no aged Cloud fixture is available here. - Known issue #15822 (
F25.switch-backendF25.health-statusF25.cloud-org-rows): Cloud-proxy traffic was reported to continue after switching from Cloud to Local. Current source probes registered inactive Cloud backends on a five-minute cadence; recheck the reported repeated OPTIONS behavior with a real registered Cloud account/org and capture only credential-redacted request metadata after switching. This run has no authenticated Cloud backend. - Known issue OpenHands/automation#565 (
F25.cloud-org-rows,F25.cloud-org-suspended): An org-scoped Cloud automation request with an unauthorizedX-Org-Idcan turn the identity service's 403 into a misleading 502/outage page. Recheck with an authenticated Cloud org-bound key and a disposable unauthorized organization id, comparing automation list and the identity response while preserving credential redaction. Local mode bypasses this identity service and cannot reproduce it. - Known issue OpenHands/software-agent-sdk#5789 (
F25.add-agent-server,F25.health-status): a deferred-init Agent Server can report ready after accepting a GUI origin through/api/init, while browser preflights from that origin still fail and Canvas cannot connect. Recheck an owned warm-pool server initialized with the actual non-localhost Canvas origin and compare admission with an origin supplied at server boot. The default loopback-origin stack is already allowed and cannot exercise this branch.
F26 Launcher modes, Docker, desktop and library
34 behaviors · Read this family’s scripts
- VersionF26.cli-versionMapped behavior
- InfoF26.cli-infoMapped behavior
- HelpF26.cli-helpMapped behavior
- Conflicting flagsF26.cli-flag-conflictsMapped behavior
- Public mode needs a keyF26.cli-public-needs-keyKnown issue
- Missing buildF26.cli-missing-buildMapped behavior
- Port in useF26.cli-port-in-useMapped behavior
- Loopback-only ingressF26.loopback-bind-defaultNot run
- Backend-onlyF26.backend-onlyMapped behavior
- Frontend-onlyF26.frontend-onlyMapped behavior
- Cross-connectF26.cross-connectMapped behavior
- Remote backend from a normal CanvasF26.remote-backendKnown issue
- Seeded Local backendF26.seeded-local-backendMapped behavior
- Rotated session keyF26.session-key-rotatedMapped behavior
- Managed Agents bridgeF26.mars-web-bridgeKnown failure
- Stop the partial stacksF26 · setup / cleanupSupport step
- LAN bindF26.host-bind-lanNot run
- LAN opt-inF26.host-bind-lan-optinKnown failure
- Generated session key persistsF26.session-key-persistMapped behavior
- Pinned session keyF26.session-key-pinnedMapped behavior
- Bind host from the environmentF26.host-bind-envMapped behavior
- Frontend-only, returning userF26.frontend-only-returningKnown failure
- Automation exits during startupF26.automation-startup-failureKnown failure
- Runtime servicesF26.runtime-servicesKnown issue
- The agent uses the runtime servicesF26.runtime-services-agent-useMapped behavior
- Library buildF26.lib-buildMapped behavior
- Style scopeF26.lib-style-scopeMapped behavior
- BlockedF26.lib-host-app · F26.docker-image · F26.docker-conversation-runtime · F26.helm-chartKnown issueBlocked
- Desktop splash and windowF26.desktop-boot-splash · F26.desktop-main-windowKnown issue
- External linksF26.desktop-external-linksKnown issueNot run
- KV survives authentication rotationF26.session-key-rotated · F26.session-key-persistKnown failure
- Partial SQLite migration startupF26.runtime-servicesKnown failureKnown issue
- Occupied internal frontend portF26.cli-port-in-useKnown failure
- Required frontend deathF26.runtime-servicesKnown failureKnown issue
- Static-server credential argvF26.runtime-servicesKnown failureKnown issue
- Keep-alive proxy timeout listenersF26.runtime-servicesKnown failureKnown issue
- Default Rich logging responsivenessF26.remote-backendKnown failureKnown issue
- Desktop macos titlebarF26.desktop-macos-titlebarBlocked
Family notes & prerequisites for known issues
control-openhands launchcovers only the full stack and--public. Partial stacks and--hostneed a hand-started launcher with its ownHOME,OH_CANVAS_SAFE_STATE_DIRand all threeOH_CANVAS_SAFE_*_PORTvariables; without them it writes into the real~/.openhands/agent-canvasand grabs the default ports 8000/18000/18001/3001 that another agent may be using.- A hand-started launcher's first start downloads the agent-server into its private
HOMEcache (30–90 s). Prefix assignments are expanded left to right, soHOME=$Q/home UV_CACHE_DIR=$HOME/.cache/uvpoints the cache into$Q/hometoo, not at your real cache. Reuse one$Qfor repeat launches to keep it warm. - The browser daemon refuses other origins unless you pass
--allow-externaltobrowser goto. Each port is its own origin, so a partial-stack page starts at first run again (onboarding and a consent dialog), independent of your run's onboarding. - In a frontend-only UI the Add a backend step's Next is enabled with an empty key, while on a LAN or
--publicstack it is disabled until a key is typed: the host the step probes differs (503 vs. auth-required). - A partial-stack origin keeps its stored backend in the browser profile across launches, so a second pass lands straight in the shell.
control-openhands browser resetbrings back the first run on every origin; thencontrol-openhands browser goto /andcontrol-openhands onboard --skiprestore your own run's baseline. - Which screen a frontend-only origin shows depends on the browser, not the launcher: a profile new to the origin gets Add a backend (first run owns the initial backend), while a profile that stores a backend for that origin (the
default-localentry a full launcher on the same port seeded, or any backend added there earlier) gets the recovery gate ofF25.recovery-gateas soon as that backend answers 503 (F26.frontend-only-returning). The no-toast check belongs to the first-run state only: on the gate,browser toasts --historylists genericAn error occurredstatus toasts raised by the failing 503 probes (two within 12 s here), with no hint of which request failed. Known failure (reproduced 2026-10-08): both toasts come from the free-models hydrator'sGET /api/llm/models/verified503, which nometa.disableToastguards on that screen (nor doesbackend-version.tsx); #18160. - Stopping a backend-only instance while the frontend-only page that uses it stays open is the same backend-down state as
F25.recovery-gateafter a reload; keep the returning-user bullet above as the frontend-only-specific check (it reproduces thedefault-localcase). - The launcher serves the bundled VS Code editor. #17660 made that opt-in (
OH_CANVAS_ENABLE_VSCODE=true) and #18048 reverted it, so only a checkout between the two needs the variable (launch --vscodesets it). A launcher that serves it reserves/vscode/: a frontend-only stack answers503there and logs[static] /vscode -> 503 (rejected); a stack with an agent-server lists/vscode → http://127.0.0.1:<agent-server port + 1000>in its ingress banner and hands the agent-server that editor port (19961 for the hand-started launchers here, 19000 for the desktop app), which the launcher's own port check does not cover. On a checkout between the two without the variable,/vscode/is an ordinary SPA URL (200). Here the agent-server has no editor binary (VSCode server binary not found, VSCode will be disabledin the launcher log,/api/vscode/status{"running":false,"enabled":true}), so the editor port stays free even then. - The port-in-use error is printed twice, the second time with a Node stack trace, and suggests
PORT=<other>rather than--port(#17949). The--publickey error's example saysnpm run dev -- --publicinstead of the npx command. - A backend-only instance's
/server_info.runtime_servicesstill describes the ingress as routing/* to the frontend, which it does not run (#17949). - In this sandbox
node_modules/electron/distis absent andnode node_modules/electron/install.jsfails withERR_ASSERTION(2026-10-13), so theF26.desktop-*rows stay blocked here. - The Electron app hardcodes ports 8000/18000/18001 (and the static server takes 3001), ignores
PORT, and refuses to start as root without--no-sandbox(Running as root without --no-sandbox is not supported).npm run desktopfirst runsbuild:app, which rebuildsbuild/under every other run: startnode_modules/.bin/electron --no-sandbox electrondirectly against the existing build. - Never stop the desktop app with one group-wide signal: when Xvfb dies with Electron, the app exits without stopping its backend, which is left orphaned (own process groups, parent 1) on 8000/18000/18001/3001 and blocks the next start. If that happens, find the orphans by their ports' command lines (
ps -eo pid,pgid,cmd, look for--port 18000,--port 18001,--port 3001,ingress.mjs --port 8000) and stop each group by id. - The generated session key lives in
$HOME/.openhands/agent-canvas/api-key.txt, not underOH_CANVAS_SAFE_STATE_DIR: a hand-started launcher without a privateHOMEreads and writes the operator's real key file. - A browser origin keeps the backends it stored on an earlier pass: after the LAN pass on 18960, a later loopback launch on 18960 shows the stale
QA_LANbackend (red, old key) instead of onboarding, although the page injects a valid key. Assert key-injection bullets through thewindowglobals, orbrowser resetfirst. - Electron's splash shows each raw service-log line (
agent-server: {"asctime": ...) as its status text during boot; the named phases only appear between them. build:libfrom a copy whosenode_modulesis a symlink emits bundled dependencies underdist/<absolute node_modules path>/...; that path is an artifact of the copy, not of the product.- **Bug candidate (
F26.host-bind-lan-optin):**scripts/bind-host.mjstells npm users to pass--allow-lan-session-key, but neitherbin/agent-canvas.mjsnorscripts/dev-with-automation.mjsparses or forwards it (onlyscripts/static-server.mjsand the Docker entrypoint do), and unknown flags are silently ignored (#17949, whose first item is exactly this; reproduced again on 2026-10-08 at d2c89252d). - Known issue #17946: the npm launcher never creates its
TMUX_TMPDIR, so hand-started instances share one tmux server and a restart of one resets the others' terminals. - Known issue #17763 (
F26.docker-image): The Docker entrypoint can leave protected Agent Server APIs unauthenticated when onlyLOCAL_BACKEND_API_KEYis supplied, because its export toOH_SESSION_API_KEYS_0is inside the generate-key branch. Recheck an owned container with a dummy custom key: unauthenticatedGET /api/conversations/searchmust be 401 and the same request with that dummy key 200./server_infois intentionally public and is not an auth probe. Blocked here without a Docker daemon. - Known issue #17623 (
F26.helm-chart): The chart defaults service-account-token automounting to true even with RBAC disabled, exposing an unused cluster credential to agent processes. Recheck a disposable Kubernetes installation using the default values and an explicit opt-in; inspect token existence/readability only, never its contents. Blocked without Helm and a Kubernetes cluster. - Known issue #17470 (
F26.docker-image): On Apple Silicon under Colima/Virtualization.framework, the image's Python services can exit with SIGILL while the frontend leaves onboarding at Disconnected. The report isolatesimport litellmand comparesOPENSSL_armcap=0; recheck on the affected ARM/Colima guest with the reported cryptography/OpenSSL combination. A native macOS npm stack is not that container environment. - Known issue #17112 (
F26.desktop-main-windowF26.desktop-external-links): Desktop main-window navigation, an OAuth popup redirect, or a nested popup can render a remote page inside the app frame. Recheck all three on an owned running Electron shell with a harmless remote page and loopback redirect fixture; the browser harness cannot operate Electron windows and the installed Electron binary is unavailable here. - Known issue #16872 (
F26.desktop-external-links): Non-browser URI schemes were reported to reach the OS handler from the desktop popup flow. Current source now parses hosts and restricts external protocols; recheck refusal in a running owned Electron shell before concluding resolution. Observe an inert denied test scheme without invoking any real OS handler. The browser harness cannot drive Electron and no installed Electron binary is available here. - Known issue #16774 (
F26.desktop-boot-splashF26.desktop-main-window): The macOS 1.14.0 DMG installs an app that Gatekeeper reports as damaged instead of booting. Recheck the actual downloaded signed/notarized release artifact through install and first launch on macOS; starting source Electron or removing quarantine would bypass the reported failure. That release DMG/signature fixture is unavailable in this run. - Known issue #16720 (
F26.runtime-services): CPU-heavy commands in several conversations can starve Agent Server and stop the UI loading; the report requests lower priority for agent commands than the service. Recheck with a disposable bounded workload, recorded CPU/resource limits and real command observations, never arbitrary stress on the shared machine. The exact Rust workload and affected resource envelope are missing, and real agent execution needs a model key. The backend counterpart is OpenHands/software-agent-sdk#4575. - Known issue #16690 (
F26.docker-imageF26.runtime-services): A Docker deployment with nine chats becomes slow/disconnected, then reloads lose the list and startup proxies report ECONNREFUSED. Recheck on the affected Windows-host Docker configuration with retained conversation state and a controlled workload; creating a few empty local chats cannot prove the reported resource/runtime failure. This run lacks Docker and the original conversation/workload fixture. - Known issue #16511 (
F26.docker-image): The documented Docker bind mount can be unwritable to container uid 10001, killing Agent Server/automation while the frontend still serves Bad Gateway. Recheck a disposable host-owned mode-700 mount and a writable control against an owned image; never chmod the operator's real state directory. Blocked here without Docker. - Known issue #16300 (
F26.runtime-services): The npm launcher can fail while building LiteLLM native dependencies when resolved AWS crates require a newer Rust compiler, leaving backend services unavailable. Recheck an isolated uncached uv environment withlitellm==1.95.0, the reported Rust 1.93.1/toolchain/platform and dependency resolution; a warm current backend cache cannot exercise that install failure. The historical dependency/toolchain fixture is unavailable. - Known issue #16208 (
F26.runtime-services): On Fedora Rawhide/Python 3.14.6, settings work but starting any conversation returns HTTP 500. Recheck a native Fedora environment with the reported SDK/runtime and model/profile, including the underlying server traceback; this macOS current-runtime stack cannot prove that platform-specific failure. - Known issue #15434 (
F26.remote-backend): The embedded VS Code action on a self-hosted reverse-proxy origin was reported to reopen Canvas because its advertised URL omitted the separate editor port/path. Current launchers include an ingress/vscode/route; recheck against the affected HTTPS proxy deployment with an actually available editor binary and emitted URL before concluding resolution. This run lacks that self-hosted proxy/editor deployment. - Known issue OpenHands/software-agent-sdk#5373 (
F26.remote-backend): A self-hosted Agent Server using default Rich traceback logging can wedge its event loop and grow memory when a websocket error has a cyclic/deep exception chain; Canvas then times out or disconnects. The npm launcher forces JSON logging, so rechecking needs a separately hosted default-Rich backend plus the reported pathological peer/backlog reproducer and bounded memory/time isolation. That original peer/driver is not included in the issue body; do not synthesize a server patch or stress the shared host and claim a live UI reproduction. - Known issue OpenHands/software-agent-sdk#5310 (
F26.docker-conversation-runtime): A Docker conversation can lose the auxiliary title profile at the runtime boundary, leaving an ACP conversation untitled or producing an unrelated title-auth error while the agent still works. Recheck a saved reachable title profile and an ACP conversation inside an owned per-conversation Docker runtime, comparing its title/profile metadata with the host; inspect only profile names and credential-presence booleans. Blocked without Docker and real auxiliary-title/ACP credentials. - Known issue OpenHands/software-agent-sdk#5307 (
F26.docker-conversation-runtime): New worktree on a Docker-backed conversation can create git metadata whose reverse path exists only inside the container, so the still-live host worktree readsprunable gitdir file points to non-existent location. Recheck a disposable real git repository mounted into an owned conversation container, comparing host and containergit worktree list/status while it is alive; a local worktree does not test the filesystem boundary. Blocked without Docker. - Known issue OpenHands/software-agent-sdk#4901 (
F26.runtime-services): closing an ACP conversation on POSIX is reported to leave the adapter's descendant Node/CLI processes alive after the top npm process exits. Recheck an owned authenticated ACP provider command chain, record its exact descendant identities before close and inspect only those identities afterwards; cleanup must target those owned groups. The current run has no authorized authenticated ACP runtime for this path. - Known issue OpenHands/software-agent-sdk#5974 (
F26.runtime-services; workspace picker in F03): a saved-workspace mutation waiting for its registry file lock can block the Agent Server event loop, including/alive, until the lock is released. Recheck only an owned registry using a bounded lock holder, an independently confirmed waiting mutation, concurrent liveness probes and a successful post-release readback; the original evidence uses Linux kernel lock-wait readback. A healthy idle server or concurrent writes without deliberate lock contention do not cover it. - Known issue OpenHands/software-agent-sdk#5731 (
F26.cli-public-needs-key): whitespace-only session keys remain configured credentials in the Agent Server. The Canvas launcher forwards a nonemptyLOCAL_BACKEND_API_KEYverbatim, so a whitespace-only deployment value can leave the public login unable to use its intended key. Recheck an owned loopback-only public deployment with a whitespace-only supplied key, its actual HTTP/WebSocket authentication and a normal nonblank control; never test the server's default broad bind on an exposed interface. The SDK's missing-OH_SECRET_KEYcipher fallback is a separate configuration branch from a Canvas launcher that supplies an encryption key.
F27 Workspace tools: terminal, browser, planner, tasks and usage
30 behaviors · Read this family’s scripts
- Empty toolsF27.terminal-empty · F27.browser-empty · F27.planner-emptyKnown issue
- Usage totalsF27.usage-metrics · F27.usage-provider-balanceMapped behavior
- Compact contextF27.usage-compactMapped behavior
- Composer context ringF27.composer-context-meterMapped behavior
- Agent-driven toolsF27.terminal-output · F27.canvas-ui-open-tabKnown issue
- Terminal after reloadF27.terminal-history-reload · F27.terminal-live-appendKnown failure
- Agent tab survives reloadF27.canvas-ui-open-tabMapped behavior
- Task ListF27.tasklistMapped behavior
- Plan and BuildF27.planner-plan · F27.planner-buildKnown issue
- Create a planF27.planner-createMapped behavior
- Open a file from the agentF27.canvas-ui-navigate-fileMapped behavior
- Launch a childF27.launch-childKnown issue
- OverviewF27.overview-peek · F27.overview-pin · F27.overview-changes-link · F27.overview-drawerMapped behavior
- Overview menu opens CommitsF27.overview-menu-openMapped behavior
- Workspace and repository identityF27.overview-identityKnown issue
- No browser tool here (`F27.browser-screenshot`, blocked)F27.browser-screenshotKnown issueBlocked
- Info modals at phone widthF27.info-modals-phoneMapped behavior
- Agent tab at phone widthF27.canvas-ui-phoneMapped behavior
- Phone panel tabsF27.phoneMapped behavior
- Terminal waitingF27.terminal-waitingMapped behavior
- State not reachedF27.usage-emptyMapped behavior
- Plugins modalF27.plugins-modalBehavior contract
Family notes & prerequisites for known issues
- After a reload the Task List (and tab bar entry) appears only once history has loaded; wait about 2 s before counting
[data-active="true"]rows. [data-active]is also used by sidebar conversation cards: always combine it withhas-text=<task title>.browser click --observetakes a plain CSS selector ('[data-testid=compact-context-button]'); thetestid=form fails with aquerySelectorAllSyntaxError.- "Create a plan" leaves that conversation in plan mode: the next composer message goes to the planner helper, which has no
launch_child_conversationorcanvas_ui_control. Use a separate conversation for client-tool prompts. - The child-launch toast's Open link animates;
browser clickon it times out with "element is not stable". Read the child id from the parent's[child-conversation]message instead. GET …/file/download?path=…/.agents_tmp/PLAN.md404 andGET /api/llm/balance404 are expected app-origin errors (no plan yet; no balance endpoint). Count them inbrowser errors --app-onlybut do not report them.- Escape closes the composer context popover and the Overview "..." menu and returns focus to the trigger (#18044); an outside click, or a second click on the trigger, closes them too.
- The Overview column is 28 px narrower than its content (
scrollWidth296,clientWidth268). After some clicks inside it, Playwright's scroll-into-view shifts it and the card looks cut off on the left;browser reloadrestores it before taking screenshots. - The agent may summarize a client-tool action with its own title (for example "Launch local child conversation to reply PONG") instead of "Launching a child conversation"; assert the toast and events, not the chat title.
- The Overview peek appears only while the drawer is open (
canPeekOnHoverneedsisRightPanelShown); abrowser gotoor reload starts with the drawer closed. - The Overview's repo and branch rows depend on a bash probe (
useLocalGitInfo) that runs only while the conversation's status is idle, running, waiting for confirmation or finished and the agent is not in error. Right afterconversation startthe probe has run and its result stays cached on the page, but on an errored conversation a reload hides the rows again, andconversation pausedoes not apply to an errored conversation. Read the rows before anygotoorreload. - At phone width (and in a narrow drawer) the tab row shows only the tabs that fit; the rest are reachable only through the tabs menu (
conversation-tabs-menu-open-<tab>), and which tabs fit depends on the active tab's label width. - Plain
agent-canvasinstances on one machine share the tmux socket/tmp/tmux-<uid>/openhands(OpenHands/OpenHands#17946), so another instance stopping can reset this one's terminal.control-openhands launchgives each run its ownTMUX_TMPDIR, so in verification runs a reset means this run's agent server restarted. - Agent Tools & Metadata remembers the last tab (it reopens on Available Tools).
- The Overview menu opens only Pull Requests (
conversation-overview-menu-open-git-pull_requests); its testids areconversation-overview-menu-open-*and-pin-*forworkspaceand the Git rows only. - Known open issues: terminal history after reload (#17566) still fails (reproduced 2026-10-06); info modals at phone width (#17562) pass.
- Agent tab requests (
open_tab,navigate_to_file, chat file links) are saved per conversation like a user tab click (#18045): after the agent opens Terminal or a file and the page reloads, the drawer starts closed and the panel toggle reopens it on that tab; clicking that tab then closes the drawer. At phone width they navigate to/conversations/<id>/panel. - Known issue #17774 (
F27.planner-emptyF27.planner-plan): Planner reads on a native Windows local backend reject drive-letter/mixed-separator workspace paths withConversation file path must stay inside the workspacebefore a download request. Recheck both a scratch workspace and an opened drive-letter workspace, with and without.agents_tmp/PLAN.md; this run lacks a Windows local Agent Server. - Known issue #17198 (
F27.terminal-output): Native Windows desktop agents intermittently return[Command finished execution with no output]for real file-listing/terminal commands and retry them. Recheck with the affected Windows installer/runtime, project agent definitions and an exact command/workspace; no deterministic pattern or backend trace is provided, and this run has no Windows desktop runtime. The backend counterpart is OpenHands/software-agent-sdk#4963. - Known issue #16551 (
F27.browser-screenshot): On native Windows, the browser tool chooses system Chrome over installed Playwright Chromium and times out before returning state/screenshots. Recheck default browser selection and an explicit executable-path control on a Windows host with both browsers and the reported browser_use runtime; the verification Chromium itself is a different tool. Blocked here without Windows and real browser-tool execution credentials. - Known issue #16581 (
F27.terminal-output): A module-scoped terminal command index can suppress output in a second simultaneously mounted Terminal and reset the first when either unmounts. The report describes a future split-panel/embedded concurrent mount rather than a supported standalone entry point. Recheck in a host that actually mounts two independent Canvas Terminal consumers with real command histories; the current harness has one Terminal route and no such host fixture. - Known issue #17384 (
F27.launch-child): A file-based delegated subagent using a saved profile/provider connection can fail with HTTP 401 while the top-level conversation succeeds, because encrypted provider credentials are not decrypted in that backend factory path. Recheck a reviewed.agents/agents/worker, encrypted provider connection and saved profile using a real key, comparing parent and worker authentication. This is a delegated SDK subagent path, distinct from the client-tool child-launch recipe; neither a dummy key nor an unencrypted profile proves it. - Known issue OpenHands/software-agent-sdk#5533 (
F27.terminal-output): A slow interactive Bash startup can make the first terminal command return early with empty output and a false successful exit code. Recheck both standalone and pooled tmux using a private.bashrcwithsleep 0.4, then a boundedsleep 2first command and its real observation. The shell fixture can be arranged, but the mapped agent-command/Terminal path cannot run here without a model key. - Known issue OpenHands/software-agent-sdk#5322 (
F27.terminal-output): The default tmux pane pool or Windows terminal can letgit log -pstart an interactive pager, so the next agent command receives stale paged output instead of its own result. Recheck a reviewed large git fixture, a real installed pager and a follow-up marker command on each affected terminal backend. The fixture is arrangeable, but the mapped agent-tool path needs a model key (and the Windows half needs Windows). - Known issue #17383 (
F27.browser-screenshot; dependency counterpart OpenHands/software-agent-sdk#5152): unlocked dependency resolution can silently remove the agent's browser tools. The actual 2026-10-12 pinned runtime resolves browser-use 0.11.13, mcp 1.30.0 and fastmcp 3.4.8; its genuine BrowserToolExecutor constructs successfully. That narrowly fails to reproduce the SDK report's specified mcp 2.x import failure. Fresh constructor recheck on 2026-10-16 atb34ac59, using the actual Agent Server 1.55.0 interpreter and private HOME, again resolves browser-use 0.11.13, mcp 1.30.0 and fastmcp 3.4.8 and constructs successfully; no browser operation or model was run. The Canvas/global browser-operation path still needs an authorized real LLM and a genuine browser-enabled agent issuing abrowser_*operation; construction alone does not establish that feature works. - Browser availability also depends on OpenHands/software-agent-sdk#5899 (
F27.browser-screenshot; canonical tool-selection note in F13): a Chromium installed only underPLAYWRIGHT_BROWSERS_PATHis missed by the agent-tool probe. Recheck the real browser-tool operation on a host with only that custom cache and no standard browser, default cache or PATH executable. This Mac's user Chrome must remain installed; an executor constructor or the verification browser is not a successful agent browser operation. - Known issue OpenHands/software-agent-sdk#5835 (
F27.overview-identity): the local Overview Git probe uses conversation-scoped Bash execution; an idle-eviction pass can kill scoped work without a final output. Recheck a disposable short-idle-TTL server while a genuine Canvas Git probe is still executing, with independently observed command lifetime and the eventual output/result. The report's standalone asynchronoussleepreproduction is supporting backend evidence, not proof of a Terminal-tab command, which uses the agent event stream instead.
F28 Automation setup page
13 behaviors · Read this family’s scripts
- Blank formF28.open-blankMapped behavior
- PresetsF28.schedule-presetsKnown failure
- Event fieldsF28.event-triggerMapped behavior
- Invalid drafts saveF28.draft-save · F28.draft-validationMapped behavior
- Required fields before TestF28.required-before-testMapped behavior
- TimeoutF28.timeout · F28.draft-save-errorMapped behavior
- Test gatingF28.test-gatedMapped behavior
- Custom kind and draft TestF28.kind-toggle · F28.draft-testKnown failure
- CreateF28.createMapped behavior
- Error contrastF28.error-contrastMapped behavior
- CleanupF28 · setup / cleanupSupport step
Family notes & prerequisites for known issues
- A toast can cover the toolbar (Save draft, Test, Close) and stays while the pointer rests on it, so the next toolbar click times out ("subtree intercepts pointer events"). After each save,
browser hovera form field (for exampletestid=automation-setup-name) before clicking the toolbar again, as F22's Gotchas say. - Drive inputs with
browser fill: setting.valuefrombrowser evaldoes not reach React state for every field, and a save then sends the old value. - Change one field per Save draft when checking a validation message: a save shows only the first server error, so two edits in one save hide the second.
- A cold load of
/automations/setup?draftId=<id>or?automationId=<id>(a reload or a typed URL) opens the form: re-checked 2026-10-14 on acontrol-openhands launchof main with this family (both read their Name back). An earlier instance of unknown build stayed on Loading saved draft… for more than 20 s; if that returns, compare with opening the same draft from the dashboard. - The draft bar duplicates the prompt error:
Field requiredappears both under Prompt and in the bar. - Kebab Edit on a Custom Python automation shows the code editor instead of the saved bundle summary: open bug #18341 (
F23), with fixes in PRs #18353 and #18444. - Escape on the setup page does nothing, by design (
F23.edit-close).
Before you start
Use an OpenHands checkout at the source revision, with Node 24+, installed npm dependencies, uv / uvx, and a supported Chromium browser. The verification skill is the complete setup contract.
export PATH="$PWD/.agents/skills/verify-openhands/scripts:$PATH"
export OH_VERIFY_RUN=$(control-openhands launch --new --print-run)
control-openhands doctor
control-openhands onboard --skip
# Configure a model only for a scenario that needs one:
control-openhands llm preset deepseek
# When the run is complete:
control-openhands stop
F01 walks onboarding instead of skipping it. No-model checks run before model configuration. Keep OH_VERIFY_RUN set so commands address your own run. Desktop is 1440 × 1000; phone is 390 × 844. Model-backed checks need the configured provider key and budget.
Recipes run in source order within each family and can share fixtures. The page preserves that order; “as above” is a dependency on an earlier case. Setup commands and API writes arrange state. They do not prove a UI path. Follow the family cleanup steps.
A known failure preserves the intended expectation beside the observed defect. Executable known-bug blocks use xfail for a reproduced symptom and xpass when it stops reproducing. Cloud accounts, enterprise capabilities and other unavailable prerequisites remain explicit. “Not run” is different from “blocked”.
The maintained map describes application behavior at its pinned revision. Once a fix is verified in the application version under test, remove the obsolete failure note and keep the normal expectation. Dated evidence belongs in the backfill ledger.
Read the full map index and coverage boundaries, the CLI guide, or the earlier illustrated edition. The verification approach adapts Lauren Tan’s (@poteto) pstack verification-skill generators; attribution and adaptation.