Skip to main content

Set up an A2A trigger

To allow external agents to communicate with Retool Agents, you can enable the A2A trigger on your agent's configuration page, and copy the endpoint and API key into your A2A client. An API key is provided for each agent, and must be passed to the client via an X-Api-Key header. API keys can be rotated.

The process to use the Agent2Agent (A2A) protocol with Retool Agents is similar to creating a webhook trigger in workflows.

The A2A client then sends messages via common messaging formats like the HTTP+REST or JSON-RPC APIs, and Server-Sent Events (SSE) for long-running streaming updates.

Prior to enabling A2A, you must have all the necessary permissions for Retool AI and AI Agents turned on for your organization. Refer to Permissions for Agents for more information.

Enable the A2A trigger

On the Configuration page of your Retool Agent:

  1. Click the A2A trigger.
  2. Toggle the A2A switch on.
  3. You can either copy and paste the Endpoint and the API key separately into your A2A client, or you can click Copy next to Endpoint and select Copy as cURL from the dropdown. This copies a cURL command preformatted with your Retool Agent information and API key to your clipboard.

The default endpoint provided is the Get agent card endpoint.

Example cURLs

You can cURL to test the agent response to different endpoints. To view a full list of available endpoints, refer to the A2A conceptual guide.

Get agent card

The agent card describes the agent's identity, capabilities, skills, and interaction requirements.

Example cURL
curl --url "https://yourdomain.retool.com/api/agents/a2a/agent_id/.well-known/agent-card.json" \
-H "Content-Type: application/json" \
-H "X-Api-Key: retool_wk_########"
HTTP Response
{
"name":"A2A test",
"preferredTransport":"HTTP+JSON",
"description":"",
"url":"https://yourdomain.retool.com/api/agents/a2a/agent_id",
"provider":
{"organization":"youradmin@retool.com",
"url":"https://yourdomain.retool.com"
},
"protocolVersion":"0.3.0",
"version":"0.0.1",
"capabilities":{
"streaming":true,
"pushNotifications":false
},
"defaultInputModes":[
"application/json"
],
"defaultOutputModes":[
"application/json"
],
"skills":[

]
}"%"

Send message

Sending a message request is the primary way to initiate agent interactions. Clients can send a message to an agent and receive a task in response.

The taskId in A2A is the runId within Retool. When you send a message, for example, via POST /a2a/:agentId/v1/message:send the response is an A2A Task object with a top-level ID field of taskId.

Example cURL
curl -X POST \
"https://yourdomain.retool.com/api/agents/a2a/agent_id/v1/message:send" \
-H "Content-Type: application/json" \
-H "X-Api-Key: retool_wk_#####" \
-d '{
"message": {
"messageId": "msg-12345",
"role": "user",
"parts": [
{
"kind": "text",
"text": "tell me a joke"
}
]
}
}'
Example Response
{
"id":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"status":{
"state":"submitted",
"message":{
"role":"agent",
"parts":[
{"kind":"text",
"text":"Task submitted"
}
],
"messageId":"status-054c93a8-b0ed-49ea-915d-418e615cb7b4-1764717334957",
"taskId":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"kind":"message"
}
},
"kind":"task",
"history":[
{
"role":"user",
"parts":[
{
"kind":"text",
"text":"tell me a joke"
}
],
"messageId":"dd992a34-b2bc-4f4f-b0c1-0e7399da87d2",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"taskId":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"kind":"message"
}
]
}

If testing this endpoint with Retool Agents, you can view the POST in the log output, the monitoring page, or you can make use of the get task or streaming endpoints.

Get task

Get task retrieves the current state (including status, artifacts, and optionally history) of a previously initiated task. This is typically used for polling the status of a task initiated with message:send, or for fetching the final state of a task.

Example cURL
curl --url "https://yourdomain.retool.com/api/agents/a2a/agent_id/v1/tasks/task_id" \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: retool_wk_######'
Example Response
{
"id":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"status":{
"state":"completed",
"message":{
"role":"agent",
"parts":[
{
"kind":"text",
"text":"Why don't skeletons fight each other? \n\nBecause they don't have the guts!"
}
],
"messageId":"8dc8c544-f6d9-49a8-b9e3-cecf2433f23d",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"taskId":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"kind":"message"
}
},
"kind":"task",
"history":[
{
"role":"user",
"parts":[
{
"kind":"text",
"text":"tell me a joke"
}
],
"messageId":"dd992a34-b2bc-4f4f-b0c1-0e7399da87d2",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"taskId":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"kind":"message"
},
{
"role":"agent",
"parts":[
{
"kind":"text",
"text":"Why don't skeletons fight each other? \n\nBecause they don't have the guts!"
}
],
"messageId":"8dc8c544-f6d9-49a8-b9e3-cecf2433f23d",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"taskId":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"kind":"message"
}
]
}"%"

