A2A push connector
a2a-push receives Agent2Agent push-notification webhooks from remote
A2A agents. It is for federated Harn orchestrators: one orchestrator can
start long-running work on another and be woken when the remote task
changes state.
Orchestrator A -- a2a://B/task --> Orchestrator B
^ |
| |
+------- push POST task done --------+
Manifest
Use kind = "a2a-push" and add [triggers.a2a_push] to opt into the
connector verifier:
[[triggers]]
id = "reviewer-task-update"
kind = "a2a-push"
provider = "a2a-push"
path = "/a2a/review"
match = { events = ["a2a.task.completed", "a2a.task.failed"] }
handler = "handlers::on_reviewer_update"
[triggers.a2a_push]
expected_iss = "reviewer.prod"
expected_aud = "https://orchestrator.example.com/a2a/review"
jwks_url = "https://reviewer.prod/.well-known/jwks.json"
expected_token = "opaque-task-token"
JWT/JWKS is the default. The connector verifies:
Authorization: Bearer <jwt>is present.- The JWT signature matches the
kidin the remote JWKS. issandaudmatch the manifest.expis still in the future andiatis not in the future.jtiis single-use through the trigger inbox.expected_token, when set, matches the JWTtokenclaim, theX-A2A-Tokenheader, or atokenfield in the JSON body.
JWKS entries are cached for one day and refreshed after expiry.
Event shape
The connector accepts A2A stream-response push payloads:
{
"statusUpdate": {
"taskId": "task-123",
"contextId": "ctx-123",
"status": {"state": "completed"}
}
}
Task status updates map to TriggerEvent.kind values like
a2a.task.completed, a2a.task.failed, and a2a.task.canceled.
Artifact and message pushes map to a2a.task.artifact and
a2a.task.message.
Handlers receive provider_payload with:
task_idtask_stateartifactsenderkindraw
A2A dispatch registration
When HARN_A2A_PUSH_URL is set, outbound a2a://... dispatches include
and register a pushNotificationConfig for pending tasks. Set
HARN_A2A_PUSH_TOKEN to include a bearer credential in that config.
The built-in harn serve a2a adapter advertises push notification
support, stores push configs, and posts statusUpdate payloads to each
configured webhook when an asynchronous task completes or fails.
pushNotificationConfig.authentication is honored when the remote
webhook declares how Harn should authenticate the callback:
{
"url": "https://client.example/a2a/push",
"authentication": {
"schemes": ["OAuth2"],
"token_url": "https://idp.example/oauth/token",
"client_id": "harn-a2a",
"client_secret": "${secret}",
"scope": "push.write"
}
}
Supported schemes:
Bearer: sendsAuthorization: Bearer <credentials>.Basic: sendsAuthorization: Basic <credentials>, or builds the value fromusername/password.ApiKey: sendscredentialsinX-API-Keyby default, or in the configuredheader.OAuth2: uses client credentials attoken_urland sends the returned beareraccess_token.OpenIDConnect/oidc: uses client credentials, requires anid_token, validates it againstissuer,client_id/audience, andjwks_url, then sends it as a bearer credential. JWKS are cached and refreshed when a token arrives with a rotatedkid.mTLS: loadsclient_certplusclient_key, orclient_identity, and may useca_certfor private webhook CAs.
Legacy a2a-push routes without [triggers.a2a_push] keep the older
orchestrator listener auth: HARN_ORCHESTRATOR_API_KEYS plus
HARN_ORCHESTRATOR_HMAC_SECRET.