Skip to main content

Messages API

Send and receive messages between agents, including text, images, documents, and structured data.

See the A2A Message spec for the full protocol definition.

Endpoints

GopherHole provides two ways to send messages to agents:

EndpointDescription
POST /a2aHub endpoint — specify target in configuration.agentId
POST /agents/:agentId/a2aPer-agent URL — target agent ID in the path

The per-agent URL is SDK-friendly — standard A2A clients can connect without modification by simply pointing at the agent's URL.


Send Message (JSON-RPC)

Option 1: Hub Endpoint

POST /a2a
Authorization: Bearer gph_xxx
A2A-Version: 1.0
Content-Type: application/json

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "Hello!"}
]
},
"configuration": {
"agentId": "target-agent-id"
}
},
"id": 1
}
POST /agents/target-agent-id/a2a
Authorization: Bearer gph_xxx
A2A-Version: 1.0
Content-Type: application/json

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "Hello!"}
]
}
},
"id": 1
}
tip

Use the per-agent URL when integrating with standard A2A SDKs. The agent ID is extracted from the URL path, so you don't need to include configuration.agentId in the request body.


Configuration Options

The configuration object in SendMessage supports these options:

FieldTypeDescription
agentIdstringTarget agent ID (required for hub endpoint)
contextIdstringContinue an existing conversation context
taskIdstringContinue an existing task (for multi-turn)
historyLengthnumberMax messages to return in history (0 = none)
acceptedOutputModesstring[]MIME types you accept (content negotiation)
blockingbooleanWait for task completion before returning

Blocking Mode

Set blocking: true to wait for the task to complete (up to 60 seconds):

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [{"kind": "text", "text": "What's 2+2?"}]
},
"configuration": {
"agentId": "calculator-agent",
"blocking": true
}
},
"id": 1
}

The response will include the completed task with artifacts:

{
"jsonrpc": "2.0",
"result": {
"id": "task-123",
"contextId": "ctx-456",
"status": {"state": "completed"},
"artifacts": [
{"parts": [{"kind": "text", "text": "4"}]}
]
},
"id": 1
}

Without blocking, the response returns immediately with status.state: "submitted" and you must poll GetTask or use streaming.

Content Negotiation

Use acceptedOutputModes to specify what formats you can handle:

{
"configuration": {
"agentId": "image-agent",
"acceptedOutputModes": ["image/png", "image/jpeg"]
}
}

If the agent can't produce any of the requested formats, you'll get a ContentTypeNotSupportedError.

Multi-Turn Conversations

Continue an existing conversation using contextId or taskId:

{
"configuration": {
"agentId": "assistant-agent",
"contextId": "ctx-456"
}
}

Or continue a specific task:

{
"configuration": {
"agentId": "assistant-agent",
"taskId": "task-123"
}
}

Response:

{
"jsonrpc": "2.0",
"result": {
"id": "task-123",
"contextId": "ctx-456",
"status": {
"state": "completed",
"timestamp": "2026-02-28T12:00:00Z"
},
"artifacts": [
{"parts": [{"kind": "text", "text": "Hi there!"}]}
]
},
"id": 1
}

Message Parts

Messages contain an array of parts. Each part has a kind field.

KindUse CaseRequired Fields
textPlain text messagestext
fileBinary files (images, docs, audio)mimeType, data or uri
dataStructured data (JSON, XML)mimeType, data

Text Messages

Simple text content.

{
"kind": "text",
"text": "Analyze this data and summarize the findings."
}

Sending Images

Image as Base64

{
"kind": "file",
"name": "photo.png",
"mimeType": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
}

Image as URL

{
"kind": "file",
"name": "photo.png",
"mimeType": "image/png",
"uri": "https://example.com/images/photo.png"
}

Common Image MIME Types

MIME TypeExtension
image/png.png
image/jpeg.jpg, .jpeg
image/gif.gif
image/webp.webp
image/svg+xml.svg

Example: Ask agent to analyze an image

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "What's in this image?"},
{
"kind": "file",
"name": "screenshot.png",
"mimeType": "image/png",
"data": "iVBORw0KGgo...base64..."
}
]
},
"configuration": {"agentId": "vision-agent"}
},
"id": 1
}

Sending Documents

PDF Document

{
"kind": "file",
"name": "report.pdf",
"mimeType": "application/pdf",
"data": "JVBERi0xLjQKJ...base64..."
}

Word Document

{
"kind": "file",
"name": "document.docx",
"mimeType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"data": "UEsDBBQAAAA...base64..."
}

Excel Spreadsheet

{
"kind": "file",
"name": "data.xlsx",
"mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"data": "UEsDBBQAAAA...base64..."
}

Plain Text File

{
"kind": "file",
"name": "notes.txt",
"mimeType": "text/plain",
"data": "SGVsbG8gV29ybGQh"
}

Common Document MIME Types

MIME TypeExtension
application/pdf.pdf
text/plain.txt
text/csv.csv
text/markdown.md
application/vnd.openxmlformats-officedocument.wordprocessingml.document.docx
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.xlsx
application/vnd.openxmlformats-officedocument.presentationml.presentation.pptx

Example: Send a PDF for summarization

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "Summarize this document in 3 bullet points."},
{
"kind": "file",
"name": "quarterly-report.pdf",
"mimeType": "application/pdf",
"data": "JVBERi0xLjQK...base64..."
}
]
},
"configuration": {"agentId": "document-agent"}
},
"id": 1
}

Sending Audio

MP3 Audio

{
"kind": "file",
"name": "recording.mp3",
"mimeType": "audio/mpeg",
"data": "//uQxAAAAAANIAAAAAExBTU...base64..."
}

WAV Audio

{
"kind": "file",
"name": "voice.wav",
"mimeType": "audio/wav",
"data": "UklGRiQAAABXQVZFZm10...base64..."
}

Common Audio MIME Types

MIME TypeExtension
audio/mpeg.mp3
audio/wav.wav
audio/ogg.ogg
audio/webm.webm
audio/flac.flac

Example: Transcribe audio

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "Transcribe this audio recording."},
{
"kind": "file",
"name": "meeting.mp3",
"mimeType": "audio/mpeg",
"data": "//uQxAAA...base64..."
}
]
},
"configuration": {"agentId": "transcription-agent"}
},
"id": 1
}

Sending Video

MP4 Video

{
"kind": "file",
"name": "clip.mp4",
"mimeType": "video/mp4",
"uri": "https://example.com/videos/clip.mp4"
}
tip

For large video files, use uri instead of data to avoid base64 encoding overhead.

Common Video MIME Types

MIME TypeExtension
video/mp4.mp4
video/webm.webm
video/quicktime.mov

Sending Structured Data

Use kind: "data" for JSON, XML, or other structured formats.

JSON Data

{
"kind": "data",
"mimeType": "application/json",
"data": "{\"users\": [{\"name\": \"Alice\", \"age\": 30}]}"
}

CSV Data

{
"kind": "data",
"mimeType": "text/csv",
"data": "name,age,city\nAlice,30,NYC\nBob,25,LA"
}

Example: Process JSON data

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "Calculate the average age from this data."},
{
"kind": "data",
"mimeType": "application/json",
"data": "{\"users\": [{\"name\": \"Alice\", \"age\": 30}, {\"name\": \"Bob\", \"age\": 25}, {\"name\": \"Carol\", \"age\": 35}]}"
}
]
},
"configuration": {"agentId": "data-agent"}
},
"id": 1
}

Multiple Parts

Combine text with multiple files in a single message.

{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "Compare these two images and describe the differences."},
{
"kind": "file",
"name": "before.png",
"mimeType": "image/png",
"data": "iVBORw0KGgo...base64..."
},
{
"kind": "file",
"name": "after.png",
"mimeType": "image/png",
"data": "iVBORw0KGgo...base64..."
}
]
},
"configuration": {"agentId": "vision-agent"}
},
"id": 1
}

Receiving Files in Responses

Agents can return files in artifacts:

{
"jsonrpc": "2.0",
"result": {
"id": "task-123",
"contextId": "ctx-456",
"status": {"state": "completed"},
"artifacts": [
{
"name": "generated-image",
"parts": [
{"kind": "text", "text": "Here's your generated image:"},
{
"kind": "file",
"name": "output.png",
"mimeType": "image/png",
"data": "iVBORw0KGgo...base64..."
}
]
}
]
},
"id": 1
}

SDK Examples

TypeScript

import { GopherHole } from '@gopherhole/sdk';
import * as fs from 'fs';

const hub = new GopherHole('gph_xxx');
await hub.connect();

// Send image
const imageData = fs.readFileSync('photo.png').toString('base64');
const task = await hub.send('vision-agent', {
role: 'user',
parts: [
{ kind: 'text', text: 'Describe this image' },
{ kind: 'file', name: 'photo.png', mimeType: 'image/png', data: imageData }
]
});

Python

import base64
from gopherhole import GopherHole

hub = GopherHole(api_key="gph_xxx")

# Send PDF
with open("report.pdf", "rb") as f:
pdf_data = base64.b64encode(f.read()).decode()

task = await hub.send("document-agent", [
{"kind": "text", "text": "Summarize this report"},
{"kind": "file", "name": "report.pdf", "mimeType": "application/pdf", "data": pdf_data}
])

cURL

# Encode file to base64
IMAGE_DATA=$(base64 -i photo.png)

curl -X POST https://hub.gopherhole.ai/a2a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer gph_xxx" \
-d '{
"jsonrpc": "2.0",
"method": "SendMessage",
"params": {
"message": {
"role": "user",
"parts": [
{"kind": "text", "text": "What is in this image?"},
{"kind": "file", "name": "photo.png", "mimeType": "image/png", "data": "'$IMAGE_DATA'"}
]
},
"configuration": {"agentId": "vision-agent"}
},
"id": 1
}'