java-server
java-server exposes an Agent over the AG-UI protocol. It reads a RunAgentInput, runs the agent, and streams the resulting events back as Server-Sent Events. It is the server-side counterpart of HttpAgent.
- A transport-neutral core (
com.agui.community.server) that handles parsing, running, framing and backpressure, with no dependency on an HTTP framework. - A JDK adapter (
com.agui.community.server.jdk) for the built-incom.sun.net.httpserver.HttpServer, with no third-party dependencies.
JDK HTTP server
HttpServer uses a single thread when no executor is set, so set an executor with enough threads for your concurrent runs. On Java 21+ you can use Executors.newVirtualThreadPerTaskExecutor().
Responses
If the agent signals
onError, the handler writes a final RUN_ERROR event and closes the stream. It does not drop the connection.
Multiple agents
Pass anAgentRegistry to serve several agents from one context. The path segment after the context selects the agent:
/agent) works only when the registry holds exactly one agent. The single-agent constructor new JdkAgentHttpHandler(agent, serializer) is shorthand for a registry with one entry under the ID default, so that agent answers on both /agent and /agent/default.
AgentRegistry is an interface with find(id) and ids(). Implement it yourself to resolve agents dynamically, for example per tenant or from a database.
Building blocks
To run on another stack, such as plain servlets, Netty, Vert.x or a WebSocket server, use the core types directly.Custom transport
parse and run are separate steps. This lets you reject bad input with a 400 before you commit to a streaming 200:
run always completes normally, whether the stream ended normally, on an error (after the RUN_ERROR frame), or because the client disconnected.
Backpressure and disconnects
EventRelaySubscriber requests one event at a time and asks for the next only after the previous frame has been written. A slow client therefore slows the agent down through the subscription. If EventSink.write throws an IOException, for example because the client went away, the subscriber cancels the subscription. Your agent should stop producing events when it is cancelled.
Other wire formats
TheEventEncoder alone decides the framing. For a WebSocket transport that sends one JSON document per message, pass an encoder that skips the SSE framing:
Serializer.