# Update a draft

Replaces an open draft’s title or change set.

|  |  |
| --- | --- |
| REST | `PATCH /api/v1/agents/{agent_id}/drafts/{draft_id}` |
| MCP tool | `update_draft` |
| Classification | **Write** |
| Scope | `agents:write` |
| Minimum role on the agent | editor |
| Confirmation | Not needed |
| Retry safety | Safe to retry with the same input |
| Success status | 200 |

## What it does

Replaces an open draft’s title or change set. New changes are written against the agent as it is now.

## Side effects

Changes the open draft only.

## Inputs

| Name | Type | Required | In | Description |
| --- | --- | --- | --- | --- |
| `agent_id` | string | yes | path | The agent id (agt_...), from list_agents. |
| `draft_id` | string | yes | path | The draft id. |
| `title` | string | no | body |  |
| `changes` | object | no | body | Changes by section. identity and personality take the fields to change. links, offers, knowledge and places take add (new items), update (items with id plus the fields to change) and remove (ids). Get ids and current values from get_agent_configuration; get the full schema from get_configuration_schema. |

## Example

REST:

```bash
curl -X PATCH "https://covo.lanaai.io/api/v1/agents/agt_4edc89bb2964/drafts/80da083a-0818-47b5-afc4-ef5b39c59137" \
  -H "Authorization: Bearer $COVO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Spring greeting (final)"}'
```

MCP (POST /mcp):

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "update_draft",
    "arguments": {
      "agent_id": "agt_4edc89bb2964",
      "draft_id": "80da083a-0818-47b5-afc4-ef5b39c59137",
      "title": "Spring greeting (final)"
    }
  }
}
```

## Response

Returns an object with `id`, `title`, `status`, `base_revision`, `current_revision`, `stale`, `change_set`, `changes`, `problems`, `removes`, `validation`, `client`, `created_at` and `updated_at`. This is a real response, shortened to two items per list.

200 response:

```json
{
  "id": "80da083a-0818-47b5-afc4-ef5b39c59137",
  "title": "Spring greeting (final)",
  "status": "open",
  "base_revision": 6,
  "current_revision": 6,
  "stale": false,
  "change_set": {
    "personality": {
      "greeting": "Hi, I am Avery’s Concierge. Ask me about spring projects."
    }
  },
  "changes": [
    {
      "path": "personality.greeting",
      "operation": "replace",
      "before": "I'm Avery Quinn's Concierge. I can help you learn about Avery Quinn's work, what's on offer, or anything else you're curious about.",
      "after": "Hi, I am Avery’s Concierge. Ask me about spring projects."
    }
  ],
  "problems": [],
  "removes": 0,
  "validation": {
    "valid": true,
    "state": "ready",
    "errors": [],
    "warnings": [
      {
        "step": "knowledge",
        "field": null,
        "severity": "recommended",
        "message": "Add a few common questions. Short, specific answers work best."
      },
      {
        "step": "publish",
        "field": null,
        "severity": "recommended",
        "message": "Ask the preview a question before you publish."
      }
    ]
  },
  "client": {
    "name": "docs-examples",
    "interface": "rest"
  },
  "created_at": "2026-10-07T20:14:41.872Z",
  "updated_at": "2026-10-07T20:14:41.885Z"
}
```

Over MCP the same object comes back as the tool result, in `structuredContent` and as JSON text.

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| 401 | `unauthorized` | No token, or it is unknown, revoked or expired. OAuth apps refresh or reconnect. |
| 403 | `account_suspended` | The account that owns the token is paused. |
| 403 | `insufficient_scope` | The token lacks `agents:write`. |
| 404 | `agent_not_found` | Unknown agent, or not reachable with this token. |
| 400 | `bad_request` | An input is invalid; `field` names it. |
| 429 | `rate_limited` | Wait `Retry-After` seconds. |
