Skip to content

Getting Started

Go from zero to your first cross-organization message. You’ll provision a free Layr8 node, write a simple agent that sends a message to the echo agent in the developer sandbox, and see the response.

What You’ll Build

Your Environment Layr8 Developer Sandbox
┌──────────────────────────┐ ┌──────────────────────────────┐
│ │ │ │
│ ┌────────────────────┐ │ │ ┌────────────────────────┐ │
│ │ Your Agent │ │ DIDComm │ │ Sandbox Echo Agent │ │
│ │ (~30 lines) │──┼──────────────►│ │ Echoes your messages │ │
│ └────────┬───────────┘ │ │ └────────────┬───────────┘ │
│ │ │ │ │ │
│ ┌────────┴───────────┐ │ │ ┌────────────┴───────────┐ │
│ │ Your Node │ │ encrypted │ │ Sandbox Node │ │
│ │ (free, managed) │◄─┼──────────────►│ │ (alice-sandbox │ │
│ │ *.layr8.cloud │ │ │ │ .layr8.cloud) │ │
│ └────────────────────┘ │ │ └────────────────────────┘ │
│ │ │ │
└──────────────────────────┘ └──────────────────────────────┘

Your agent connects to your node via WebSocket. Your node handles encryption, identity resolution, and policy enforcement, then routes messages to the sandbox node — which delivers them to the echo agent. The echo agent responds, and the reply follows the same path back. Your agent never talks directly to the sandbox; the nodes handle everything.

The Developer Sandbox

Layr8 runs a developer sandbox — a set of hosted nodes on *.layr8.cloud with agents you can interact with while building and testing your own:

  • alice-sandbox.layr8.cloud — the requester-side node, hosting agents that initiate cross-org requests (PostgreSQL proxy, REST proxy)
  • bob-sandbox.layr8.cloud — the resource-side node, hosting agents that serve data and respond to requests
  • Echo agent (did:web:alice-sandbox.layr8.cloud:echo) — the simplest sandbox agent: send it a message, get the same message back

The echo agent is useful for verifying your setup end-to-end before integrating with a real partner. The postgres and REST agents demonstrate more complex patterns — see Example Agents for details.

Prerequisites

Step 1: Create Your Free Node

  1. Go to portal.layr8.io and create an account
  2. Create an organization
  3. Provision a free node — this takes about a minute
  4. When the node is ready, click the Console button to open your node’s admin console

Your node is your organization’s messaging endpoint. It handles encryption, identity resolution, and message routing.

Step 2: Configure Your Node

From the admin console:

  1. Create an API key — your agents use this key to connect to your node. You can create multiple keys for different agents or environments. Never share your API key with another person or organization — it’s how your agent establishes trust with your node.
  2. Add DIDs to the allow list — your node only accepts messages from DIDs on its allow list. Add the DIDs of any agents or partners you want to communicate with. You can use a trailing wildcard to allow an entire domain (e.g., did:web:alice-sandbox.layr8.cloud:*). For this tutorial, add did:web:alice-sandbox.layr8.cloud:echo so you can message the sandbox echo agent.
  3. Note your node URL from the console — you’ll need it to connect your agent.

Step 3: Set Up Your Project

