PlatformsGo
Go
Implement the Aelio SDK in Go using the wire protocol — community guide.
Status: No official Go SDK yet. The wire protocol enum includes
'go'as a planned language. This guide shows how to implement the SDK yourself (~300 lines).
Go backends can connect to Aelio by implementing the JSON-over-WebSocket wire protocol directly. The Python SDK (sdk/python/sdk.py, ~330 lines) is the best reference implementation.
Wire protocol overview
Your Go backend Aelio Server
│ │
│── WebSocket /sdk ──────────────▶│ Authorization: Bearer secret
│── register frame ──────────────▶│ (functions, states, persona)
│ │
│◀── invoke frame ────────────────│ (LLM wants a tool)
│── result frame ────────────────▶│ (handler return value)
│ │
│◀── ping ───────────────────────│ (every 30s)
│── pong ──────────────────────▶│Step 1: Connect
package aelio
import (
"net/http"
"github.com/gorilla/websocket"
)
func Connect(secret, serverURL string) (*websocket.Conn, error) {
header := http.Header{}
header.Set("Authorization", "Bearer "+secret)
url := serverURL + "/sdk"
conn, _, err := websocket.DefaultDialer.Dial(url, header)
return conn, err
}Step 2: Register tools
Send immediately after connecting:
type FunctionDef struct {
Name string `json:"name"`
Description string `json:"description"`
Params map[string]interface{} `json:"params"`
Safety string `json:"safety"`
}
type RegisterMessage struct {
Type string `json:"type"`
Functions []FunctionDef `json:"functions"`
Language string `json:"language"`
SDKVersion string `json:"sdkVersion"`
}
func Register(conn *websocket.Conn, functions []FunctionDef) error {
msg := RegisterMessage{
Type: "register",
Functions: functions,
Language: "go",
SDKVersion: "0.1.0",
}
return conn.WriteJSON(msg)
}Step 3: Handle invocations
type InvokeMessage struct {
Type string `json:"type"`
ID string `json:"id"`
Function string `json:"function"`
Args map[string]interface{} `json:"args"`
Context map[string]interface{} `json:"context"`
}
type ResultMessage struct {
Type string `json:"type"`
ID string `json:"id"`
OK bool `json:"ok"`
Data interface{} `json:"data,omitempty"`
Error *ErrorBody `json:"error,omitempty"`
}
type ErrorBody struct {
Code string `json:"code"`
Message string `json:"message"`
Retryable bool `json:"retryable"`
}
type Handler func(args map[string]interface{}, ctx map[string]interface{}) (interface{}, error)
func Listen(conn *websocket.Conn, handlers map[string]Handler) {
for {
var raw map[string]interface{}
if err := conn.ReadJSON(&raw); err != nil {
// reconnect with exponential backoff
break
}
msgType, _ := raw["type"].(string)
switch msgType {
case "invoke":
id, _ := raw["id"].(string)
fn, _ := raw["function"].(string)
args, _ := raw["args"].(map[string]interface{})
ctx, _ := raw["context"].(map[string]interface{})
handler, ok := handlers[fn]
if !ok {
conn.WriteJSON(ResultMessage{
Type: id, ID: id, OK: false,
Error: &ErrorBody{Code: "FUNCTION_NOT_FOUND", Message: fn},
})
continue
}
result, err := handler(args, ctx)
if err != nil {
conn.WriteJSON(ResultMessage{
Type: "result", ID: id, OK: false,
Error: &ErrorBody{Code: "HANDLER_ERROR", Message: err.Error()},
})
} else {
conn.WriteJSON(ResultMessage{
Type: "result", ID: id, OK: true, Data: result,
})
}
case "ping":
conn.WriteJSON(map[string]string{"type": "pong"})
case "send":
// Handle outbound message delivery (BYO channel)
}
}
}Step 4: Full example
package main
import (
"log"
"os"
)
func main() {
secret := os.Getenv("AELIO_SDK_SECRET")
url := os.Getenv("AELIO_SERVER_URL")
conn, err := Connect(secret, url)
if err != nil {
log.Fatal(err)
}
functions := []FunctionDef{
{
Name: "getOrderStatus",
Description: "Get the status of a customer order",
Params: map[string]interface{}{"orderId": map[string]string{"type": "string"}},
Safety: "read",
},
}
if err := Register(conn, functions); err != nil {
log.Fatal(err)
}
handlers := map[string]Handler{
"getOrderStatus": func(args, ctx map[string]interface{}) (interface{}, error) {
return map[string]interface{}{
"orderId": args["orderId"],
"customerId": ctx["customerId"],
"status": "shipped",
}, nil
},
}
log.Println("Aelio SDK connected (Go)")
Listen(conn, handlers)
}Step 5: Run
AELIO_SDK_SECRET=change-me-in-production \
AELIO_SERVER_URL=ws://127.0.0.1:3010 \
go run main.goProtocol reference
| Detail | Value |
|---|---|
| WebSocket path | /sdk |
| Auth header | Authorization: Bearer <secret> |
| Register timeout | 15 seconds |
| Heartbeat interval | 30 seconds |
| Heartbeat timeout | 60 seconds |
| Max frame size | 64 KB |
| Max connections | 32 |
| Reconnect backoff | Exponential, max 30s |
Message types
Client → Server: register, result, pong, ingest, set_state, set_flow_progress
Server → Client: invoke, send, ping, error, ack
See the full SDK Wire Protocol reference.
Reference implementations
- Python SDK:
sdk/python/sdk.py(~330 lines) — best minimal reference - Node SDK:
sdk/node/src/index.ts— full-featured reference - Protocol types:
packages/protocol/src/index.ts— Zod schemas - Server validation:
server/src/routes/sdk.ts— what the server expects