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

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:

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:

What each example shows:

  1. Ex 1 — instant Message back, no Task, no SSE.
  2. Ex 2 — Task created, SSE delivers statusUpdate → artifactUpdate → COMPLETED (~10s later).
  3. 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.