essessey
Say the letters out loud. That’s the name. S-S-E.
essessey gets a model’s answer to whoever is waiting for it: token by token, block by block, in the order it actually happened. A turn is a sequence of Event values (an optional id, a name and a JSON payload). A Sink delivers them over SSE, NATS, WebSocket or anything else you write, and a Source reads them back so Reassemble can glue the turn together again at the other end.
The hill this package dies on: SSE is a format, not a transport. The event: / data: / blank line framing exists because an HTTP response body is a pipe with no seams. NATS and WebSocket already deliver discrete messages, so there the framing is dead weight. Here SSE is one binding that adds framing, the message-oriented ones don’t, and all of them carry the same Event. Events and bindings has the whole argument.
It doesn’t talk to a model; that’s elelem’s job, and the elelem adapter is the seam between them. It doesn’t own your HTTP handler and doesn’t pick your broker. The NATS and WebSocket bindings are written against the one method each needs, so you hand them the connection you already have and essessey pulls in no transport SDK.
Install
go get github.com/psyb0t/essessey
The module declares go 1.26.0 in its go.mod, so you need Go 1.26 or newer.
Quick look
sink := essessey.NewInMemorySink() // or sse.NewWriterSink(w), nats.NewSink(conn, "turn"), ws.NewSink(conn)
pub := essessey.NewPublisher(ctx, sink)
if err := pub.SendStreamPreamble(msgID, streamID, model); err != nil {
return err
}
streamer := essessey.NewTextStreamer(pub, 0)
for chunk := range delta {
if err := streamer.Write(ctx, chunk); err != nil {
return err
}
}
if err := streamer.Close(ctx); err != nil {
return err
}
return pub.SendStreamEpilogue(essessey.StopReasonEndTurn, outputTokens)
Where to go next
| You want to | Read |
|---|---|
| Emit a first stream and read it back | Getting started |
Understand Event, Sink, Source and why SSE is not a transport | Events and bindings |
| See every event, payload and block type on the wire | Event protocol |
| Emit text, reasoning, line-checked output and tool blocks | Publisher and streamers |
| Turn a stream back into text, tool calls and a timeline | Reading a stream back |
| Let a client reconnect without losing events | Resuming a dropped stream |
Stream over HTTP with text/event-stream | SSE binding |
| Publish to NATS subjects | NATS binding |
| Send events over a WebSocket | WebSocket binding |
| Wire elelem’s callbacks straight into the protocol | elelem adapter |
| Build, lint and test the library itself | Development |
The Go package docs are on pkg.go.dev, and the source is on GitHub.