Send streaming messages

Send streaming messages is similar to message:send, but it provides real-time streaming of updates during processing.

Example cURL
 curl -X POST \
"https://yourdomain.retool.com/api/agents/a2a/agent_id/v1/message:stream" \
-H "Content-Type: application/json" \
-H "X-Api-Key: retool_wk_your_api_key" \
-d '{
"message": {
"messageId": "msg-123456",
"role": "user","parts": [
{
"kind": "text",
"text": "tell me a joke"
}
]
}
}'
Example Response
"event":"task
data":{
"task":{
"id":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"status":{
"state":"submitted",
"message":{
"role":"agent",
"parts":[
{
"kind":"text",
"text":"Task submitted"
}
],
"messageId":"status-7c185114-3ba7-4742-80d1-1e03af262ffa-1764963458316",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"kind":"message"
}
},
"kind":"task",
"history":[
{
"role":"user",
"parts":[
{
"kind":"text",
"text":"tell me a joke"
}
],
"messageId":"d61ae646-96d7-45a9-806d-ecac05a2d649",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"kind":"message"
}
]
}
}"event":"statusUpdate
data":{
"statusUpdate":{
"kind":"status-update",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"status":{
"state":"working",
"message":{
"role":"agent",
"parts":[
{
"kind":"text",
"text":"Agent run started, thinking"
}
],
"messageId":"status-7c185114-3ba7-4742-80d1-1e03af262ffa-1764963461322",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"kind":"message"
}
},
"final":false
}
}"event":"statusUpdate
data":{
"statusUpdate":{
"kind":"status-update",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"status":{
"state":"working",
"message":{
"role":"agent",
"parts":[
{
"kind":"text",
"text":"Why don't skeletons fight each other?\n\nBecause they don't have the guts!"
}
],
"messageId":"bed394ef-cd1c-46e9-b469-755620575236",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"kind":"message"
}
},
"final":false
}
}"event":"statusUpdate
data":{
"statusUpdate":{
"kind":"status-update",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"status":{
"state":"completed",
"message":{
"role":"agent",
"parts":[
{
"kind":"text",
"text":"Why don't skeletons fight each other?\n\nBecause they don't have the guts!"
}
],
"messageId":"bed394ef-cd1c-46e9-b469-755620575236",
"contextId":"85ba1598-f940-436f-a964-1bed22b94930",
"taskId":"7c185114-3ba7-4742-80d1-1e03af262ffa",
"kind":"message"
}
},
"final":true
}
}

Subscribe to task

Subscribe to task establishes a streaming connection to receive updates for an existing task.

Example cURL
 curl -X POST \
"https://yourdomain.retool.com/api/agents/a2a/agent_id/v1/tasks/task_id:subscribe" \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: retool_wk_#####'
Example Response
{
"kind":"status-update",
"taskId":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"status":{
"state":"completed",
"message":{
"role":"agent",
"parts":[
{
"kind":"text",
"text":"Why don't skeletons fight each other? \n\nBecause they don't have the guts!"
}
],
"messageId":"8dc8c544-f6d9-49a8-b9e3-cecf2433f23d",
"contextId":"23a617f6-f7a7-40a8-955c-f17faad5c954",
"taskId":"054c93a8-b0ed-49ea-915d-418e615cb7b4",
"kind":"message"
}
},
"final":true
}"%"

Cancel task

Cancel task requests the cancellation of an ongoing task. The server will attempt to cancel the task, but success is not guaranteed (e.g., the task might have already completed or failed, or cancellation might not be supported at its current stage).

Example cURL
 curl -X POST \
"https://yourdomain.retool.com/api/agents/a2a/agent_id/v1/tasks/task_id:cancel" \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: retool_wk_#####'
Example Response
{
"success":false,
"message":"workflow execution already completed"
}"%"