<?xml version="1.0" encoding="UTF-8"?>
<mule
xmlns:a2a="http://www.mulesoft.org/schema/mule/a2a"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/a2a http://www.mulesoft.org/schema/mule/a2a/current/mule-a2a.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd">
<http:listener-config name="HTTP_Listener_config" basePath="/v1">
<http:listener-connection host="0.0.0.0" port="${http.port}"/>
</http:listener-config>
<a2a:server-config name="A2A_Server">
<a2a:connection listenerConfig="HTTP_Listener_config" agentPath="/stock-summarizer">
<a2a:interfaces>
<a2a:interface protocol="JSONRPC" path="/rpc"/>
<a2a:interface protocol="HTTP_JSON" path="/"/>
</a2a:interfaces>
</a2a:connection>
<a2a:agent-card>
<a2a:json><![CDATA[{
"name": "Stock Summarizer Agent",
"version": "2.0.0",
"protocolVersion": "1.0",
"description": "Summarizes stock-related questions; supports streaming and push notifications.",
"supportedInterfaces": [
{ "protocolBinding": "JSONRPC", "url": "http://localhost:8082/v1/stock-summarizer/rpc", "protocolVersion": "1.0", "tenant": "" },
{ "protocolBinding": "HTTP_JSON", "url": "http://localhost:8082/v1/stock-summarizer/", "protocolVersion": "1.0", "tenant": "" }
],
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": false
},
"skills": [
{
"id": "stock-summary",
"name": "Stock Earnings Summary",
"description": "Summarizes stock earnings and financial highlights.",
"inputModes": ["application/json", "text/plain"],
"outputModes": ["application/json", "text/plain"]
}
],
"provider": { "organization": "MuleSoft", "url": "https://www.mulesoft.com" },
"defaultInputModes": ["application/json", "text/plain"],
"defaultOutputModes": ["application/json", "text/plain"]
}]]></a2a:json>
</a2a:agent-card>
</a2a:server-config>
<a2a:client-config name="A2A_Client">
<a2a:jsonrpc-client-connection agentUrl="http://localhost:8082/v1/stock-summarizer"/>
</a2a:client-config>
<http:request-config name="OpenAI_config" basePath="/v1">
<http:request-connection host="api.openai.com" port="443" protocol="HTTPS"/>
</http:request-config>
<!-- Optional: customize the initial Task response for streaming and non-blocking sends. -->
<flow name="initialTaskFlow">
<a2a:on-async-request-listener config-ref="A2A_Server"/>
<ee:transform>
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
task: {
id: attributes.taskId,
contextId: attributes.contextId,
status: { state: "TASK_STATE_SUBMITTED" }
}
}]]></ee:set-payload>
</ee:message>
</ee:transform>
</flow>
<!-- Unified task-listener: serves blocking, non-blocking, and streaming SendMessage. -->
<flow name="a2aServerFlow">
<a2a:task-listener config-ref="A2A_Server"/>
<ee:transform doc:name="OpenAI Request">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
model: "gpt-4.1",
messages: [ { role: "user", content: payload.message.parts[0].text } ]
}]]></ee:set-payload>
</ee:message>
<ee:variables>
<ee:set-variable variableName="taskId">#[attributes.taskId]</ee:set-variable>
<ee:set-variable variableName="contextId">#[attributes.contextId]</ee:set-variable>
</ee:variables>
</ee:transform>
<http:request method="POST" config-ref="OpenAI_config" path="/chat/completions" responseTimeout="20000">
<http:headers><![CDATA[#[%dw 2.0
output application/java
---
{ Authorization: "Bearer " ++ p("secure::openai.token") }]]]></http:headers>
</http:request>
<ee:transform doc:name="A2A Task Response">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
id: vars.taskId,
contextId: vars.contextId,
status: {
state: "TASK_STATE_COMPLETED",
message: {
role: "ROLE_AGENT",
messageId: uuid(),
parts: [{ text: payload.choices[0].message.content }]
}
},
artifacts: [
{
artifactId: uuid(),
name: "answer",
parts: [{ text: payload.choices[0].message.content }]
}
]
}]]></ee:set-payload>
</ee:message>
</ee:transform>
</flow>
<!-- Push-notification config authoring (unchanged listener; 1.0.0 TaskPushNotificationConfig shape on payload). -->
<flow name="pushNotificationConfigFlow">
<a2a:push-notification-config-listener config-ref="A2A_Server"/>
<logger level="INFO" message="Push notification config: #[payload]"/>
</flow>
<flow name="pushNotificationCallbackFlow">
<http:listener config-ref="HTTP_Listener_config" path="/update/notification"/>
<logger level="INFO" message="Push notification callback received: #[payload]"/>
</flow>
<!-- Example client caller: submit a task then iterate the server's task list. -->
<flow name="a2aClientFlow">
<http:listener config-ref="HTTP_Listener_config" path="/stock/summarize"/>
<a2a:send-message config-ref="A2A_Client">
<a2a:message><![CDATA[#[%dw 2.0
output application/json
---
{
message: {
role: "ROLE_USER",
messageId: uuid(),
parts: [{ text: "Summarize the stock earnings for " ++ attributes.queryParams.stock ++ " in Q4 2024" }]
},
configuration: {
pushNotificationConfig: {
url: "http://localhost:8082/v1/update/notification"
}
}
}]]></a2a:message>
</a2a:send-message>
</flow>
<flow name="listAllTasksFlow">
<http:listener config-ref="HTTP_Listener_config" path="/admin/tasks"/>
<foreach batchSize="1">
<a2a:list-tasks config-ref="A2A_Client">
<a2a:list-tasks-params><![CDATA[{ "pageSize": 50 }]]></a2a:list-tasks-params>
</a2a:list-tasks>
<logger level="INFO" message="Task page: #[payload]"/>
</foreach>
</flow>
</mule>