Skip to main content

java-core

java-core defines the protocol’s data model and the Agent abstraction. It has no third-party runtime dependencies. Streaming uses the JDK’s java.util.concurrent.Flow, and JSON is left to a pluggable Serializer.

Packages

The Agent interface

Everything in the SDK is an Agent: your own implementation, the remote HttpAgent client, and the Spring AI SpringAiAgent. This means a client and a server agent are interchangeable. For example, you can put a remote agent behind your own server, or test a front-end integration against a local stub. The contract is:
  • Each subscription to the returned publisher is one run.
  • The publisher emits the run’s events in order, then calls onComplete.
  • If the run fails, the publisher calls onError. The server modules convert this into a terminal RUN_ERROR event for the client.
Because Flow.Publisher is the JDK’s copy of the Reactive Streams interface, you can convert it at the edges of your application:

Implementing an agent

Without a reactive library, SubmissionPublisher is the easiest way to produce events. Create one per subscription so that each subscriber gets its own run:
With Project Reactor you can build the stream as a Flux and convert it once:
A well-formed run starts with RUN_STARTED and ends with RUN_FINISHED or RUN_ERROR. See Events for the full set of events.

Serialization

The core does not depend on a JSON library. Client and server components take a Serializer:
An implementation must:
  • Handle the sealed hierarchies polymorphically: Event uses the type discriminator ("RUN_STARTED", …), Message uses role ("user", …), and RunOutcome uses type ("success", "interrupt").
  • Write enums (Role, EventType, OutcomeType, ResumeStatus) by their wire value.
  • Be thread-safe.
  • Wrap library-specific failures in SerializationException. The server modules map this exception to 400 Bad Request.

JacksonSerializer

You usually don’t need to write a serializer yourself. JacksonSerializer in ag-ui-spring-server-core does all of the above with Jackson. Despite the artifact name, it does not depend on Spring:
It ignores unknown properties and omits null fields, so a RunAgentInput serializes as:
If you want to configure your own ObjectMapper the same way, call JacksonSerializer.configure(mapper).

Next