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

# message/send

> Send synchronous messages to A2A agents and receive immediate responses

## Overview

The `message/send` method is the primary way to communicate with A2A agents synchronously. Send a message and receive a complete response in a single HTTP request.

<Note>
  **Synchronous Communication**: This method blocks until the agent provides a complete response. For streaming responses, use [`message/stream`](/api-reference/endpoint/message-stream) instead.
</Note>

## Request

### Headers

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`
</ParamField>

<ParamField header="x-api-key" type="string" required>
  Your API key for authentication
</ParamField>

### Path Parameters

<ParamField path="agent_id" type="string" required>
  Unique identifier of the target agent
</ParamField>

### Body Parameters

<ParamField body="jsonrpc" type="string" required>
  JSON-RPC version, must be `"2.0"`
</ParamField>

<ParamField body="id" type="string" required>
  Unique identifier for this request (for response correlation)
</ParamField>

<ParamField body="method" type="string" required>
  Must be `"message/send"`
</ParamField>

<ParamField body="params" type="object" required>
  Message parameters object

  <Expandable title="params properties">
    <ParamField body="params.message" type="object" required>
      The message to send to the agent

      <Expandable title="message properties">
        <ParamField body="params.message.role" type="string" required>
          Message role, must be `"user"`
        </ParamField>

        <ParamField body="params.message.messageId" type="string" required>
          UUID v4 identifier for this message
        </ParamField>

        <ParamField body="params.message.parts" type="array" required>
          Array of message parts (text, files, etc.)

          <Expandable title="parts array items">
            <ParamField body="params.message.parts[].type" type="string" required>
              Part type: `"text"` or `"file"`
            </ParamField>

            <ParamField body="params.message.parts[].text" type="string">
              Text content (required when type is "text")
            </ParamField>

            <ParamField body="params.message.parts[].file" type="object">
              File object (required when type is "file")

              <Expandable title="file properties">
                <ParamField body="params.message.parts[].file.name" type="string" required>
                  Original filename
                </ParamField>

                <ParamField body="params.message.parts[].file.mimeType" type="string" required>
                  MIME type of the file
                </ParamField>

                <ParamField body="params.message.parts[].file.bytes" type="string" required>
                  Base64 encoded file content (without data URL prefix)
                </ParamField>
              </Expandable>
            </ParamField>
          </Expandable>
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="params.contextId" type="string">
      Context ID for multi-turn conversations (from previous response)
    </ParamField>

    <ParamField body="params.sessionId" type="string">
      Optional session identifier for grouping related messages
    </ParamField>

    <ParamField body="params.id" type="string">
      Optional task ID for this operation
    </ParamField>
  </Expandable>
</ParamField>

## Response

### Success Response

<ResponseField name="jsonrpc" type="string">
  JSON-RPC version, always `"2.0"`
</ResponseField>

<ResponseField name="result" type="object">
  Result object containing the agent's response

  <Expandable title="result properties">
    <ResponseField name="result.id" type="string">
      Task ID for this operation
    </ResponseField>

    <ResponseField name="result.status" type="object">
      Status information

      <Expandable title="status properties">
        <ResponseField name="result.status.state" type="string">
          Task state: `"completed"`, `"working"`, `"failed"`, or `"canceled"`
        </ResponseField>

        <ResponseField name="result.status.message" type="object">
          Agent's response message

          <Expandable title="message properties">
            <ResponseField name="result.status.message.role" type="string">
              Message role, always `"agent"`
            </ResponseField>

            <ResponseField name="result.status.message.parts" type="array">
              Array of response parts

              <Expandable title="parts array items">
                <ResponseField name="result.status.message.parts[].type" type="string">
                  Part type, typically `"text"`
                </ResponseField>

                <ResponseField name="result.status.message.parts[].text" type="string">
                  Response text content
                </ResponseField>
              </Expandable>
            </ResponseField>
          </Expandable>
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="result.contextId" type="string">
      Context ID for multi-turn conversations (save for subsequent messages)
    </ResponseField>

    <ResponseField name="result.final" type="boolean">
      Whether this is the final response (always `true` for message/send)
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="id" type="string">
  Request ID (matches the request ID)
</ResponseField>

### Error Response

<ResponseField name="jsonrpc" type="string">
  JSON-RPC version, always `"2.0"`
</ResponseField>

<ResponseField name="error" type="object">
  Error information

  <Expandable title="error properties">
    <ResponseField name="error.code" type="number">
      JSON-RPC error code
    </ResponseField>

    <ResponseField name="error.message" type="string">
      Human-readable error message
    </ResponseField>

    <ResponseField name="error.data" type="object">
      Additional error details
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="id" type="string">
  Request ID (matches the request ID)
</ResponseField>

## Examples

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "http://localhost:8000/api/v1/a2a/my-agent" \
    -H "Content-Type: application/json" \
    -H "x-api-key: your-api-key" \
    -d '{
      "jsonrpc": "2.0",
      "id": "req-001",
      "method": "message/send",
      "params": {
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "What is the A2A protocol?"
            }
          ],
          "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6"
        }
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('http://localhost:8000/api/v1/a2a/my-agent', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': 'your-api-key'
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: "req-001",
      method: "message/send",
      params: {
        message: {
          role: "user",
          parts: [
            {
              type: "text",
              text: "What is the A2A protocol?"
            }
          ],
          messageId: crypto.randomUUID()
        }
      }
    })
  });

  const result = await response.json();
  console.log(result);
  ```

  ```python Python theme={null}
  import requests
  import uuid
  import json

  payload = {
      "jsonrpc": "2.0",
      "id": "req-001",
      "method": "message/send",
      "params": {
          "message": {
              "role": "user",
              "parts": [
                  {
                      "type": "text",
                      "text": "What is the A2A protocol?"
                  }
              ],
              "messageId": str(uuid.uuid4())
          }
      }
  }

  response = requests.post(
      "http://localhost:8000/api/v1/a2a/my-agent",
      headers={"x-api-key": "your-api-key"},
      json=payload
  )

  print(json.dumps(response.json(), indent=2))
  ```
