Skip to main content

openhands-automation

This skill should be used when the user asks to "create an automation", "schedule a task", "set up a cron job", "webhook integration", "event-triggered automation", or mentions automations, scheduled tasks, cron scheduling, or webhook events in OpenHands Cloud.

معلومات المصدر

المستودع
OpenHands/extensions
آخر نشاط في المصدر
٥ أكتوبر ٢٠٢٦ في ١٥:٠٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٥٧
التفرعات
١٠٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
10 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
openhands-automation
description
This skill should be used when the user asks to "create an automation", "schedule a task", "set up a cron job", "webhook integration", "event-triggered automation", or mentions automations, scheduled tasks, cron scheduling, or webhook events in OpenHands Cloud.
triggers
["automation","automations","scheduled task","cron job","cron schedule","webhook","webhooks","event trigger","github event","pull request automation","issue automation","/automation:create"]
# OpenHands Automations Create and manage automations that run inside an OpenHands agent server — triggered by cron schedules or webhook events (GitHub, custom services). Windows PowerShell equivalents for the automation API `curl` examples and shell-variable conventions are in `references/windows.md`. ## Automation Creation Process The agent must follow these steps when creating an automation: * Quickly check that you can access the correct automations backend using the auth mechanism below * Quickly check that you can access any necessary integrations (e.g. GitHub, Slack); if access fails, inform the user and stop * Ask the user for any necessary information, e.g. if you need the name of a Slack channel or GitHub repo to proceed * Write the code or prompt that will be sent to the automations backend _inside the current workspace_ * Show the code to the user with the `canvas_ui` tool if available, otherwise present it in a fenced code block in your reply * Message the user with a concise summary of how the automation will behave, and ask if they are ready to deploy it ## Architecture Two components work together to run automations: **Automation Service** (API at `OPENHANDS_HOST/api/automation/v1`) Manages the *when*: holds automation definitions, schedules cron-triggered runs, dispatches webhook-triggered runs, and receives completion callbacks to mark runs as done. This is the API you call to create, update, and manage automations. **Agent Server** (accessible as `AGENT_SERVER_URL` inside script runs) Manages the *what*: the runtime environment where automation scripts execute and where conversations (AI agent interactions with tools, bash, file editing, etc.) run. When a run is triggered, the automation service uploads the automation's tarball to the agent server, which unpacks and runs the entrypoint script. The script connects back to the agent server using `AGENT_SERVER_URL` and a session API key to start, monitor, and stop conversations. The agent server typically runs inside a **sandbox** (a Docker or Kubernetes container). Some deployments use sandboxless mode, where the agent server runs directly on a host. **Key environment variables:** | Variable | Availability | Description | |---|---|---| | `RUNTIME_URL` | Ambient in cloud environments | Public-facing URL of the **agent server** sandbox. Use this to determine whether external webhook delivery is possible — if unset or local, webhooks cannot be received. The automation service may run at a separate URL (see Determining the API Host). | | `AGENT_SERVER_URL` | Injected into scripts at run time, local Agent Canvas only | Internal URL of the agent server. Available inside script execution context; **not** an ambient environment variable outside of a running script, and not set on OpenHands Cloud or Enterprise. | | `OPENHANDS_HOST` | Shell convention only — set manually | Base URL for the automation service API. **Not a real environment variable.** Set it from an explicit host, a detected local Agent Canvas server, or the cloud default. Used in all `curl` examples throughout this skill. | > **⚠️ CRITICAL — Agent behavior rules:** > > 0. **Does this task need an LLM at all? Check first.** Before picking a preset, ask whether the task actually requires reasoning, judgment, summarization, or open-ended tool use. If it is fully deterministic — fixed data transforms, scheduled HTTP calls, healthcheck pings, file rotation, picking from a known list, posting a templated message — an LLM-driven preset is overkill. Every run will consume LLM tokens, which adds up fast at high frequencies (every 5 min ≈ 288 runs/day). Surface the trade-off to the user and offer the custom-script path (see `references/custom-automation.md`) as the cheaper, more reliable option. Be especially careful for cron schedules tighter than hourly. > > **Instant-recognition patterns — these are always deterministic, never use an LLM preset:** > - "post a quote / message / fact every N minutes" (rotating from a list) > - "send a scheduled reminder / standup / digest" > - "ping a health-check URL on a schedule" > - "post to Slack / webhook every N minutes" > - Any task where the full output could be written as a static template right now > > 1. **For LLM-appropriate work, default to preset endpoints.** They handle all SDK boilerplate, tarball packaging, and upload automatically: > - **Prompt preset** (`POST /v1/preset/prompt`) — for tasks expressed as a natural language prompt that benefit from agent reasoning > - **Plugin preset** (`POST /v1/preset/plugin`) — when plugins with skills, MCP configs, or commands are needed > 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: > - **Prompt preset** - natural language prompt execution (LLM-driven) > - **Plugin preset** - load plugins with extended capabilities (skills, MCP, hooks, commands) > - **Custom script** - full control over code, with or without an LLM; see `references/custom-automation.md` > > 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. > 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. > 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: > - **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. > - 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." ### No-LLM Script Helpers When building a deterministic custom script, these two stdlib-only functions are required. Copy them verbatim - they use variables injected by the automation service: `SESSION_API_KEY`, plus `AGENT_SERVER_URL` on a local Agent Canvas or `OPENHANDS_CLOUD_API_URL` and `SANDBOX_ID` on OpenHands Cloud and Enterprise. ```python import json, os, urllib.request def get_secret(name): """Fetch a named secret: from the agent server when AGENT_SERVER_URL is set, else from the OpenHands API.""" url = os.environ.get("AGENT_SERVER_URL", "").rstrip("/") key = os.environ.get("SESSION_API_KEY") or os.environ.get("OH_SESSION_API_KEYS_0", "") if url: # local Agent Canvas url = f"{url}/api/settings/secrets/{name}" else: # OpenHands Cloud / Enterprise api = os.environ["OPENHANDS_CLOUD_API_URL"].rstrip("/") url = f"{api}/api/v1/sandboxes/{os.environ['SANDBOX_ID']}/settings/secrets/{name}" with urllib.request.urlopen(urllib.request.Request( url, headers={"X-Session-API-Key": key} )) as r: return r.read().decode().strip() def fire_callback(status="COMPLETED", error=None): """Signal run completion. MUST be called on every exit path — success AND error.""" url = os.environ.get("AUTOMATION_CALLBACK_URL", "") if not url: return body = {"status": status, "run_id": os.environ.get("AUTOMATION_RUN_ID", "")} if error: body["error"] = error try: urllib.request.urlopen(urllib.request.Request(url, data=json.dumps(body).encode(), headers={ "Content-Type": "application/json", "Authorization": f"Bearer {os.environ.get('AUTOMATION_CALLBACK_API_KEY', '')}", })) except Exception as e: print(f"Callback error: {e}") ``` Entrypoint must be `python3 main.py` (no `setup.sh` needed). Wrap your main logic in `try/except` and call `fire_callback("FAILED", str(e))` in the except block. **State persistence between runs** — polling automations that track a "last processed" timestamp or active conversation IDs must use the built-in KV store rather than local files. Local files are lost when a run ends on a cloud pod. The KV store is available when `AUTOMATION_KV_TOKEN` is injected into the run environment. See `references/custom-automation.md#state-persistence-kv-store` for ready-to-copy `kv_get` / `kv_set` / `load_state` / `save_state` helpers. --- ## Authentication All requests require authentication: - Cloud (default `https://app.all-hands.dev`): Bearer token: `-H "Authorization: Bearer ${OPENHANDS_API_KEY}"` - Local Agent Canvas (`http://localhost:8001`): session API key through `X-Session-API-Key`: `-H "X-Session-API-Key: ${OPENHANDS_AUTOMATION_API_KEY:-${SESSION_API_KEY}}"` The curl examples below show cloud Bearer authentication. For local Agent Canvas, replace that header with the `X-Session-API-Key` header above. ## API Endpoints ### Determining the API Host **Before making API calls, determine the correct host:** The automation service may run at a different URL from the agent server. In the examples throughout this skill, `${OPENHANDS_HOST}` is a shell-variable convention for the automation service base URL — it is **not** a real environment variable. Set it from context before running any curl command: - Look for a `<HOST>` value in the system prompt or runtime-services block. If present, use that URL. - If running inside a local Agent Canvas stack and no explicit host is provided, use `http://localhost:8001` for the local automation/agent-server API. - Otherwise default to `https://app.all-hands.dev`. For a local Agent Canvas server, validate the endpoint before making a mutating request and authenticate with the session key through `X-Session-API-Key` when that API requires it. Do not use the cloud default merely because no `<HOST>` value is present. ```bash # Choose the host that matches the detected environment: OPENHANDS_HOST="http://localhost:8001" # local Agent Canvas # OPENHANDS_HOST="https://app.all-hands.dev" # OpenHands Cloud ``` ### Automation Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/api/automation/v1/preset/prompt` | POST | **Create automation from a prompt (recommended)** | | `/api/automation/v1/preset/plugin` | POST | **Create automation with plugins** | | `/api/automation/v1` | GET | List automations | | `/api/automation/v1/{id}` | GET | Get automation details | | `/api/automation/v1/{id}` | PATCH | Update automation | | `/api/automation/v1/{id}` | DELETE | Delete automation | | `/api/automation/v1/{id}/dispatch` | POST | Trigger a run manually | | `/api/automation/v1/{id}/runs` | GET | List automation runs | ### Custom Webhook Endpoints | Endpoint | Method | Description | |----------|--------|-------------| | `/api/automation/v1/webhooks` | POST | Register a custom webhook source | | `/api/automation/v1/webhooks` | GET | List all custom webhooks | | `/api/automation/v1/webhooks/{id}` | GET | Get webhook details | | `/api/automation/v1/webhooks/{id}` | PATCH | Update webhook settings | | `/api/automation/v1/webhooks/{id}` | DELETE | Delete a webhook | | `/api/automation/v1/webhooks/{id}/rotate-secret` | POST | Rotate signing secret | --- ## Trigger Types Automations support two trigger types: | Trigger Type | Use Case | |--------------|----------| | **Cron** | Run on a schedule (daily, weekly, hourly, etc.) | | **Event** | Run when a webhook event occurs (GitHub PR opened, issue commented, etc.) — **requires a publicly reachable deployment** | --- ## Creating Automations Two preset endpoints simplify automation creation by handling SDK boilerplate, tarball packaging, and upload automatically: 1. **Prompt Preset** — Execute a natural language prompt (simple tasks) 2. **Plugin Preset** — Load plugins with skills, MCP configs, and commands (extended capabilities) --- ### Prompt Preset Use the **preset/prompt endpoint** for simple automations. Provide a natural language prompt describing the task. #### How It Works 1. Send a prompt describing the task (e.g., "Generate a weekly status report") 2. The automation service generates a Python script that: fetches LLM config and secrets from the agent server, starts an AI agent conversation with your prompt, and sends a completion callback when done 3. The script is packaged as a tarball and the automation is registered; on each trigger, the automation service uploads the tarball to the agent server, which unpacks and runs the script inside its environment #### Request ```bash curl -X POST "${OPENHANDS_HOST}/api/automation/v1/preset/prompt" \ -H "Authorization: Bearer ${OPENHANDS_API_KEY}" \ -H "Content-Type: application/json" \ -d '{ "name": "My Automation Name", "prompt": "What the automation should do", "trigger": { "type": "cron", "schedule": "0 9 * * *", "timezone": "UTC" } }' ``` #### Request Fields | Field | Required | Description | |-------|----------|-------------| | `name` | Yes | Name of the automation (1-500 characters) | | `prompt` | Yes | Natural language instructions (1-50,000 characters) | | `trigger` | Yes | Trigger configuration — either `cron` or `event` (see below) | | `timeout` | No | Max execution time in seconds (default: system maximum) | | `repos` | No | Repositories to clone (see [Repository Cloning](#repository-cloning)) | **Cron Trigger Fields:** | Field | Required | Description | |-------|----------|-------------| | `trigger.type` | Yes | `"cron"` | | `trigger.schedule` | Yes | Cron expression (5 fields: min hour day month weekday) | | `trigger.timezone` | No | IANA timezone (default: `"UTC"`) | **Event Trigger Fields:** | Field | Required | Description | |-------|----------|-------------| | `trigger.type` | Yes | `"event"` | | `trigger.source` | Yes | Event source: `"github"` or custom webhook source name | | `trigger.on` | Yes | Event key pattern(s) to match (see Event Keys below) | | `trigger.filter` | No | JMESPath expression for payload filtering (see Filter Expressions below) | #### Prompt Tips 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: - `"Generate a weekly status report summarizing the team's GitHub activity and post it to Slack"` - `"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"`
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub