Skip to content

[Feature]: Give automations an editable description, shown in the UI #16925

Description

@VascoSch92

Problem or Motivation

An automation carries a name and nothing else that describes it. The list and detail surfaces have nowhere to say what an automation actually does, so the card falls back to rendering the raw prompt as its subtitle — cards read as instructions addressed to an agent rather than a summary addressed to a person. Once a workspace holds more than a handful of automations, the list stops being scannable.

Renaming is already possible: the Edit dialog renders a Name input and PATCHes /v1/{id}, and the service has always accepted name. Description simply does not exist — there is no column on automations, no field on any request or response schema, and no property on the frontend Automation type.

Desired Behavior

As a user, I can give any automation a short description, edit it later from the same dialog I rename it in, and read it wherever the automation is listed.

  • The Edit dialog offers a Description field alongside Name and Prompt.
  • The automation card's subtitle shows the description, falling back to the prompt when there is none, so undescribed automations look exactly as they do today.
  • The list row and the detail page header both show it.
  • An automation launched from a template arrives with the catalog blurb already filled in, rather than empty.
  • The description survives export/import and git-sync round-trips.

Scope

Three repos, in this order — each is one PR, and the last is blocked on the first two being released.

1. OpenHands/automation — persist and expose the field

  • Migration 020_add_automation_description.py: description (Text, nullable) on automations (latest revision on main is 019)
  • description on the Automation model, on CreateAutomationRequest / UpdateAutomationRequest (max_length=2000), and on AutomationResponse
  • create_automation passes it through — the PATCH handler needs no change, it setattrs everything in body.model_dump(exclude_unset=True)
  • Same field on CreatePromptAutomationRequest / CreatePluginAutomationRequest and both Automation(...) constructions in preset_router.py, so template-created automations can carry one
  • "automationDescription" added to _STATIC_FEATURES in capabilities_router.py
  • git-sync: serialize into automation.yaml from _automation_yaml_fields only when non-null, and read it back in _validate_and_resolve_fields
  • Release to PyPI

2. OpenHands/extensions — declare the attribute

  • "description" added to AutomationAttributeName in automations/index.d.ts
  • automations/interface.schema.json: "description": { "$ref": "#/$defs/attribute" } under attributes.properties (the object sets additionalProperties: false)
  • automations/interface.json: { "type": "textarea", "label": "Description", "required": false }
  • Release

3. OpenHands/OpenHands — edit and display

  • Bump versions.automation in config/defaults.json and @openhands/extensions in package.json
  • description?: string | null on the Automation type; "description" in AutomationAttributeName and in HOST_ATTRIBUTES (ATTRIBUTE_NAMES derives from it)
  • Description textarea in edit-automation-modal.tsx, gated on both the manifest attribute and the automationDescription capability
  • Card subtitle, list row, and detail header render it
  • buildCreatePayload / buildBundlePayload in src/manifests/automation-setup.ts seed it from entry.description
  • Export/import carry it (serializeAutomation, parseAutomationFile, buildCreateAutomationRequest)

Acceptance Criteria

  • A description set in the Edit dialog persists across a reload and appears on the card, the list row, and the detail page.
  • Clearing the description sends null and the card falls back to showing the prompt, unchanged from today's rendering.
  • An automation with no description renders exactly as it does today — no empty line, no layout shift.
  • Renaming still works from the same dialog, and a rename sent together with a description edit succeeds as one PATCH.
  • Against an automation service that predates the field, the Description input does not render and no request carries description — editing name, prompt, model, schedule, and timeout all still work.
  • An automation launched from a template arrives with the catalog description already set.
  • Exporting an automation with a description and re-importing it preserves the description; the export file version stays 1 and older files without the field still import.
  • A git-synced automation with no description produces no change to its automation.yaml — enabling this feature does not re-export every already-synced automation.
  • Editing description in a synced automation.yaml updates the automation on the next sync cycle.
  • A screenshot of the Edit dialog and of the automations list is attached to the PR.

Alternatives Considered

Reuse the prompt as the description. What the cards do today, and the reason they read poorly — a prompt is written for an agent and is often several hundred characters.

Skip the extensions release and make Description a host-owned field. Every input in the Edit dialog resolves through getAttributeSpec(), and the attribute set is published by @openhands/extensions in automations/interface.json; an attribute the manifest does not declare does not render. Rendering it outside that lookup would cut the change from three repos to two, but it breaks the rule the whole automations surface is built on — the host holds no automation-specific copy or field list. Rejected in favour of a three-file change plus a version bump.

Store the description in preset_metadata. Avoids a migration, but the field would exist only for preset-created automations, would not be settable through the normal update path, and would not round-trip through git-sync.

Additional Context

Two traps worth knowing before starting:

  • UpdateAutomationRequest sets extra="forbid", so a PATCH carrying description to an older automation service returns 422 and fails the entire request — including a rename sent alongside it. This is why the UI gates the field on the automationDescription capability rather than on the manifest alone: the manifest ships with the app, but the service version is whatever the deployment happens to run.
  • The git-sync exporter hashes the serialized file tree. Emitting description: null for automations that have none changes every hash on the first cycle and pushes one no-op commit per automation, so the key must be omitted when null — the same reasoning as the existing tarball_executables handling in _automation_yaml_fields.

Editing is currently gated to local backends (canEdit = active.backend.kind === "local", in both src/routes/automation-detail.tsx and src/routes/automations-list.tsx), so this ships local-only. Lifting that gate for cloud is a separate change — it would expose every editable attribute at once, not just this one.

References verified against OpenHands/OpenHands@59981caf7, OpenHands/automation@7e9b89a, and OpenHands/extensions@806dfe5.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions