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
x-ttlnumber(GopherHole extension) Message time-to-live in seconds. 0 = fail if offline (no queue). Omit = recipient default (30 days). See Offline Delivery.

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
}'