Go SDK
The Layr8 Go SDK is a minimal, idiomatic Go library for building DIDComm agents. It handles WebSocket connections, Phoenix Channel protocol, DIDComm message formatting, reconnection with backoff, and thread correlation. You write domain logic.
A basic agent is ~50 lines of Go. The SDK manages everything between your handler and the network.
Install
go get github.com/layr8/go-sdkCore Concepts
Config
client, err := layr8.NewClient(layr8.Config{ NodeURL: "wss://your-node.node.layr8.io/plugin_socket/websocket", APIKey: "your-api-key", AgentDID: "did:web:your-node.node.layr8.io:my-agent",})All fields fall back to environment variables if empty: LAYR8_NODE_URL, LAYR8_API_KEY, LAYR8_AGENT_DID. If AgentDID is omitted, the node assigns an ephemeral DID on connect.
Handlers
Register handlers before calling Connect. The handler’s return value determines what happens:
client.Handle("https://layr8.io/protocols/echo/1.0/request", func(msg *layr8.Message) (*layr8.Message, error) { // Return (*Message, nil) → send response to sender // Return (nil, error) → send problem report to sender // Return (nil, nil) → no response (fire-and-forget) },)The protocol base URI is derived automatically from the message type and registered with the node on connect.
Send (Fire-and-Forget)
err := client.Send(ctx, &layr8.Message{ Type: "https://didcomm.org/basicmessage/2.0/message", To: []string{"did:web:partner-node:agent"}, Body: map[string]string{"content": "Hello!"},})Request (Request/Response)
resp, err := client.Request(ctx, &layr8.Message{ Type: "https://layr8.io/protocols/echo/1.0/request", To: []string{"did:web:partner-node:echo-agent"}, Body: EchoRequest{Message: "ping"},})// resp is the correlated response, matched by thread IDMessages
type Message struct { ID string // auto-generated if empty Type string // DIDComm message type URI From string // auto-filled with agent DID To []string // recipient DIDs ThreadID string // auto-generated for Request Body any // serialized to JSON Context *MessageContext // populated on inbound messages}Use msg.UnmarshalBody(&target) to deserialize the body. On inbound messages, msg.Context provides node metadata: Authorized, Recipient, and SenderCredentials.
Durable Handlers (Persist-then-Ack)
For messages that must not be lost, use manual ack to persist before acknowledging:
client.Handle("https://layr8.io/protocols/order/1.0/created", func(msg *layr8.Message) (*layr8.Message, error) { var body any msg.UnmarshalBody(&body)
// Write to disk first — if this fails, the message is // NOT acked and the cloud-node will redeliver it. if err := persistToDisk(msg.ID, body); err != nil { return nil, err }
msg.Ack() // safe to ack now return nil, nil }, layr8.WithManualAck(),)See examples/durable-handler for a complete working example.
Claude Code Skill
The SDK includes a Claude Code skill that teaches Claude the full API. Install it into any agent project:
mkdir -p .claude/skillscp /path/to/go-sdk/.claude/skills/build-layr8-agent.md .claude/skills/Once installed, Claude Code knows how to build Layr8 agents in every session. Example prompts:
- “Build me a postgres query agent that forwards SQL queries to a partner’s database”
- “Add a handler for order.created messages that validates the sender’s credentials”
- “Convert this REST endpoint into a DIDComm agent”
Links
- Go SDK on GitHub — Full README, source code, and examples
- Example Agents — Working demo agents from beginner to advanced
- DIDComm Reference — Protocol details and message patterns
- Getting Started — End-to-end setup walkthrough