Go
Go SDK
v1.2.0 · MIT License · Go 1.22+ · Zero external dependencies
Zero external dependencies for the core. Uses only stdlib crypto/ed25519, net/http, and encoding/json. Idiomatic Go interfaces throughout.
Installation
go get github.com/projectmed99/aroha/sdks/go
The module path is
github.com/projectmed99/aroha/sdks/go. All packages live under the aroha/ subdirectory within this module.ArohaServer
Minimal agent
package main
import (
"context"
"crypto/ed25519"
"crypto/rand"
"log"
"github.com/projectmed99/aroha/sdks/go/aroha/transport"
"github.com/projectmed99/aroha/sdks/go/aroha/identity"
"github.com/projectmed99/aroha/sdks/go/aroha/messages"
)
func main() {
pub, priv, _ := ed25519.GenerateKey(rand.Reader)
myDID := identity.GenerateDID(pub)
server := transport.NewArohaServer(transport.ArohaServerOptions{
AgentDID: myDID,
Port: 3000,
DevMode: true, // skip crypto in development
OnMessage: func(ctx context.Context, env messages.ArohaEnvelope, respond transport.RespondFn, stream transport.StreamFn) error {
if env.Type != "ArohaRequest" {
return nil
}
body := env.Body.(map[string]any)
capability := body["capability"].(string)
switch capability {
case "greet":
params := body["params"].(map[string]any)
return respond(messages.ArohaResponse{
Capability: capability,
Result: map[string]any{"message": "Hello, " + params["name"].(string) + "!"},
})
}
return nil
},
ResolvePublicKey: func(ctx context.Context, did string) (ed25519.PublicKey, error) {
// return nil, nil if unknown
return nil, nil
},
})
log.Printf("Agent %s listening on :3000", myDID)
log.Fatal(server.Start(context.Background()))
}Production server
server := transport.NewArohaServer(transport.ArohaServerOptions{
AgentDID: myDID,
PrivateKey: priv,
Port: 3000,
ClockToleranceMs: 5000,
MaxBodyBytes: 1_048_576,
MinClientVersion: "1.0",
ResolvePublicKey: func(ctx context.Context, did string) (ed25519.PublicKey, error) {
return registry.LookupPublicKey(ctx, did)
},
Middleware: []transport.Middleware{
rbac.NewMiddleware(rbac.Options{RequiredTrustLevel: 2}),
},
OnMessage: handleMessage,
})ArohaClient
package main
import (
"context"
"fmt"
"github.com/projectmed99/aroha/sdks/go/aroha/transport"
"github.com/projectmed99/aroha/sdks/go/aroha/messages"
)
func main() {
client := transport.NewArohaClient()
envelope, err := messages.BuildEnvelope(messages.BuildEnvelopeParams{
Type: "ArohaRequest",
From: myDID,
To: "did:aroha:travel-agent",
Body: map[string]any{
"capability": "search-flights",
"params": map[string]any{
"from": "JFK",
"to": "LHR",
"date": "2026-08-01",
},
},
CorrelationID: messages.NewCorrelationID(),
PrivateKey: priv,
})
if err != nil {
panic(err)
}
resp, err := client.Send(context.Background(), "http://travel-agent.example.com", envelope)
if err != nil {
panic(err)
}
if resp != nil && resp.Type == "ArohaResponse" {
fmt.Println(resp.Body)
}
}Identity & DIDs
import (
"crypto/ed25519"
"crypto/rand"
"github.com/projectmed99/aroha/sdks/go/aroha/identity"
)
// Self-sovereign DID
pub, priv, _ := ed25519.GenerateKey(rand.Reader)
did := identity.GenerateDID(pub)
// → "did:aroha:base58encodedPublicKey"
// Domain-anchored DID
webDID := identity.BuildWebDID("myco.ai", "agents", "travel")
// → "did:aroha-web:myco.ai:agents:travel"
// Resolve a DID
doc, err := identity.ResolveDID(ctx, "did:aroha:someagent")
// doc.VerificationMethod[0].PublicKeyMultibase → key bytesEnvelopes
import "github.com/projectmed99/aroha/sdks/go/aroha/messages"
// Build a typed envelope — all fields (id, created, expires, nonce, proof) set automatically
env, err := messages.BuildEnvelope(messages.BuildEnvelopeParams{
Type: "ArohaReserve",
From: orchestratorDID,
To: providerDID,
Body: map[string]any{
"capability": "book-flight",
"params": map[string]any{"from": "JFK", "to": "LHR"},
"budgetUsd": 500,
},
CorrelationID: messages.NewCorrelationID(),
PrivateKey: priv,
TTL: 5 * time.Minute, // optional, defaults to 5m
})
// Validate an inbound envelope
result, err := messages.ValidateEnvelope(env, senderPubKey, myDID, nonceRegistry, messages.ValidateOptions{
ClockToleranceMs: 5000,
})Spending Mandates
import (
"time"
"github.com/projectmed99/aroha/sdks/go/aroha/mandate"
)
constraints := mandate.SpendingConstraints{
SpendLimitUSD: 500,
AllowedCapabilities: []string{"search-flights", "reserve-flight"},
ExpiresAt: time.Now().Add(time.Hour),
}
// User authorises the orchestrator
m, err := mandate.IssueIntent(
userDID,
orchestratorDID,
constraints,
userPrivKey,
)
// Orchestrator sub-delegates to a flight agent (limits can only narrow)
subM, err := mandate.Attenuate(m, mandate.AttenuateParams{
GranteeDID: flightAgentDID,
Constraints: mandate.SpendingConstraints{
SpendLimitUSD: 300,
AllowedCapabilities: []string{"reserve-flight"},
},
PrivateKey: orchestratorPrivKey,
})
// Verify on the receiving server
valid, reason, err := mandate.Verify(subM, flightAgentDID)
fmt.Println(valid, reason) // true, "ok"Saga Orchestration
import "github.com/projectmed99/aroha/sdks/go/aroha/orchestrator"
engine := orchestrator.NewSagaEngine(orchestrator.SagaEngineOptions{
Client: client,
OrchestratorDID: myDID,
PrivateKey: priv,
})
result, err := engine.Run(ctx, []orchestrator.SagaStep{
{
AgentDID: "did:aroha:flight-agent",
Endpoint: "http://flights.example.com",
Capability: "reserve-flight",
Params: map[string]any{"from": "JFK", "to": "LHR"},
BudgetUSD: 300,
},
{
AgentDID: "did:aroha:hotel-agent",
Endpoint: "http://hotels.example.com",
Capability: "reserve-hotel",
Params: map[string]any{"city": "London", "nights": 3},
BudgetUSD: 200,
},
})
fmt.Println(result.Status) // "committed" or "compensated"
for _, step := range result.Steps {
fmt.Println(step.CommitToken) // use for billing
}Reputation Engine
import "github.com/projectmed99/aroha/sdks/go/aroha/reputation"
engine := reputation.NewBayesianEngine()
// Record an outcome after a capability call
engine.RecordOutcome(reputation.Outcome{
AgentDID: "did:aroha:flight-agent",
Capability: "reserve-flight",
Satisfaction: reputation.Satisfied, // or Neutral, Dissatisfied
})
// Get the current score (0–1) for routing decisions
score := engine.Score("did:aroha:flight-agent", "reserve-flight")
fmt.Printf("Score: %.3f
", score)
// Thompson Sampling — sample a score for exploration
sampled := engine.Sample("did:aroha:flight-agent", "reserve-flight")All Packages
aroha/cryptoEd25519 sign/verify, AES-GCM, random nonces
aroha/identityDID generation, did:aroha-web:, resolution
aroha/messagesEnvelope types, BuildEnvelope, ValidateEnvelope, NonceRegistry
aroha/transportArohaServer (net/http), ArohaClient
aroha/orchestratorSagaEngine, SagaStep, AgentSelector, CSNHandler
aroha/mandateSpendingMandate: IssueIntent, Attenuate, Verify
aroha/reputationBayesian Beta engine, Thompson Sampling