</RequestExample>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "jsonrpc": "2.0",
    "result": {
      "id": "task-456",
      "status": {
        "state": "completed",
        "message": {
          "role": "agent",
          "parts": [
            {
              "type": "text",
              "text": "The A2A (Agent-to-Agent) protocol is a standardized communication protocol developed by Google for enabling structured communication between AI agents. It uses JSON-RPC 2.0 over HTTP/HTTPS and supports features like multi-turn conversations, file uploads, and streaming responses."
            }
          ]
        }
      },
      "contextId": "ctx-abc123",
      "final": true
    },
    "id": "req-001"
  }
  ```

  ```json Error Response theme={null}
  {
    "jsonrpc": "2.0",
    "error": {
      "code": -32602,
      "message": "Invalid params",
      "data": {
        "details": "Missing required field: messageId"
      }
    },
    "id": "req-001"
  }
  ```
</ResponseExample>

## Multi-turn Conversation Example

<RequestExample>
  ```bash First Message theme={null}
  curl -X POST "http://localhost:8000/api/v1/a2a/my-agent" \
    -H "Content-Type: application/json" \
    -H "x-api-key: your-api-key" \
    -d '{
      "jsonrpc": "2.0",
      "id": "req-001",
      "method": "message/send",
      "params": {
        "message": {
          "role": "user",
          "parts": [{"type": "text", "text": "My name is John"}],
          "messageId": "msg-001"
        }
      }
    }'
  ```

  ```bash Follow-up Message theme={null}
  curl -X POST "http://localhost:8000/api/v1/a2a/my-agent" \
    -H "Content-Type: application/json" \
    -H "x-api-key: your-api-key" \
    -d '{
      "jsonrpc": "2.0",
      "id": "req-002",
      "method": "message/send",
      "params": {
        "contextId": "ctx-abc123",
        "message": {
          "role": "user",
          "parts": [{"type": "text", "text": "What is my name?"}],
          "messageId": "msg-002"
        }
      }
    }'
  ```
</RequestExample>

## File Upload Example

<RequestExample>
  ```bash File Upload theme={null}
  curl -X POST "http://localhost:8000/api/v1/a2a/my-agent" \
    -H "Content-Type: application/json" \
    -H "x-api-key: your-api-key" \
    -d '{
      "jsonrpc": "2.0",
      "id": "req-003",
      "method": "message/send",
      "params": {
        "message": {
          "role": "user",
          "parts": [
            {
              "type": "text",
              "text": "Please analyze this document"
            },
            {
              "type": "file",
              "file": {
                "name": "report.pdf",
                "mimeType": "application/pdf",
                "bytes": "JVBERi0xLjQKJcOkw7zDtsO..."
              }
            }
          ],
          "messageId": "msg-003"
        }
      }
    }'
  ```
</RequestExample>

## Best Practices

<AccordionGroup>
  <Accordion icon="lightbulb" title="Message IDs">
    * Always use UUID v4 for `messageId` fields
    * Keep request IDs unique for proper correlation
    * Store `contextId` from responses for multi-turn conversations
  </Accordion>

  <Accordion icon="file" title="File Uploads">
    * Use Base64 encoding **without** data URL prefix
    * Specify correct MIME types for proper handling
    * Keep files under 5MB for optimal performance
  </Accordion>

  <Accordion icon="shield" title="Error Handling">
    * Always check for `error` field in responses
    * Implement retry logic for transient errors (5xx codes)
    * Validate JSON-RPC format before sending requests
  </Accordion>
</AccordionGroup>
