# Run the editing agent

`POST https://api.vidmoat.com/v1/ai/agent`

- Scope: `ai.agent`
- Cost: 5 credits

Describe an edit in `message` and let the agent emit and apply the commands. One turn per call, charged once: you drive the loop. Works on every plan.

> **Note.** Add `dryRun: true` to get the plan back without applying it. The credits are still spent, because the model call is what they pay for, and so is a turn that plans nothing.

### Body

- `projectId` (string, required): The project to edit.
- `message` (string, required): The edit, in plain words. Up to 2,000 characters.
- `dryRun` (boolean, optional, default `false`): Return the planned commands without applying them.

## Response

Returns `200`.

### Response fields

- `projectId` (string): The project.
- `applied` (boolean): Whether the commands were saved.
- `planner` (string): Which model planned the turn.
- `message` (string): The agent's reply.
- `commands` (array): The commands it planned.
- `results` (array): One entry per command: `{ op, ok, error?, data? }`. A failed command is reported here, not as an HTTP error.
- `verification` (object): What happened: `accepted` (count), `failed` (`[{ op, error }]`), `blocked`, `layout` warnings, and `outcome` (`executed`, `needs-repair` or `blocked`).
- `lint` (array): Layout warnings: `{ severity: "warn" | "note", time, message }`.
- `suggestedPreviewTimes` (array of numbers): Timestamps worth looking at with the preview endpoint before you render.
- `project` (object): The project after the turn, summary view.
- `credits` (object): `{ charged, remaining }`: what this call cost and the balance after it.

> **Tip: With a test key.** Test keys still need a real project, then return an empty plan (`planner: "fixture"`) without calling a model or spending.

## Errors

Besides the errors any request can get ([authentication](https://developer.vidmoat.com/developer/docs/authentication#when-a-request-is-refused), [rate limits](https://developer.vidmoat.com/developer/docs/rate-limits)):

| Status | Code | When |
| --- | --- | --- |
| 400 | [`invalid_request`](https://developer.vidmoat.com/developer/docs/errors#invalid_request) | `message` or `projectId` is missing. |
| 404 | [`not_found`](https://developer.vidmoat.com/developer/docs/errors#not_found) | No such project, or it is not yours. The two are indistinguishable on purpose. |
| 402 | [`insufficient_credits`](https://developer.vidmoat.com/developer/docs/errors#insufficient_credits) | The balance cannot cover the call. Nothing ran. `remaining` is the balance. |
| 422 | [`prompt_rejected`](https://developer.vidmoat.com/developer/docs/errors#prompt_rejected) | The prompt failed the safety check. Nothing was charged. `field` names the field. |
| 502 | [`provider_error`](https://developer.vidmoat.com/developer/docs/errors#provider_error) | No planner answered. The charge is refunded. |

## Request examples

```bash curl
curl -X POST https://api.vidmoat.com/v1/ai/agent \
  -H "Authorization: Bearer $VIDMOAT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"'$ID'","message":"cut the silences and add captions"}'
```

```js Node
const ID = 'YOUR_PROJECT_ID';

const res = await fetch('https://api.vidmoat.com/v1/ai/agent', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.VIDMOAT_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    projectId: ID,
    message: 'cut the silences and add captions',
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message ?? `HTTP ${res.status}`);
console.log(data);
```

```python Python
import os
import requests

ID = "YOUR_PROJECT_ID"

res = requests.post(
    "https://api.vidmoat.com/v1/ai/agent",
    headers={"Authorization": f"Bearer {os.environ['VIDMOAT_KEY']}"},
    json={
      "projectId": ID,
      "message": "cut the silences and add captions",
    },
    timeout=60,
)
res.raise_for_status()
print(res.json())
```

## Example response

```json
{
  "projectId": "cm1abc",
  "applied": true,
  "planner": "deepseek",
  "message": "Added captions.",
  "commands": [{ "op": "addTextClip", "text": "Hi", "start": 0, "duration": 2 }],
  "results": [{ "op": "addTextClip", "ok": true }],
  "lint": [],
  "suggestedPreviewTimes": [1],
  "project": { "id": "cm1abc", "name": "Demo", "clipCount": 1, "durationSec": 2 },
  "credits": { "charged": 5, "remaining": 4495 }
}
```

---

Source: https://developer.vidmoat.com/developer/docs/api/generation/run-agent
Previous: [Get a generation job](https://developer.vidmoat.com/developer/docs/api/generation/get-generation-job.md)
Next: [List plugins](https://developer.vidmoat.com/developer/docs/api/plugins/list-plugins.md)
All documentation: https://developer.vidmoat.com/llms-full.txt
