> ## Documentation Index
> Fetch the complete documentation index at: https://noorle.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SendMessage

> Send a message to a Noorle agent over A2A and wait for the complete result — a Task or a Message, depending on how the run ends

Send a message and wait for the run to reach a terminal state or an interrupt.

```
POST https://agent-{handle}.noorle.com/
```

The method name is `SendMessage` in the JSON-RPC envelope. There is no
`/message/send` path and no `message/send` method name.

## Request

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "SendMessage",
  "params": {
    "message": {
      "messageId": "0198f0c2-1a3d-7c41-9b2e-8f5a6d3c1e07",
      "role": "ROLE_USER",
      "parts": [{ "text": "What is the status of order 4471?" }]
    }
  }
}
```

```bash theme={null}
curl -X POST https://agent-my-agent.noorle.com/ \
  -H "Authorization: Bearer eyJhbGc..." \
  -H "Content-Type: application/json" \
  -d @request.json
```

### `params`

| Field           | Type   | Required | Description         |
| --------------- | ------ | -------- | ------------------- |
| `message`       | object | Yes      | The message to send |
| `configuration` | object | No       | Send configuration  |
| `metadata`      | object | No       | Extension metadata  |

### `message`

| Field              | Type      | Required | Description                                                                              |
| ------------------ | --------- | -------- | ---------------------------------------------------------------------------------------- |
| `messageId`        | string    | Yes      | Sender-generated unique id                                                               |
| `role`             | string    | Yes      | `ROLE_USER` or `ROLE_AGENT`                                                              |
| `parts`            | array     | Yes      | Content parts                                                                            |
| `contextId`        | string    | No       | **The Noorle thread id.** Echo it to continue a conversation; omit it for a fresh thread |
| `taskId`           | string    | No       | Reuse an existing task. Omit and the server mints one                                    |
| `metadata`         | object    | No       | Extension metadata                                                                       |
| `extensions`       | string\[] | No       | Extension URIs relevant to this message                                                  |
| `referenceTaskIds` | string\[] | No       | Related task ids                                                                         |

### Parts

A part is a field-presence union — exactly one content key, plus optional
`filename`, `mediaType`, and `metadata`.

| Key    | Type   | Content              |
| ------ | ------ | -------------------- |
| `text` | string | Plain text           |
| `raw`  | string | Base64-encoded bytes |
| `url`  | string | A URL to fetch       |
| `data` | object | Structured JSON      |

<Note>
  **There is no `file` part on the wire.** A file attachment lowers to `raw`
  (inline bytes) or `url`, with `filename` and `mediaType` set alongside it.
</Note>

Inbound file parts are fetched through the platform's outbound egress policy.
Attachments are capped at **20 MiB** per file and images at **4096 × 4096**.

## Response

The result is a field-presence union of exactly one key.

<CodeGroup>
  ```json Task mode theme={null}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "task": {
        "id": "0198f0c2-2b4e-7d52-ac3f-9061e4d2f118",
        "contextId": "0198f0c2-0b11-7a2f-8c9d-4e1b2a7f6c35",
        "status": {
          "state": "TASK_STATE_COMPLETED",
          "timestamp": "2026-08-04T10:31:15Z"
        },
        "artifacts": [ /* ... */ ]
      }
    }
  }
  ```

  ```json Message mode theme={null}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
      "message": {
        "messageId": "0198f0c2-3c5f-7e63-bd40-a172f5e3d229",
        "contextId": "0198f0c2-0b11-7a2f-8c9d-4e1b2a7f6c35",
        "role": "ROLE_AGENT",
        "parts": [{ "text": "Order 4471 shipped on 2 August." }]
      }
    }
  }
  ```
</CodeGroup>

**Which one you get depends on what the run did.** A run that called a tool
commits to Task mode and returns a `task`. A run that ends on a bare reply
returns a `message` with no task transition.

Write your client to handle both.

## Interrupts

When the run reaches `TASK_STATE_INPUT_REQUIRED` or `TASK_STATE_AUTH_REQUIRED`,
`SendMessage` stops draining and returns the persisted task snapshot rather
than hanging until the stream closes.

For an approval gate, resume with a follow-up `SendMessage` carrying a
`noorle.gate_decision` data part and **both** `taskId` and `contextId`. Only
user callers may resolve a gate over A2A. See
[A2A overview](/docs/reference/a2a/overview).

## Errors

Returned with **HTTP 200** and the error in the JSON-RPC envelope.

| Code   | Cause                                                             |
| ------ | ----------------------------------------------------------------- |
| -32700 | Invalid JSON                                                      |
| -32600 | Invalid request envelope                                          |
| -32601 | Unknown method — check you sent `SendMessage`, not `message/send` |
| -32602 | Invalid params                                                    |
| -32603 | Internal error                                                    |

Reusing a `taskId` that already exists fails rather than overwriting the
existing task.

## Related

* [SendStreamingMessage](/docs/reference/a2a/message-stream)
* [Tasks](/docs/reference/a2a/tasks)
* [A2A overview](/docs/reference/a2a/overview)