Terminal window
export GOPRIVATE=github.com/layr8/*
mkdir my-first-agent && cd my-first-agent
go mod init my-first-agent
go get github.com/layr8/go-sdk

The SDK is in a private repository. GOPRIVATE tells Go to skip the public module proxy. You also need Git configured for SSH access to GitHub — see Troubleshooting if you get authentication errors.

Step 4: Write Your First Agent

Create main.go:

package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"time"
layr8 "github.com/layr8/go-sdk"
)
type EchoResponse struct {
Echo string `json:"echo"`
}
func main() {
client, err := layr8.NewClient(layr8.Config{})
if err != nil {
log.Fatal(err)
}
// Register as an echo protocol speaker — required to connect
client.Handle("https://layr8.io/protocols/echo/1.0/request",
func(msg *layr8.Message) (*layr8.Message, error) {
log.Printf("received echo request: %v", msg.Body)
return &layr8.Message{
Type: "https://layr8.io/protocols/echo/1.0/response",
Body: msg.Body,
}, nil
},
)
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
if err := client.Connect(ctx); err != nil {
log.Fatal(err)
}
defer client.Close()
log.Printf("agent running as %s", client.DID())
// Send a message to the sandbox echo agent
reqCtx, cancel := context.WithTimeout(ctx, 15*time.Second)
defer cancel()
resp, err := client.Request(reqCtx, &layr8.Message{
Type: "https://layr8.io/protocols/echo/1.0/request",
To: []string{"did:web:alice-sandbox.layr8.cloud:echo"},
Body: map[string]string{"message": "hello from my first agent!"},
})
if err != nil {
log.Fatal(err)
}
var echo EchoResponse
if err := resp.UnmarshalBody(&echo); err != nil {
log.Fatal(err)
}
fmt.Printf("Echo replied: %s\n", echo.Echo)
// Keep running — press Ctrl+C to exit
log.Println("listening for messages (Ctrl+C to exit)")
<-ctx.Done()
}

What each part does:

  • Create a client — config falls back to environment variables (LAYR8_NODE_URL, LAYR8_API_KEY, LAYR8_AGENT_DID)
  • Register a handler — declares which protocol your agent speaks. The server requires at least one. Here, your agent handles echo requests (and can respond to them too).
  • Connect — opens the WebSocket connection to your node
  • Send a request — sends a DIDComm message to the sandbox echo agent and waits for the response
  • Stay running — after sending, the agent keeps listening for incoming messages until you press Ctrl+C

For language-specific details, see the Go SDK, Node.js SDK, or Python SDK reference.

Step 5: Run Your Agent

Set your environment variables and run:

Terminal window
export LAYR8_NODE_URL="wss://your-node.layr8.cloud/plugin_socket/websocket"
export LAYR8_API_KEY="your-api-key-from-console"
export LAYR8_AGENT_DID="did:web:your-node.layr8.cloud:my-agent"

LAYR8_AGENT_DID is optional — if you omit it, your node assigns a temporary DID that changes on each connect. Set it to get a stable, addressable identity that other agents can message.

Terminal window
go run .

You should see:

agent running as did:web:your-node.layr8.cloud:my-agent
Echo replied: hello from my first agent!
listening for messages (Ctrl+C to exit)

What Just Happened

Your agent just communicated across organizational boundaries — from your node to the developer sandbox — using identity, not URLs:

  • Identity-based addressing — messages addressed by DID, not endpoint URLs
  • Node-to-node encryption — messages encrypted between nodes using authenticated encryption
  • No shared secrets — no API keys exchanged between organizations
  • Decentralized — no central broker or authority in the middle

This is coordination at Layer 8. Read How Layr8 Works for the full picture.

Alternative: Use Claude Code to Write Your Agent

If you use Claude Code, each SDK includes a skill that teaches Claude the full Layr8 API. Install it once and Claude can build agents for you:

Terminal window
# Clone the SDK repo (if you haven't already)
git clone https://github.com/layr8/go-sdk.git /tmp/layr8-go-sdk
# Copy the skill into your project
mkdir -p .claude/skills
cp /tmp/layr8-go-sdk/.claude/skills/build-layr8-agent.md .claude/skills/

Then describe what you want:

“Build me an echo agent that responds to messages with the same content.”

Claude writes a complete, working agent — config, handler registration, connection management, and graceful shutdown.

Troubleshooting

connection error: join rejected: error

Check your LAYR8_NODE_URL and LAYR8_API_KEY. The most common cause is an incorrect API key or a malformed WebSocket URL. The URL should look like wss://your-node.layr8.cloud/plugin_socket/websocket.

protocols_already_bound

Another agent is already connected with the same DID. Each DID can only have one active connection. Either close the other agent or use a different LAYR8_AGENT_DID.

Messages sent but no response (timeout)

Check your node’s allow list in the admin console. Your node only delivers messages from DIDs on its allow list. For the echo agent, add did:web:alice-sandbox.layr8.cloud:echo (or did:web:alice-sandbox.layr8.cloud:* for all sandbox agents).

Python: SSLCertVerificationError on macOS

macOS Python installations sometimes lack root certificates. Fix with:

Terminal window
pip install certifi
export SSL_CERT_FILE=$(python -c "import certifi; print(certifi.where())")

Go: could not read Username for 'https://github.com'

The Go SDK is in a private repository. Set GOPRIVATE and ensure Git is configured for SSH access to GitHub:

Terminal window
export GOPRIVATE=github.com/layr8/*
git config --global url."git@github.com:".insteadOf "https://github.com/"

For more on error handling in DIDComm, see Problem Reports.

Next Steps

  • Example Agents — Echo, Postgres, REST proxy, IoT — working code to learn from
  • SDK ReferenceGo · Node.js · Python — Core concepts, patterns, and API details
  • Architecture — How a Layr8 Node fits into your infrastructure
  • How Layr8 Works — Core concepts and the paradigm shift