Our A2A “campaign” is so far progressing according to plan: we’ve marched from the motivation for Agent systems, to A2A objects, runtime behaviour and diagrams, ending up with a working Clockwork Agent example in part 5. But Napoleon’s armies didn’t run on maps (diagrams) and dispatches (protocols) alone; they depended on keeping time. Part 6 is where we upgrade the clock to the Quartz Chronometer Agent!
In the previous blog, we introduced the Clockwork Agent example – a runnable demo of the main A2A protocol paths: an immediate Message, a long-running Task, and an input-required flow with follow-up on the same task. You’d be wrong to conclude that’s the end of the story: the Clockwork Agent was a deliberate simplification – it demoed the example using plain Java. This part demonstrates the same example using the official A2A protocols – JSON-RPC on the reference SDK server and SSE for long-running tasks – as the Quartz Chronometer Agent!
You can find the new code here: https://github.com/instaclustr/code-samples/tree/main/AI/A2A/quartz-chronometer
Here’s an explanatory flow diagram:

Quartz Chronometer Agent: the Clockwork Agent examples using the official A2A JSON-RPC + SSE protocols
I’ve called it the Quartz Chronometer, as it’s a significant upgrade to the original Java version. Napoleon had several famous timekeepers that he used during his military campaigns, including a Breguet No. 178 Travel clock and a more practical pocket watch. But even the first experimental quartz clock was 50+ times more accurate than these.
And there’s also a real timing improvement in this version – by moving from polling to streaming.
What the A2A default protocol example includes
The Quartz Chronometer example is a complete A2A default-protocol version of the Clockwork Agent. It’s the same deterministic, rule-based server (so no LLMs yet), but with a different stack:
- Quarkus
- We use Quarkus because the official a2a-java reference server ships on it — see the Quarkus guides for the framework itself.
- Our custom code is now limited to an Agent Card producer and an AgentExecutor; Quarkus handles HTTP, JSON-RPC, and SSE.
- A2A-java reference JSON-RPC server
- Official Quarkus reference server for A2A over JSON-RPC
- https://github.com/a2aproject/a2a-java/blob/main/reference/jsonrpc/README.md
- Agent Card at
/.well-known/agent-card.json - Streaming with SSE for long-running tasks instead of the GetTask poll loop
- For long-running tasks, the client keeps a connection open and receives
statusUpdate/ artifactUpdate frames over Server-Sent Events (SSE) - https://a2a-protocol.org/latest/topics/streaming-and-async/
- For long-running tasks, the client keeps a connection open and receives
What changed in the A2A demo?
The following table summarizes what changed from the Clockwork Agent to the Quartz Chronometer:
| Clockwork (Part 5) | Quartz Chronometer (Part 6) | |
|---|---|---|
| Server | Hand-rolled HttpServer | Official A2A reference server (Quarkus) |
| Binding | JSON-RPC (custom) | JSON-RPC (SDK) |
| Port | 8080 | 8085 |
| Task updates | Client polls GetTask | Client receives streaming SSE statusUpdate / artifactUpdate |
| Examples | 3 examples | Same 3 clockwork examples |
The transports and how the client observes long tasks are the main changes.
Designing the A2A default protocol example
The guiding design principle was to use the best default A2A mechanism that matches each example’s response shape, summarized in the following table:
| Example | Prompt | Server | Client |
|---|---|---|---|
| 1 · Time | What is the current time? | sendMessage → immediate Message | JSON-RPC, streaming off |
| 2 · Countdown | Count down 60 seconds | Task + startWork / updateStatus / complete | JSON-RPC + SSE |
| 3 · Confirm | Count down 20 seconds with confirm | requiresInput → user confirm on same taskId → countdown | SSE before and after confirm |
The implementation is still small (now 570 lines of Java). The AgentExecutor routes prompts, QuartzCountdownRunner drives the async loop via AgentEmitter, and QuartzDemoClient runs all three examples in one script. The full design notes are on GitHub.
A2A demo: Example output
Here’s sample output from the new code:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
=== Agent Card === name: Quartz Chronometer Agent streaming: true skills: 3 === Example 1: Synchronous Time (immediate Message) === Response: The current time is 2026-08-19 14:16:13 AEST. === Example 2: Async Countdown (SSE stream) === Example 2 statusUpdate | state=TASK_STATE_WORKING | Countdown started: 10s remaining. Example 2 artifactUpdate | Countdown completed at 2026-08-19 14:16:23 AEST. Example 2 statusUpdate | state=TASK_STATE_COMPLETED | Countdown completed at 2026-08-19 14:16:23 AEST. Final artifact: Countdown completed at 2026-08-19 14:16:23 AEST. === Example 3: Input-Required Countdown (SSE stream) === event=statusUpdate | state=TASK_STATE_INPUT_REQUIRED | Please confirm countdown start for 10 seconds. Sending confirm on task e45f8042-f43a-4c52-9429-6b41a5d74193 event=statusUpdate | state=TASK_STATE_WORKING | Countdown started: 10s remaining. Example 3 statusUpdate | state=TASK_STATE_WORKING | Countdown started: 10s remaining. Example 3 artifactUpdate | Countdown completed at 2026-08-19 14:16:33 AEST. Example 3 statusUpdate | state=TASK_STATE_COMPLETED | Countdown completed at 2026-08-19 14:16:33 AEST. Final artifact: Countdown completed at 2026-08-19 14:16:33 AEST. === Quartz Chronometer demo complete === |
What each example shows:
- Ex 1 — instant Message back, no Task, no SSE.
- Ex 2 — Task created, SSE delivers
statusUpdate→artifactUpdate→ COMPLETED (~10s later). - Ex 3 — first SSE event is
INPUT_REQUIRED; client sends confirm on the same task ID; then the same SSE countdown pattern as Ex 2.
What’s missing?
So, what’s still missing?
An obvious omission is A2A webhooks. But webhooks are not needed for this example, as the Quartz Chronometer models a connected client that stays open while tasks run. Webhooks only matter if we want to support notifications from Agents to disconnected clients. I went down a rabbit hole with an earlier version of this example (called the “bridge”) and explored three different notification mechanisms for the same “countdown” task, including webhooks (polling, SSE, webhook), and the code is still here).
JSON-RPC for the request-response interaction and SSE streaming (for countdown and confirmation examples) are the correct protocols for this example.
As with the Clockwork Agent example, there are still some simplifications and features implemented, but not demonstrated (see the GitHub for more details on the limitations).
Fixing stale polling data with streaming
After writing the previous blog, I noticed a minor issue with the Clockwork Agent demo (and the polling version of the “bridge” – SSE and webhooks both fixed the problem in that code). Polling doesn’t know if anything changed since the last read – it simply pulls the current value on a fixed schedule. It can therefore receive the same value twice, or even skip over a value. Pull-based updates are not ideal as they are disconnected from real state transitions. Put another way, polling is sampling, not subscribing!
The symptom shows up in the console output as duplicate or missing status lines. Polling is also inefficient. We fixed this problem by using the A2A SSE to prevent guessing on a timer and polling, to let Agents push updates only when status data changes. Each streamed value now corresponds to a real state change, so the clients stay aligned with the Agent. This is our promised timing improvement – the Quartz Chronometer is more accurate than Clockwork!
Benefits of the A2A default protocol example
The Quartz Chronometer (using default A2A protocols) marks significant progress towards a more realistic A2A protocol demo. It preserves the Clockwork Agent’s observable behaviour while replacing the hand-rolled server and polling loop with the official A2A Java reference server, JSON-RPC, and SSE. We still don’t have LLMs or Kafka, but we now have a stronger protocol foundation with significant benefits:
| Benefit | vs original Java-only Clockwork Agent |
|---|---|
| Spec-faithful | Official a2a-java + JSON-RPC reference server — Agent Card, operations, and task lifecycle match what other A2A clients expect |
| Correct task updates | SSE for long tasks (normative connected-client path), not a poll loop (with overheads and stale data) |
| Less custom wire code | You implement business logic (AgentExecutor); the SDK handles JSON-RPC, streaming, and card serving |
| Interoperability | Compliant clients can call it — not tied to the bespoke HttpServer / /rpc shim |
| Production-shaped | Same patterns you’d use for real agents (SDK, requiresInput(), AgentEmitter, streaming capabilities) |
| Room to grow | The project can adopt other official bindings (gRPC/REST) without rewriting the agent model |
The Quartz Chronometer shows how A2A agents can communicate and hand work to one another using the official protocol stack. As those interactions grow in volume, complexity, and operational scope, scaling agent systems will eventually require durable events, state, search and gateways — workloads Instaclustr already operates as managed Kafka, OpenSearch, PostgreSQL, Cassandra, ClickHouse, Cadence, and a new MCP gateway. A2A defines how agents communicate and hand work to one another; Apache Kafka and related infrastructure provide the foundation for operating it at scale.
Want to catch up on the other blogs in this series?
Explore the earlier posts to follow the series from the evolution of agent systems and the A2A object model through runtime behavior, protocol diagrams, and the first runnable Java example.