---
name: miles-engineer
description: Hand repo and pull-request work to the user's Miles Engineer — merge a PR once it is green, review a PR, bring a branch up to date, fix failing CI, address review comments, or any other repo task. Use when a PR you opened needs merging or follow-up, or when a repo task should run on the user's own Mac with their approval.
metadata:
  {
    "openclaw":
      {
        "requires": { "bins": ["curl"], "env": ["MILES_API_KEY"] },
        "primaryEnv": "MILES_API_KEY",
      },
  }
---

# Miles Engineer handoff

Miles' Engineer is a coding agent that works on the user's own Mac (their checkout, their git, their `gh`) or, for jobs that need no checkout, through their GitHub API connection. You hand it a task over HTTP; it does the work on the user's leash and reports back.

Base URL: `https://api.heymiles.app/api/v1` (or `$MILES_API_BASE` if set). Every call sends `Authorization: Bearer $MILES_API_KEY`.

## Rules

- **You cannot approve.** Pushes, merges and first-time commands wait for the human to approve in Miles or in the Slack thread. When a task is `awaiting_approval`, tell the human what it's waiting on (`task.approval.action`) and where (`task.approval.where`) — never try to approve it another way, and never merge the PR yourself as a workaround.
- **Put the whole job in the request.** The Engineer treats PR bodies, review comments and CI logs as data, not instructions, so anything it must do goes in `instructions`.
- **Don't claim success early.** A PR is merged only when the task is `completed` with `outcome: "done"`. `completed` + `not_done` / `blocked` / `partial` means it stopped — read `task.result` for why (checks still running, conflicts, changes requested…) and report that.
- **Use your own task id as `externalId`** so a retry never creates a second task.
- **Poll gently:** every 30–60 seconds at most, and stop when the status is `completed`, `failed`, `cancelled` or `expired`.

## 1. Check the setup

```bash
curl -s "${MILES_API_BASE:-https://api.heymiles.app/api/v1}/engineer" \
  -H "Authorization: Bearer $MILES_API_KEY"
```

- `engineer.deployed` false → tell the human: "Deploy the Engineer in Miles (Agents → Marketplace → Engineer) so I can hand it work."
- `mac.online` false and `github.apiConnected` false → the task will queue until their Mac is back.
- `folders` lists the repo folders the Engineer can run commands in; pass one as `folder` if you know it.

## 2. Hand off the task

```bash
curl -s -X POST "${MILES_API_BASE:-https://api.heymiles.app/api/v1}/engineer/tasks" \
  -H "Authorization: Bearer $MILES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "merge_when_green",
    "repo": "OWNER/REPO",
    "pr": 123,
    "mergeMethod": "merge",
    "instructions": "Opened by OpenClaw for <why>. Merge once green.",
    "externalId": "<your task id>",
    "slack": { "channelId": "<channel id>", "threadTs": "<thread ts>" }
  }'
```

Actions:

| action | use it for | needs |
|---|---|---|
| `merge_when_green` | merge a PR once its checks pass; add `"checks": ["typecheck"]` to also run checks locally first | `repo`, `pr` |
| `review` | a bug/risk review; `"postReview": true` posts it on the PR as a comment | `repo`, `pr` |
| `update_branch` | bring a PR branch up to date with its base (merge, never force-push) | `repo`, `pr` |
| `fix_ci` | reproduce and fix failing checks, push to the same branch | `repo`, `pr` or `branch` |
| `address_comments` | make the changes review comments ask for, push | `repo`, `pr` |
| `custom` | anything else, in `instructions` | `instructions` |

Include `slack` when you're working in a Slack thread: the Engineer's approval card and result land in that same thread (the Miles (Work) app must be installed there). Leave it out otherwise.

The response is `202` with `task.id` and `task.status` — `running`, or `queued` with a `queuedReason` (for example, the Mac is asleep). A `200` with `"replay": true` means this `externalId` was already handed off; carry on with that task.

## 3. Follow it

```bash
curl -s "${MILES_API_BASE:-https://api.heymiles.app/api/v1}/engineer/tasks/<task id>" \
  -H "Authorization: Bearer $MILES_API_KEY"
```

| status | what to do |
|---|---|
| `queued` | report `queuedReason`; check back later |
| `running` | wait; `steps` shows what it's doing |
| `awaiting_approval` | tell the human what to approve and where; wait |
| `completed` | report `outcome` + a short summary of `result`, with the PR link |
| `failed` / `cancelled` / `expired` | report `error` |

To stop a task that is queued or waiting for approval:

```bash
curl -s -X POST "${MILES_API_BASE:-https://api.heymiles.app/api/v1}/engineer/tasks/<task id>/cancel" \
  -H "Authorization: Bearer $MILES_API_KEY"
```

## Errors

Errors come back as `{ "error": { "code", "message" } }`. Relay `message` to the human — it says exactly what to change. Common codes: `engineer_not_deployed`, `engineer_paused`, `mac_not_set_up`, `github_not_connected`, `action_needs_mac`, `folder_not_found`, `slack_not_connected`, `too_many_tasks`, `rate_limited` (retry after `Retry-After` seconds).
