Repository navigation
feat(hello-world-automation): add script-runner automation plugin example - #804
juanmichelini wants to merge 1 commit into
Conversation
…mple Adds plugins/hello-world-automation, a minimal plugin-backed executable automation. Uses the 'script' runner (python3 scripts/main.py) so the plugin-spec create flow works without a pre-provisioned agent profile. Squashed from branch openhands/automation-plugin-hello-world-script-runner (head e5c7517, PR #797) which originated from a now-deleted fork and was never merged. Co-authored-by: openhands <openhands@all-hands.dev>
all-hands-bot
left a comment
There was a problem hiding this comment.
This review was posted by an AI agent (OpenHands).
Scope check: plugins/<name>/.plugin/plugin.json is this repository's own content layout (see AGENTS.md), and the automation metadata lives inside the plugin manifest rather than in OpenHands/automation, so this change belongs here. Continuing with the technical review.
What I verified against the contract owner. I fetched OpenHands/automation (openhands/automation/plugin_specs.py, router.py, dispatcher.py), which owns the openhands.automation.plugin.v1 schema. The embedded automation block validates against AutomationPluginDefinition (extra="forbid"): literal schema_version, entrypoint.runner="script" with a relative, metacharacter-free command, runtime.plugins: [], an object config_schema whose message default is applied, and a suggested_trigger cron. Entrypoint resolution is cd "$AUTOMATION_PLUGIN_ROOT" && python3 scripts/main.py, and the script-runner tarball ships .automation/config.json at exactly the path the script reads through AUTOMATION_CONFIG_PATH. The AUTOMATION_AGENT_PROFILE_NAME / AUTOMATION_LLM_PROFILE_NAME / AUTOMATION_CALLBACK_API_KEY variables the script reads are the ones the service actually injects. The README's claims about the script runner needing no agent profile, and about conversation runners requiring a runtime.agent_profile, both match the schema. The two vendor manifests are correct symlinks to .plugin, matching the repo convention.
I ran the entrypoint (no env, with AUTOMATION_CONFIG_PATH, and with an unreachable AUTOMATION_CALLBACK_URL): it exits 0 in all three cases, honors the config default and an explicit message, and turns a failed callback into a warning rather than a crash. Focused repo checks pass: tests/test_plugin_manifest.py, tests/test_skill_plugin_loading.py, tests/test_sync_extensions.py, tests/test_skills_catalog.py, tests/test_catalogs.py (225 passed; the one failure is the SDK import test, which needs openhands-sdk and is unrelated to this diff), plus scripts/check_plugin_resources.py.
Findings
-
scripts/main.pyreads the event type from keys that the automation service never sets. See the inline comment on line 88. This is the one behavioral defect in the diff: on an event-triggered run the script always reportsevent_context: (unknown), which contradicts the script's own docstring and the "mention that the run received event context" behavior the PR advertises. Small fix, but worth doing in an example that exists to demonstrate the contract. -
The required
Validate PR descriptioncheck is red on this head. It reports that the description is missing theHUMAN:line and note, theAGENT:marker, and the## Why,## Summary, and## How to Testsections from.github/pull_request_template.md, and that no issue is linked in## Issue Number. The template and the linked-issue readiness gate are repository contribution requirements, so this needs the PR body rewritten before merge. (Not a code problem, and not one of the branch-protection required checks, but it will stay red.) -
Non-blocking: the plugin is not listed in any file under
marketplaces/, sopython scripts/sync_extensions.py --checkemitsnot in any marketplace: ./plugins/hello-world-automation. That warning is explicitly non-blocking and there is precedent (plugins/issue-duplicate-checkeris in the same state), and the launch flow in the description resolves the plugin byrepo_pathrather than through the marketplace, so this does not block the PR. Registering it would make the example discoverable in the generated README catalog.
Verdict
🔄 CHANGES REQUESTED
| if event_payload: | ||
| try: | ||
| event = json.loads(event_payload) | ||
| event_type = event.get("type") or event.get("event_type") or "(unknown)" |
There was a problem hiding this comment.
AUTOMATION_EVENT_PAYLOAD does not contain a type or event_type key, so this always resolves to "(unknown)" on an event-triggered run.
The automation service builds that payload in OpenHands/automation (openhands/automation/dispatcher.py, _build_event_payload) with exactly these top-level keys: trigger (the trigger type string, e.g. "event"), trigger_payload (the full trigger config), automation_id, automation_name, and event (the provider's raw webhook body, e.g. a GitHub payload whose keys are action, issue, comment, repository, sender). There is no type/event_type field at any level, so the branch that prints "responding with the standard greeting plus event notice" is dead code and the demo silently misreports the run.
Suggested fix, matching how the payload is actually shaped:
payload = json.loads(event_payload)
trigger = payload.get("trigger", "(unknown)")
has_event = bool(payload.get("event"))
print(f" event_context: {trigger}{' + event payload' if has_event else ''}")
Description
Adds
plugins/hello-world-automation, a minimal plugin-backed executable automation example using thescriptrunner.python3 scripts/main.py— reads the resolved plugin config, prints a greeting, fires the completion callback.plugin/plugin.jsonunder theautomationkey (openhands.automation.plugin.v1)POST /api/automation/v1/plugin-spec) works without a pre-provisioned agent profile/hello-world-automation:hellocommand for conversation-runner usageBackground
This squashes the work previously on branch
openhands/automation-plugin-hello-world-script-runner(heade5c7517, PR #797), which originated from a now-deleted fork and was never merged. Landing it onmaingives the plugin-spec automation flow a stable, on-main test fixture — the launch flow (/launch?mode=automation&plugin_source=github:OpenHands/extensions&plugin_repo_path=plugins/hello-world-automation) needs the plugin to exist onmainto work end-to-end.Checklist
.plugin/plugin.jsonThis PR was created by an AI agent (OpenHands) on behalf of @juanmichelini.