Install
$ go get github.com/BViganotti/new_actae/sdks/go
Go 1.25+ with github.com/gorilla/websocket. For env-based config: ACTAE_URL, ACTAE_API_KEY, ACTAE_WS_URL — actae.NewClientFromEnv reads them.
60-second start
goimport ("context"; actae "github.com/BViganotti/new_actae/sdks/go")
client, err := actae.NewClientFromEnv(actae.ClientOptions)
ev, _ := client.Record(ctx, "my-channel", "agent.step",
map[string]any{"input": "hello"}, actae.RecordOptions{Actor: "agent"})
events, _ := client.Replay(ctx, "my-channel", actae.ReplayOptions{Limit: 100})Channels are named event streams, events are immutable JSON with a monotonic cursor, replay reads them back. Everything else is a specialization on top.
Payload fidelity and options
- Integer fidelity. JSON decodes with
int64precision —{n: 1}comes back asint64(1),{n: 1.0}asfloat64(1.0). Use theactae.As*accessors (AsInt64,AsString,AsMap,AsList) orjson.Marshal(ev.Payload)into your own struct. - Optional fields are pointers.
actae.Ptr(v)saves you thev := …; &vdance. - Retries are safe. Pass
RecordOptions.OperationID(a stable UUID) — the server returns the original event instead of duplicating. ev.Cursoris the gapless per-channel index — use it for replay resume, subscribe resume, and group acks.
WebSocket
goclient.OnMessage(func(topic string, event actae.Event) { /* live events */})
client.Connect(ctx)
client.SubscribeAndWait(ctx, "my-channel", nil) // cursor to resume from
client.Publish(ctx, "my-channel", map[string]any{"x": 1})
client.Disconnect()Stream(ctx, topic, cursor)returns a channel of live events — subscribe and collect in one call.OnMessagecallbacks accumulate;OnError/OnSubscribed/OnDisconnected/OnReconnectare single-slot.- The server never echoes your own publishes back — set
ClientOptions{EchoSelf: true}for single-client demos. - Auto-reconnect resubscribes all topics from their last cursors; keepalive pings default to 30s.
Connectblocks until the server authenticates your API key (AuthErroron rejection).
State: StateManager and the transactional store
StateManager is the framework-agnostic save/load/resume helper. For stronger guarantees, the state subpackage provides state.Store[T]: a typed store that commits via Transition with expected_version/expected_cursor guards — the event and the snapshot land in one server-side transaction. Replaying the same operation id with byte-identical content is the same logical operation; different content under the same key is a distinct transition.
AgentSession, forks, groups, and executions
AgentSession records full runs with step numbers, deterministic operation IDs, Fork (continues at N+1 with inherited state), and crash-recovery Resume. Consumer groups (create/join/claim/ack/heartbeat), wake-ups (ScheduleWakeup), and idempotent tool executions mirror the Python surface.
GitHub Copilot integration
The actae/copilot subpackage records every Copilot session event (recorder, hooks, session manager, fork) against github.com/github/copilot-sdk/go — every session becomes an Actae channel, forkable at any event.
Errors and testing
HTTP 401 surfaces as AuthError (Python parity); 4xx/5xx map to typed errors with 409 subclasses for idempotency, fork-boundary, version, and execution-claim conflicts. Unit tests need no server (httptest fakes + gorilla test server); the live smoke test runs against a dev instance via ACTAE_URL/ACTAE_API_KEY.