@openhands/extensions 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/custom-codereview-guide.md +31 -0
- package/.claude-plugin/marketplace.json +9 -0
- package/.codex-plugin/marketplace.json +9 -0
- package/.github/workflows/build-vscode-app.yml +3 -3
- package/.github/workflows/deprecation-check.yml +1 -1
- package/.github/workflows/pypi-publish.yml +2 -2
- package/.github/workflows/tests.yml +1 -1
- package/.plugin/marketplace.json +9 -0
- package/.release-please-manifest.json +1 -1
- package/README.md +3 -2
- package/automations/bundle-index.js +5 -5
- package/automations/catalog/github-issue-to-pr/manifest.json +2 -2
- package/automations/catalog/github-issue-triage/manifest.json +2 -2
- package/automations/catalog/github-pr-reviewer/manifest.json +2 -2
- package/marketplaces/openhands-extensions.json +9 -0
- package/package.json +1 -1
- package/plugins/openhands/skills/openhands-automation/README.md +6 -4
- package/plugins/openhands/skills/openhands-automation/SKILL.md +103 -21
- package/plugins/openhands/skills/openhands-automation/references/custom-automation.md +3 -4
- package/plugins/openhands/skills/openhands-sdk/SKILL.md +2 -1
- package/plugins/qa-changes/README.md +4 -0
- package/plugins/qa-changes/skills/qa-changes/README.md +3 -1
- package/plugins/qa-changes/skills/qa-changes/SKILL.md +42 -0
- package/plugins/vulnerability-remediation/skills/github/README.md +5 -1
- package/plugins/vulnerability-remediation/skills/github/SKILL.md +27 -0
- package/plugins/vulnerability-remediation/skills/github/scripts/agent_conversation.py +51 -4
- package/pyproject.toml +1 -1
- package/python/openhands_extensions/_version.py +1 -1
- package/scripts/sync_openhands_sdk_skill.py +16 -13
- package/skills/azure-devops/README.md +3 -1
- package/skills/azure-devops/SKILL.md +4 -0
- package/skills/bitbucket/README.md +3 -1
- package/skills/bitbucket/SKILL.md +4 -2
- package/skills/bitbucket-cloud/README.md +2 -0
- package/skills/bitbucket-cloud/SKILL.md +2 -0
- package/skills/bitbucket-data-center/README.md +2 -0
- package/skills/bitbucket-data-center/SKILL.md +2 -0
- package/skills/github/README.md +5 -1
- package/skills/github/SKILL.md +27 -0
- package/skills/github/scripts/agent_conversation.py +51 -4
- package/skills/github-issue-to-pr/scripts/agent_conversation.py +51 -4
- package/skills/github-issue-triage/scripts/agent_conversation.py +51 -4
- package/skills/github-pr-reviewer/README.md +5 -0
- package/skills/github-pr-reviewer/SKILL.md +12 -0
- package/skills/github-pr-reviewer/scripts/agent_conversation.py +51 -4
- package/skills/github-pr-reviewer/scripts/main.py +20 -6
- package/skills/github-pr-reviewer/scripts/worker.py +77 -15
- package/skills/github-pr-reviewer/tests/test_main.py +23 -0
- package/skills/gitlab/README.md +3 -1
- package/skills/gitlab/SKILL.md +4 -0
- package/skills/index.js +23 -11
- package/skills/linear/README.md +2 -0
- package/skills/linear/SKILL.md +6 -2
- package/skills/openhands-automation/README.md +6 -4
- package/skills/openhands-automation/SKILL.md +103 -21
- package/skills/openhands-automation/references/custom-automation.md +3 -4
- package/skills/openhands-sdk/SKILL.md +2 -1
- package/skills/qa-changes/README.md +3 -1
- package/skills/qa-changes/SKILL.md +42 -0
- package/skills/simplified-technical-english/.claude-plugin/plugin.json +15 -0
- package/skills/simplified-technical-english/.codex-plugin/plugin.json +15 -0
- package/skills/simplified-technical-english/.plugin/plugin.json +15 -0
- package/skills/simplified-technical-english/README.md +21 -0
- package/skills/simplified-technical-english/SKILL.md +65 -0
- package/tests/fixtures/automations/github-pr-reviewer.json +9 -9
- package/tests/test_agent_conversation_dispatch.py +130 -0
- package/tests/test_github_reviewer_delivery.py +279 -2
package/skills/linear/README.md
CHANGED
|
@@ -12,6 +12,8 @@ This skill is activated by the following keywords:
|
|
|
12
12
|
|
|
13
13
|
## Details
|
|
14
14
|
|
|
15
|
+
Use authenticated Linear MCP tools first when they are available in the agent's environment. Detect the connection through tool availability rather than a particular server name. Fall back to the documented `LINEAR_API_KEY` and direct GraphQL flow when those tools are unavailable or raw API or `curl` access is explicitly needed.
|
|
16
|
+
|
|
15
17
|
You need access to an environment variable, `LINEAR_API_KEY`, which allows you to interact with the Linear API.
|
|
16
18
|
|
|
17
19
|
<IMPORTANT>
|
package/skills/linear/SKILL.md
CHANGED
|
@@ -9,16 +9,20 @@ triggers:
|
|
|
9
9
|
|
|
10
10
|
# Linear
|
|
11
11
|
|
|
12
|
+
## Connection selection
|
|
13
|
+
|
|
14
|
+
Use authenticated Linear MCP tools first when they are available in the agent's environment. Detect this by tool availability, without depending on a particular MCP server name. Use the API key and direct GraphQL instructions below only when Linear MCP tools are unavailable or when raw API or `curl` access is explicitly needed.
|
|
15
|
+
|
|
12
16
|
Windows PowerShell equivalents for the repeated Linear GraphQL `curl` and environment-variable snippets are in `references/windows.md`.
|
|
13
17
|
|
|
14
18
|
<IMPORTANT>
|
|
15
|
-
Before
|
|
19
|
+
Before using the direct API fallback, check if the required environment variable is set:
|
|
16
20
|
|
|
17
21
|
```bash
|
|
18
22
|
[ -n "$LINEAR_API_KEY" ] && echo "LINEAR_API_KEY is set" || echo "LINEAR_API_KEY is NOT set"
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
If LINEAR_API_KEY is missing, ask the user to provide it before proceeding.
|
|
25
|
+
If LINEAR_API_KEY is missing and authenticated Linear MCP tools are unavailable, ask the user to provide it before proceeding.
|
|
22
26
|
</IMPORTANT>
|
|
23
27
|
|
|
24
28
|
## Understanding Linear Identifiers
|
|
@@ -16,13 +16,13 @@ This skill is activated by keywords:
|
|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
19
|
-
- **Prompt-based creation**: Create automations from a natural language prompt
|
|
19
|
+
- **Prompt-based creation**: Create automations from a natural language prompt, for tasks that benefit from agent reasoning
|
|
20
|
+
- **Custom scripts**: Run your own code, with or without an LLM — the cheaper, more reliable fit for deterministic tasks (fixed data, scheduled HTTP calls, templated messages), and for custom dependencies or full control (see [references/custom-automation.md](references/custom-automation.md))
|
|
20
21
|
- **Event-triggered automations**: Trigger on GitHub events (PR opened, issue commented, push, etc.)
|
|
21
22
|
- **Custom webhooks**: Register webhooks for any service (Stripe, Slack, Linear, etc.)
|
|
22
23
|
- **JMESPath filters**: Match events based on payload content (labels, mentions, repos)
|
|
23
24
|
- **Automation management**: List, update, enable/disable, and delete automations
|
|
24
25
|
- **Manual dispatch**: Trigger automation runs on-demand
|
|
25
|
-
- **Custom automations**: For advanced users who need full control (see [references/custom-automation.md](references/custom-automation.md))
|
|
26
26
|
|
|
27
27
|
## API Base URL
|
|
28
28
|
|
|
@@ -30,6 +30,8 @@ Use an explicitly provided host first. When a local Agent Canvas automation serv
|
|
|
30
30
|
|
|
31
31
|
## Quick Start
|
|
32
32
|
|
|
33
|
+
The examples below use the prompt preset, which suits tasks that need reasoning or judgment. For a deterministic task that needs no LLM, use a custom script instead — see the *Custom Script Example (No LLM)* in [SKILL.md](SKILL.md).
|
|
34
|
+
|
|
33
35
|
### Cron-Triggered Automation
|
|
34
36
|
|
|
35
37
|
```bash
|
|
@@ -81,9 +83,9 @@ curl -X POST "https://app.all-hands.dev/api/automation/v1/preset/prompt" \
|
|
|
81
83
|
}'
|
|
82
84
|
```
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
For preset automations, the service handles SDK code generation, tarball packaging, upload, and automation creation automatically.
|
|
85
87
|
|
|
86
88
|
## See Also
|
|
87
89
|
|
|
88
90
|
- [SKILL.md](SKILL.md) — Full API reference, agent behavior rules, event keys, filters, and examples
|
|
89
|
-
- [references/custom-automation.md](references/custom-automation.md) — Reference for custom automations with user-provided SDK
|
|
91
|
+
- [references/custom-automation.md](references/custom-automation.md) — Reference for custom automations with user-provided scripts, SDK-based or deterministic (no LLM)
|
|
@@ -64,14 +64,14 @@ The agent server typically runs inside a **sandbox** (a Docker or Kubernetes con
|
|
|
64
64
|
> 1. **For LLM-appropriate work, default to preset endpoints.** They handle all SDK boilerplate, tarball packaging, and upload automatically:
|
|
65
65
|
> - **Prompt preset** (`POST /v1/preset/prompt`) — for tasks expressed as a natural language prompt that benefit from agent reasoning
|
|
66
66
|
> - **Plugin preset** (`POST /v1/preset/plugin`) — when plugins with skills, MCP configs, or commands are needed
|
|
67
|
-
> 2. **
|
|
68
|
-
>
|
|
69
|
-
> - **
|
|
70
|
-
> - **
|
|
71
|
-
>
|
|
72
|
-
>
|
|
73
|
-
>
|
|
74
|
-
>
|
|
67
|
+
> 2. **Present the options, then build the one the user picks.** Whenever rule 0 applies, or neither preset is a clean fit (custom Python dependencies, a non-Python entrypoint, a multi-file project, direct SDK lifecycle control), lay the choices out side by side with a one-line note on cost and reliability for each, and let the user choose:
|
|
68
|
+
> - **Prompt preset** - natural language prompt execution (LLM-driven)
|
|
69
|
+
> - **Plugin preset** - load plugins with extended capabilities (skills, MCP, hooks, commands)
|
|
70
|
+
> - **Custom script** - full control over code, with or without an LLM; see `references/custom-automation.md`
|
|
71
|
+
>
|
|
72
|
+
> Do not silently fall back to either side. The "ready to deploy?" confirmation in the creation process applies to every path equally; a custom script needs no extra permission beyond it, and a preset gets no pass on it.
|
|
73
|
+
> 3. **Building a custom script:** follow `references/custom-automation.md` for tarball packaging, validation, and upload. The *Custom Script Example (No LLM)* below shows the whole flow end to end.
|
|
74
|
+
> 4. **Before suggesting event-triggered (webhook) automations, check whether the deployment is publicly reachable.** Check `RUNTIME_URL`. Webhooks require an internet-accessible URL so that external services (GitHub, Slack, Linear, etc.) can deliver events to the automation service. If `RUNTIME_URL` is unset, empty, or resolves to a local or private address (`localhost`, `127.0.0.1`, `0.0.0.0`, or any RFC 1918 range: `10.x.x.x`, `192.168.x.x`, `172.16–31.x.x`), the service cannot receive inbound webhook traffic from the public internet. In that case:
|
|
75
75
|
> - **Recommend a cron-based polling automation instead.** Have the automation run on a schedule and call the external service's API (e.g., the GitHub REST API) to check for new events since the last run.
|
|
76
76
|
> - Explain the limitation clearly to the user: "Because this is a local deployment, external services can't reach the webhook endpoint. I'll set up a polling automation using a cron schedule instead."
|
|
77
77
|
|
|
@@ -255,8 +255,10 @@ curl -X POST "${OPENHANDS_HOST}/api/automation/v1/preset/prompt" \
|
|
|
255
255
|
Write the prompt as an instruction to an AI agent. The prompt executes inside a sandbox with full tool access (bash, file editing, etc.), the user's configured LLM, stored secrets, and MCP server integrations. Examples:
|
|
256
256
|
|
|
257
257
|
- `"Generate a weekly status report summarizing the team's GitHub activity and post it to Slack"`
|
|
258
|
-
- `"
|
|
259
|
-
- `"
|
|
258
|
+
- `"Read yesterday's new error reports in Sentry, group them by likely root cause, and open one GitHub issue per new failure pattern with a proposed fix"`
|
|
259
|
+
- `"Go through support tickets tagged 'bug' since the last run, try to reproduce each against main, and comment on the ticket with what you found"`
|
|
260
|
+
|
|
261
|
+
Each of these needs judgment: deciding what counts as a pattern, whether a reproduction succeeded, what is worth reporting. A task whose output could be written as a fixed template right now belongs in a custom script instead (see *Custom Script Example (No LLM)* below).
|
|
260
262
|
|
|
261
263
|
#### Cron Schedule
|
|
262
264
|
|
|
@@ -296,24 +298,105 @@ curl -X POST "${OPENHANDS_HOST}/api/automation/v1/preset/prompt" \
|
|
|
296
298
|
}'
|
|
297
299
|
```
|
|
298
300
|
|
|
299
|
-
**Weekly
|
|
301
|
+
**Weekly dependency review:**
|
|
300
302
|
```bash
|
|
301
303
|
curl -X POST "${OPENHANDS_HOST}/api/automation/v1/preset/prompt" \
|
|
302
304
|
-H "Authorization: Bearer ${OPENHANDS_API_KEY}" \
|
|
303
305
|
-H "Content-Type: application/json" \
|
|
304
306
|
-d '{
|
|
305
|
-
"name": "Weekly
|
|
306
|
-
"prompt": "
|
|
307
|
+
"name": "Weekly Dependency Review",
|
|
308
|
+
"prompt": "Check the repository dependencies for new releases. Read each changelog, open one PR with the upgrades that look safe, and list any release with breaking changes in the PR description so a human can decide on it",
|
|
307
309
|
"trigger": {"type": "cron", "schedule": "0 2 * * 0", "timezone": "UTC"},
|
|
308
|
-
"timeout":
|
|
310
|
+
"timeout": 1800
|
|
309
311
|
}'
|
|
310
312
|
```
|
|
311
313
|
|
|
314
|
+
### Custom Script Example (No LLM)
|
|
315
|
+
|
|
316
|
+
The same shape as the prompt preset, for a task that needs no reasoning: check a URL on a schedule and post to Slack only when it fails. Every run takes a moment and costs no tokens. This is the complete flow; `get_secret` and `fire_callback` are the helpers from *No-LLM Script Helpers* above.
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
mkdir healthcheck && cd healthcheck
|
|
320
|
+
|
|
321
|
+
cat > main.py << 'PYEOF'
|
|
322
|
+
"""Hourly health check: alert Slack on a non-200 response. No LLM, no SDK."""
|
|
323
|
+
import json, os, sys, urllib.request
|
|
324
|
+
|
|
325
|
+
URL = "https://api.example.com/health"
|
|
326
|
+
CHANNEL = "C12345678"
|
|
327
|
+
|
|
328
|
+
def get_secret(name):
|
|
329
|
+
url = os.environ.get("AGENT_SERVER_URL", "").rstrip("/")
|
|
330
|
+
key = os.environ.get("SESSION_API_KEY") or os.environ.get("OH_SESSION_API_KEYS_0", "")
|
|
331
|
+
if url: # local Agent Canvas
|
|
332
|
+
url = f"{url}/api/settings/secrets/{name}"
|
|
333
|
+
else: # OpenHands Cloud / Enterprise
|
|
334
|
+
api = os.environ["OPENHANDS_CLOUD_API_URL"].rstrip("/")
|
|
335
|
+
url = f"{api}/api/v1/sandboxes/{os.environ['SANDBOX_ID']}/settings/secrets/{name}"
|
|
336
|
+
req = urllib.request.Request(url,
|
|
337
|
+
headers={"X-Session-API-Key": key})
|
|
338
|
+
with urllib.request.urlopen(req) as r:
|
|
339
|
+
return r.read().decode().strip()
|
|
340
|
+
|
|
341
|
+
def fire_callback(status="COMPLETED", error=None):
|
|
342
|
+
url = os.environ.get("AUTOMATION_CALLBACK_URL", "")
|
|
343
|
+
if not url: return
|
|
344
|
+
body = {"status": status, "run_id": os.environ.get("AUTOMATION_RUN_ID", "")}
|
|
345
|
+
if error: body["error"] = error
|
|
346
|
+
req = urllib.request.Request(url, data=json.dumps(body).encode(), headers={
|
|
347
|
+
"Content-Type": "application/json",
|
|
348
|
+
"Authorization": f"Bearer {os.environ.get('AUTOMATION_CALLBACK_API_KEY', '')}",
|
|
349
|
+
})
|
|
350
|
+
try: urllib.request.urlopen(req)
|
|
351
|
+
except Exception as e: print(f"Callback error: {e}")
|
|
352
|
+
|
|
353
|
+
def slack(text):
|
|
354
|
+
token = get_secret("SLACK_BOT_TOKEN")
|
|
355
|
+
req = urllib.request.Request("https://slack.com/api/chat.postMessage",
|
|
356
|
+
data=json.dumps({"channel": CHANNEL, "text": text}).encode(),
|
|
357
|
+
headers={"Content-Type": "application/json", "Authorization": f"Bearer {token}"})
|
|
358
|
+
urllib.request.urlopen(req)
|
|
359
|
+
|
|
360
|
+
try:
|
|
361
|
+
try:
|
|
362
|
+
status = urllib.request.urlopen(URL, timeout=10).status
|
|
363
|
+
except Exception as e:
|
|
364
|
+
status = f"error: {e}"
|
|
365
|
+
if status != 200:
|
|
366
|
+
slack(f":rotating_light: {URL} returned {status}")
|
|
367
|
+
print(f"{URL} -> {status}")
|
|
368
|
+
fire_callback("COMPLETED")
|
|
369
|
+
except Exception as e:
|
|
370
|
+
print(f"ERROR: {e}", file=sys.stderr)
|
|
371
|
+
fire_callback("FAILED", str(e))
|
|
372
|
+
sys.exit(1)
|
|
373
|
+
PYEOF
|
|
374
|
+
|
|
375
|
+
tar -czf ../healthcheck.tar.gz .
|
|
376
|
+
|
|
377
|
+
TARBALL_PATH=$(curl -s -X POST "${OPENHANDS_HOST}/api/automation/v1/uploads?name=healthcheck" \
|
|
378
|
+
-H "Authorization: Bearer ${OPENHANDS_API_KEY}" \
|
|
379
|
+
-H "Content-Type: application/gzip" \
|
|
380
|
+
--data-binary @../healthcheck.tar.gz | jq -r '.tarball_path')
|
|
381
|
+
|
|
382
|
+
curl -X POST "${OPENHANDS_HOST}/api/automation/v1" \
|
|
383
|
+
-H "Authorization: Bearer ${OPENHANDS_API_KEY}" \
|
|
384
|
+
-H "Content-Type: application/json" \
|
|
385
|
+
-d "{
|
|
386
|
+
\"name\": \"Hourly Health Check\",
|
|
387
|
+
\"trigger\": {\"type\": \"cron\", \"schedule\": \"0 * * * *\", \"timezone\": \"UTC\"},
|
|
388
|
+
\"tarball_path\": \"$TARBALL_PATH\",
|
|
389
|
+
\"entrypoint\": \"python3 main.py\"
|
|
390
|
+
}"
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
For state between runs (last alert time, last seen event), use the KV store helpers in `references/custom-automation.md#state-persistence-kv-store`.
|
|
394
|
+
|
|
312
395
|
---
|
|
313
396
|
|
|
314
397
|
## Polling as a Webhook Alternative
|
|
315
398
|
|
|
316
|
-
When the deployment cannot receive inbound webhook traffic (see rule
|
|
399
|
+
When the deployment cannot receive inbound webhook traffic (see rule 4), use a cron-triggered automation that calls the external service’s API on a schedule to check for new events.
|
|
317
400
|
|
|
318
401
|
### Polling vs. Webhooks at a Glance
|
|
319
402
|
|
|
@@ -442,15 +525,15 @@ curl -X POST "${OPENHANDS_HOST}/api/automation/v1/preset/prompt" \
|
|
|
442
525
|
}'
|
|
443
526
|
```
|
|
444
527
|
|
|
445
|
-
#### GitHub:
|
|
528
|
+
#### GitHub: Flag risky changes pushed to main
|
|
446
529
|
|
|
447
530
|
```bash
|
|
448
531
|
curl -X POST "${OPENHANDS_HOST}/api/automation/v1/preset/prompt" \
|
|
449
532
|
-H "Authorization: Bearer ${OPENHANDS_API_KEY}" \
|
|
450
533
|
-H "Content-Type: application/json" \
|
|
451
534
|
-d '{
|
|
452
|
-
"name": "
|
|
453
|
-
"prompt": "
|
|
535
|
+
"name": "Risky Change Watch",
|
|
536
|
+
"prompt": "Review the diff of this push. If it touches authentication, billing, data migrations, or anything that changes behavior for existing users, open an issue that explains the risk in plain terms and mentions the code owners. Otherwise do nothing.",
|
|
454
537
|
"trigger": {
|
|
455
538
|
"type": "event",
|
|
456
539
|
"source": "github",
|
|
@@ -942,7 +1025,7 @@ The **prompt preset** is the right default for genuinely agent-shaped work — a
|
|
|
942
1025
|
|
|
943
1026
|
**Watch for deterministic, high-frequency patterns.** Requests like "send a daily standup reminder", "ping a healthcheck URL every minute", "post a random quote every 5 minutes", or "rotate a fact-of-the-day message" do not need an LLM. Surface this to the user explicitly with a rough cost framing (e.g. "this schedule will invoke your LLM ~288 times/day") before defaulting to a preset. As a rule of thumb, any cron tighter than hourly deserves a deliberate "should this really be agent-driven?" check.
|
|
944
1027
|
|
|
945
|
-
**When neither preset is the right fit** (deterministic task, custom Python dependencies, non-Python entrypoint, multi-file project structure, direct SDK lifecycle control), explain the options
|
|
1028
|
+
**When neither preset is the right fit** (deterministic task, custom Python dependencies, non-Python entrypoint, multi-file project structure, direct SDK lifecycle control), explain the options and let the user decide, exactly as for any other automation. If they choose the custom route, follow `references/custom-automation.md` and the *Custom Script Example (No LLM)* above.
|
|
946
1029
|
|
|
947
1030
|
## Security Considerations
|
|
948
1031
|
|
|
@@ -955,7 +1038,6 @@ See `references/security.md` — also covers narrowing triggers and sender-level
|
|
|
955
1038
|
|
|
956
1039
|
## Reference Files
|
|
957
1040
|
|
|
958
|
-
- **`references/custom-automation.md`** — Detailed guide for custom automations: tarball uploads, code structure (SDK and no-LLM), state persistence via the KV store, environment variables, validation rules, and complete examples. Consult this whenever you need to evaluate or
|
|
1041
|
+
- **`references/custom-automation.md`** — Detailed guide for custom automations: tarball uploads, code structure (SDK and no-LLM), state persistence via the KV store, environment variables, validation rules, and complete examples. Consult this whenever you need to evaluate, recommend, or build the custom path (including for deterministic / cost-sensitive tasks per rule 0).
|
|
959
1042
|
- **`references/ab-testing.md`** — A/B testing for plugin automations: defining variants with weights, experiment configuration, variant selection logic, observability via conversation tags, and complete examples. Consult this when a user wants to compare plugin versions or configurations.
|
|
960
|
-
- **`references/security.md`** — Trust boundaries: untrusted content vs. verified sender, least-privilege secrets, trigger scoping, sender authorization, pre-deploy verification. Consult whenever an automation handles external input or forwards secrets to a spawned conversation.
|
|
961
1043
|
- **`references/security.md`** — Trust boundaries for automations: untrusted event content vs. verified sender, least-privilege secret scoping for spawned conversations, narrowing triggers, sender-level authorization, and verifying a script actually runs before deploying it. Consult this whenever an automation handles external/untrusted input (GitHub issues/PRs, Slack messages, any public-facing webhook) or forwards secrets to a spawned conversation.
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# Custom Automation Reference
|
|
2
2
|
|
|
3
|
-
> **⚠️ Do NOT use this reference unless the user has explicitly requested a custom automation.** Always use the preset/prompt endpoint from the main SKILL.md first. If the preset approach cannot satisfy the requirement, explain the options to the user and let them decide.
|
|
4
|
-
|
|
5
3
|
This file contains detailed documentation for creating custom automations with user-provided code, uploads, and entrypoints.
|
|
6
4
|
|
|
7
|
-
**When to use custom automation
|
|
5
|
+
**When to use a custom automation:**
|
|
6
|
+
- The task is deterministic and needs no LLM (fixed data, scheduled HTTP calls, templated messages), especially on a frequent schedule
|
|
8
7
|
- Full control over the automation code structure is needed
|
|
9
8
|
- Custom dependencies or a specific runtime are required
|
|
10
|
-
- The user
|
|
9
|
+
- The user picked this path after seeing the options side by side (see the agent behavior rules in `SKILL.md`)
|
|
11
10
|
|
|
12
11
|
## Table of Contents
|
|
13
12
|
|
|
@@ -131,10 +131,11 @@ print("All done!")
|
|
|
131
131
|
- [Secret Registry](https://docs.openhands.dev/sdk/guides/secrets.md): Provide environment variables and secrets to agent workspace securely.
|
|
132
132
|
- [Security & Action Confirmation](https://docs.openhands.dev/sdk/guides/security.md): Control agent action execution through confirmation policy and security analyzer.
|
|
133
133
|
- [Send Message While Running](https://docs.openhands.dev/sdk/guides/convo-send-message-while-running.md): Interrupt running agents to provide additional context or corrections.
|
|
134
|
-
- [Software Agent SDK](https://docs.openhands.dev/sdk.md): Build AI agents that write software. A clean, modular SDK with production-ready tools.
|
|
134
|
+
- [Software Agent SDK](https://docs.openhands.dev/sdk/index.md): Build AI agents that write software. A clean, modular SDK with production-ready tools.
|
|
135
135
|
- [Structured Output](https://docs.openhands.dev/sdk/guides/structured-output.md): Attach a schema to any tool so the LLM returns typed, validated fields alongside the tool's own arguments.
|
|
136
136
|
- [Stuck Detector](https://docs.openhands.dev/sdk/guides/agent-stuck-detector.md): Detect and handle stuck agents automatically with timeout mechanisms.
|
|
137
137
|
- [Task Tool Set](https://docs.openhands.dev/sdk/guides/task-tool-set.md): Delegate complex work to specialized sub-agents that run synchronously and return results to the parent agent.
|
|
138
|
+
- [Task-Based Model Routing](https://docs.openhands.dev/sdk/guides/llm-task-routing.md): Let the agent pick the best saved LLM profile for the task at hand with the built-in route_task_to_model tool.
|
|
138
139
|
- [Theory of Mind (TOM) Agent](https://docs.openhands.dev/sdk/guides/agent-tom-agent.md): Enable your agent to understand user intent and preferences through Theory of Mind capabilities, providing personalized guidance based on user modeling.
|
|
139
140
|
- [TODO Management](https://docs.openhands.dev/sdk/guides/github-workflows/todo-management.md): Implement TODOs using OpenHands Agent
|
|
140
141
|
|
|
@@ -14,5 +14,7 @@ The skill guides the agent through four phases:
|
|
|
14
14
|
|
|
15
15
|
1. **Understand** — Classify changes and identify entry points
|
|
16
16
|
2. **Setup** — Install dependencies, build, check CI status
|
|
17
|
-
3. **Exercise** — Run the actual code as a user would (browser, CLI, API requests)
|
|
17
|
+
3. **Exercise** — Run the actual code as a user would (browser, CLI, API requests).
|
|
18
|
+
For frontend changes, capture screenshots of each affected state and a GIF of
|
|
19
|
+
the key interaction (before/after where behavior changes)
|
|
18
20
|
4. **Report** — Post a structured QA report with evidence and a verdict
|
|
@@ -75,6 +75,37 @@ This is the most important phase. **Actually use the software** the way a real u
|
|
|
75
75
|
- Verify the visual change renders correctly. Take screenshots as evidence.
|
|
76
76
|
- Test user interactions (clicks, form submissions, navigation).
|
|
77
77
|
- Try at least one edge case (empty state, long text, missing data).
|
|
78
|
+
- Then capture visual evidence and attach it to the PR (see next step).
|
|
79
|
+
|
|
80
|
+
**Capture visual evidence (frontend PRs only):**
|
|
81
|
+
|
|
82
|
+
If the PR has frontend work, run the affected screens from the branch's final
|
|
83
|
+
state and record what a reviewer would otherwise have to imagine from the diff.
|
|
84
|
+
The goal: the change can be reviewed **by observation, not by reading code.**
|
|
85
|
+
|
|
86
|
+
1. **Screenshot each relevant state** of every affected screen - whichever
|
|
87
|
+
apply: *empty*, *loading*, *error*, and *populated*. Skip states the screen
|
|
88
|
+
genuinely cannot reach.
|
|
89
|
+
2. **Record the key interaction end to end** - the main flow the PR changes,
|
|
90
|
+
driven the way a user would. Prefer a GIF: GitHub renders a GIF inline from
|
|
91
|
+
an image link, but only links a video file.
|
|
92
|
+
3. **Where behavior changes, capture before/after** - the same state or
|
|
93
|
+
interaction on the base branch and on the PR branch, so the delta is
|
|
94
|
+
visible.
|
|
95
|
+
4. **Attach it to the report.** Embed the images and GIF in the QA report so
|
|
96
|
+
they render inline, and label each one (screen and state, or before/after).
|
|
97
|
+
Do not push commits to the PR branch to host media: that changes the head
|
|
98
|
+
you are verifying, and the shipped QA workflow has read-only access to
|
|
99
|
+
repository contents. If you cannot upload media where the report is posted,
|
|
100
|
+
save the files where the run keeps its artifacts, say where to find them,
|
|
101
|
+
and describe in text what each capture shows. In the `qa-changes` GitHub
|
|
102
|
+
Action that is `$GITHUB_WORKSPACE/output/`, the parent of the PR checkout
|
|
103
|
+
you work in, which the action uploads as the `openhands-qa-changes-logs`
|
|
104
|
+
artifact; a relative `output/` inside the checkout is not uploaded.
|
|
105
|
+
|
|
106
|
+
Keep it proportional: capture the screens the PR actually touches, not the whole
|
|
107
|
+
app. If you cannot render a screen (missing data, an unreachable state, no
|
|
108
|
+
browser), say so in the report rather than faking it.
|
|
78
109
|
|
|
79
110
|
**For CLI changes:**
|
|
80
111
|
- Run the CLI command with realistic arguments. Capture stdout and stderr.
|
|
@@ -181,6 +212,16 @@ prior state rather than reproducing a failure.}
|
|
|
181
212
|
|
|
182
213
|
</details>
|
|
183
214
|
|
|
215
|
+
<details><summary>Visual Evidence</summary>
|
|
216
|
+
|
|
217
|
+
{Frontend PRs only. Embed the screenshots (per screen and state: empty,
|
|
218
|
+
loading, error, populated) and the GIF of the key interaction so they
|
|
219
|
+
render inline, or say where the captures are stored if they could not be
|
|
220
|
+
uploaded. Where behavior changed, show before/after. Label each clearly.
|
|
221
|
+
Omit this section entirely for non-frontend PRs.}
|
|
222
|
+
|
|
223
|
+
</details>
|
|
224
|
+
|
|
184
225
|
<details><summary>Unable to Verify</summary>
|
|
185
226
|
|
|
186
227
|
{What could not be verified, what was attempted, and suggested
|
|
@@ -221,6 +262,7 @@ was verified.}
|
|
|
221
262
|
- **Run the code, not the tests.** Execute the actual software — start servers, run CLI commands, make HTTP requests, open browsers. Do not run `pytest`, `npm test`, or equivalent test suites. That is CI's job.
|
|
222
263
|
- **Do not analyze code.** Reading files and commenting on style, structure, or logic is code review's job. Your job is to exercise behavior, not read source files.
|
|
223
264
|
- **Set a high bar.** If the change affects a UI, open it in a real browser. If it affects a CLI, run the actual CLI with real inputs. If it affects an API, make real HTTP requests.
|
|
265
|
+
- **Make frontend changes reviewable by observation.** For UI PRs, attach screenshots of each relevant state and a GIF of the key interaction (before/after where behavior changes) so a reviewer can see the change, not infer it from the diff.
|
|
224
266
|
- **Test what the PR claims.** The PR description is the specification. Verify the claim, not hypothetical scenarios.
|
|
225
267
|
- **Leave CI to CI.** Do not re-run tests, linters, formatters, or type checkers. Note CI status, then focus entirely on functional verification that CI cannot do.
|
|
226
268
|
- **Report evidence, not opinions.** Include exact commands, outputs, and error messages — inside collapsible blocks.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "simplified-technical-english",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Write explanations and chat in the style of ASD-STE100 Simplified Technical English: short active sentences, one idea each, plain consistent words. Applies to prose only, never to code.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "OpenHands",
|
|
7
|
+
"email": "contact@all-hands.dev"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/OpenHands/extensions",
|
|
10
|
+
"repository": "https://github.com/OpenHands/extensions",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"simplified-technical-english"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "simplified-technical-english",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Write explanations and chat in the style of ASD-STE100 Simplified Technical English: short active sentences, one idea each, plain consistent words. Applies to prose only, never to code.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "OpenHands",
|
|
7
|
+
"email": "contact@all-hands.dev"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/OpenHands/extensions",
|
|
10
|
+
"repository": "https://github.com/OpenHands/extensions",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"simplified-technical-english"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "simplified-technical-english",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Write explanations and chat in the style of ASD-STE100 Simplified Technical English: short active sentences, one idea each, plain consistent words. Applies to prose only, never to code.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "OpenHands",
|
|
7
|
+
"email": "contact@all-hands.dev"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/OpenHands/extensions",
|
|
10
|
+
"repository": "https://github.com/OpenHands/extensions",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"simplified-technical-english"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Simplified Technical English skill
|
|
2
|
+
|
|
3
|
+
This skill helps OpenHands write **prose** in the style of ASD-STE100 Simplified
|
|
4
|
+
Technical English: short active sentences, one idea each, plain and consistent
|
|
5
|
+
words. The aim is text that is easy to read the first time. This matters most
|
|
6
|
+
for readers whose first language is not English, and for instructions where a
|
|
7
|
+
misread is costly.
|
|
8
|
+
|
|
9
|
+
Use it for:
|
|
10
|
+
|
|
11
|
+
- chat replies, explanations, summaries, and step lists that need maximum clarity
|
|
12
|
+
- ops, deploy, or security instructions where a misread is costly
|
|
13
|
+
- briefing another agent to produce plain, scannable prose
|
|
14
|
+
|
|
15
|
+
**The hard boundary is prose only.** The skill must never change code, identifiers,
|
|
16
|
+
CLI flags, API fields, commit messages, or reference/API docs. A controlled
|
|
17
|
+
English vocabulary must not bleed into code, where exact domain terms win.
|
|
18
|
+
|
|
19
|
+
It complements `plain-english-content` (GOV.UK-style content design) and
|
|
20
|
+
`technical-writing` (conversational engineering prose); this one adds the
|
|
21
|
+
ASD-STE100 register and the explicit "do not touch code" guardrail.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: simplified-technical-english
|
|
3
|
+
description: >
|
|
4
|
+
Write explanations and chat in the style of ASD-STE100 Simplified Technical
|
|
5
|
+
English: short active sentences, one idea each, plain approved words. Use this
|
|
6
|
+
when the reader benefits from maximum clarity: summaries, PR descriptions,
|
|
7
|
+
safety- or ops-critical instructions, or any comment or reply that should be easy
|
|
8
|
+
to read the first time. Applies to PROSE ONLY; it must never change code, identifiers,
|
|
9
|
+
APIs, or commit messages.
|
|
10
|
+
license: MIT
|
|
11
|
+
triggers:
|
|
12
|
+
- simplified technical english
|
|
13
|
+
- STE
|
|
14
|
+
- ASD-STE100
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Simplified Technical English
|
|
18
|
+
|
|
19
|
+
ASD-STE100 Simplified Technical English is a controlled-language standard from
|
|
20
|
+
aerospace and defense. It exists to make technical text easy to read the first
|
|
21
|
+
time, especially for people who read English as a second language. This skill
|
|
22
|
+
adapts its spirit for agent prose.
|
|
23
|
+
|
|
24
|
+
Apply it to your **prose**: chat replies, explanations, summaries, step lists,
|
|
25
|
+
recommendations. The goal is easy reading, not dumbed-down thinking. Open the
|
|
26
|
+
text up and keep the substance.
|
|
27
|
+
|
|
28
|
+
## Core rules
|
|
29
|
+
|
|
30
|
+
- **Prefer short sentences.** Aim for 20 words or fewer, particularly for instructions.
|
|
31
|
+
- **One idea per sentence, one topic per paragraph.** Split a sentence that carries two ideas.
|
|
32
|
+
- **Active voice.** Write "Run the tests", not "The tests should be run".
|
|
33
|
+
- **Plain, consistent words.** Prefer a common word over a fancy one. Use one word for one idea. Do not switch synonyms for the same thing mid-text.
|
|
34
|
+
- **Say the thing directly.** Lead with the answer. Give the number, name, or path. Cut filler like "in terms of", "a range of", "going forward".
|
|
35
|
+
- **Positive instructions.** Tell the reader what to do, not only what to avoid.
|
|
36
|
+
|
|
37
|
+
## The hard boundary: prose, not code
|
|
38
|
+
|
|
39
|
+
A controlled *English* vocabulary
|
|
40
|
+
must never bleed into the code the agent writes.
|
|
41
|
+
|
|
42
|
+
- **Do not** simplify or rename variables, functions, types, files, config keys, CLI flags, API fields, or error strings to obey "approved words". Code needs exact, domain-precise names.
|
|
43
|
+
- **Do not** apply it to commit messages, code comments, or reference/API documentation, where technical precision and established terminology win.
|
|
44
|
+
- **Do** keep using the project's real domain terms in prose. Naming a concept correctly beats naming it "simply".
|
|
45
|
+
|
|
46
|
+
If clarity and a required technical term ever conflict in prose, keep the term
|
|
47
|
+
and add a short plain-English gloss beside it.
|
|
48
|
+
|
|
49
|
+
## When to use it
|
|
50
|
+
|
|
51
|
+
- The user asked for plain or simple or clear text.
|
|
52
|
+
- Instructions where a misread is costly (ops, deploys, security steps).
|
|
53
|
+
- Long or dense explanations that need to be scannable.
|
|
54
|
+
|
|
55
|
+
## When not to use it
|
|
56
|
+
|
|
57
|
+
- Code, identifiers, commit messages, or API/reference docs (see the boundary above).
|
|
58
|
+
- Creative or personal-voice writing, where rhythm and personality matter more than the controlled register.
|
|
59
|
+
- Cases where a precise domain term must stay exact. Keep the term.
|
|
60
|
+
|
|
61
|
+
## Attribution
|
|
62
|
+
|
|
63
|
+
Standard: ASD-STE100 (ASD, the AeroSpace and Defence Industries Association of
|
|
64
|
+
Europe). This skill adapts its principles for agent prose; it is not the
|
|
65
|
+
official specification and does not reproduce its controlled dictionary.
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"timeout": 300,
|
|
69
69
|
"template": {
|
|
70
70
|
"id": "github-pr-reviewer",
|
|
71
|
-
"version": "1.
|
|
71
|
+
"version": "1.9.2",
|
|
72
72
|
"config": {
|
|
73
73
|
"repos": [
|
|
74
74
|
"OpenHands/agent-server-gui"
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"timeout": 300,
|
|
109
109
|
"template": {
|
|
110
110
|
"id": "github-pr-reviewer",
|
|
111
|
-
"version": "1.
|
|
111
|
+
"version": "1.9.2",
|
|
112
112
|
"config": {
|
|
113
113
|
"repos": [
|
|
114
114
|
"OpenHands/agent-server-gui"
|
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
"timeout": 300,
|
|
214
214
|
"template": {
|
|
215
215
|
"id": "github-pr-reviewer",
|
|
216
|
-
"version": "1.
|
|
216
|
+
"version": "1.9.2",
|
|
217
217
|
"config": {
|
|
218
218
|
"repos": [
|
|
219
219
|
"OpenHands/agent-server-gui",
|
|
@@ -254,7 +254,7 @@
|
|
|
254
254
|
"timeout": 300,
|
|
255
255
|
"template": {
|
|
256
256
|
"id": "github-pr-reviewer",
|
|
257
|
-
"version": "1.
|
|
257
|
+
"version": "1.9.2",
|
|
258
258
|
"config": {
|
|
259
259
|
"repos": [
|
|
260
260
|
"OpenHands/agent-server-gui",
|
|
@@ -296,7 +296,7 @@
|
|
|
296
296
|
"preset_metadata": {
|
|
297
297
|
"template": {
|
|
298
298
|
"id": "github-pr-reviewer",
|
|
299
|
-
"version": "1.
|
|
299
|
+
"version": "1.9.2",
|
|
300
300
|
"config": {
|
|
301
301
|
"repos": [
|
|
302
302
|
"OpenHands/agent-server-gui",
|
|
@@ -351,7 +351,7 @@
|
|
|
351
351
|
"timeout": 300,
|
|
352
352
|
"template": {
|
|
353
353
|
"id": "github-pr-reviewer",
|
|
354
|
-
"version": "1.
|
|
354
|
+
"version": "1.9.2",
|
|
355
355
|
"config": {
|
|
356
356
|
"repos": [
|
|
357
357
|
"OpenHands/agent-server-gui"
|
|
@@ -444,7 +444,7 @@
|
|
|
444
444
|
"timeout": 300,
|
|
445
445
|
"template": {
|
|
446
446
|
"id": "github-pr-reviewer",
|
|
447
|
-
"version": "1.
|
|
447
|
+
"version": "1.9.2",
|
|
448
448
|
"config": {
|
|
449
449
|
"repos": [
|
|
450
450
|
"OpenHands/agent-server-gui"
|
|
@@ -540,7 +540,7 @@
|
|
|
540
540
|
"timeout": 300,
|
|
541
541
|
"template": {
|
|
542
542
|
"id": "github-pr-reviewer",
|
|
543
|
-
"version": "1.
|
|
543
|
+
"version": "1.9.2",
|
|
544
544
|
"config": {
|
|
545
545
|
"repos": [
|
|
546
546
|
"OpenHands/agent-server-gui"
|
|
@@ -616,7 +616,7 @@
|
|
|
616
616
|
"timeout": 300,
|
|
617
617
|
"template": {
|
|
618
618
|
"id": "github-pr-reviewer",
|
|
619
|
-
"version": "1.
|
|
619
|
+
"version": "1.9.2",
|
|
620
620
|
"config": {
|
|
621
621
|
"repos": [
|
|
622
622
|
"OpenHands/automation"
|