### Install Layr8 Go SDK Source: https://docs.layr8.io/build/go-sdk Installs the Layr8 Go SDK using the go get command. This is the first step to integrating the SDK into your Go project. ```go go get github.com/layr8/go-sdk ``` -------------------------------- ### Set Up SSL/TLS Certificates with Let's Encrypt Source: https://docs.layr8.io/reference/hosting-dids-on-your-domain Configure SSL/TLS for secure HTTPS connections using Let's Encrypt. The certbot command is used to obtain and install certificates. Testing the SSL configuration with openssl ensures proper setup. ```bash # Using Let's Encrypt certbot certonly --webroot -w /var/www/html -d example.com # Test SSL configuration openssl s_client -connect example.com:443 -servername example.com ``` -------------------------------- ### Installation Source: https://docs.layr8.io/build/python-sdk Instructions on how to install the Layr8 Python SDK using pip. ```APIDOC ## Installation ### Description Install the Layr8 Python SDK using pip. Requires Python version 3.11 or higher. ### Command ```bash pip install layr8 ``` ### Requirements - Python >= 3.11 ``` -------------------------------- ### Protocol Versioning Examples Source: https://docs.layr8.io/concepts/layr8 Shows how protocol URIs are used for versioning. Different URIs indicate different versions of a protocol, allowing for backward-compatible additions or breaking changes. ```text https://acme.com/protocols/procurement/1.0/rfq ← original https://acme.com/protocols/procurement/1.1/rfq ← backward-compatible addition https://acme.com/protocols/procurement/2.0/rfq ← breaking change ``` -------------------------------- ### Install Layr8 Python SDK Source: https://docs.layr8.io/build/python-sdk Installs the Layr8 Python SDK using pip. Requires Python version 3.11 or higher. ```bash pip install layr8 ``` -------------------------------- ### Install Claude Code Skill for Layr8 Agent Source: https://docs.layr8.io/build/go-sdk Copies the Claude Code skill definition file into the .claude/skills directory. This enables Claude Code to understand and assist in building Layr8 agents. ```bash mkdir -p .claude/skills cp /path/to/go-sdk/.claude/skills/build-layr8-agent.md .claude/skills/ ``` -------------------------------- ### DIDComm Plaintext Message Example (JSON) Source: https://docs.layr8.io/concepts/layr8 An example of a DIDComm plaintext message sent from one agent requesting data from another. It includes standard envelope fields and an application-specific body. ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "type": "https://example.com/protocols/orders/1.0/query", "from": "did:web:acme.layr8.io:purchasing", "to": ["did:web:widgets.layr8.io:catalog"], "created_time": 1706745600, "expires_time": 1706749200, "body": { "status": "open", "limit": 50 } } ``` -------------------------------- ### Sending Messages Source: https://docs.layr8.io/build/python-sdk Examples of sending fire-and-forget and request/response messages using the Layr8 SDK. ```APIDOC ## Sending Messages ### Description Send DIDComm messages using the `client.send` and `client.request` methods. ### Fire-and-Forget Send ```python await client.send(Message( type="https://didcomm.org/basicmessage/2.0/message", to=["did:web:partner-node:agent"], body={"content": "Hello!"}, )) ``` ### Request/Response Send ```python resp = await client.request( Message( type="https://layr8.io/protocols/echo/1.0/request", to=["did:web:partner-node:echo-agent"], body={"message": "ping"}, ), timeout=5.0, ) # resp is the correlated response, matched by thread ID ``` ``` -------------------------------- ### DIDComm Plaintext Response Message Example (JSON) Source: https://docs.layr8.io/concepts/layr8 An example of a DIDComm plaintext response message. It mirrors the structure of the request message but includes a 'thid' (thread ID) to link back to the original query and provides the requested data in the body. ```json { "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "type": "https://example.com/protocols/orders/1.0/results", "from": "did:web:widgets.layr8.io:catalog", "to": ["did:web:acme.layr8.io:purchasing"], "thid": "550e8400-e29b-41d4-a716-446655440000", "body": { "orders": [ {"id": "ORD-1042", "item": "Widget A", "quantity": 200}, {"id": "ORD-1043", "item": "Widget B", "quantity": 75} ] } } ``` -------------------------------- ### Install Claude Code Skill for Layr8 Agent Development Source: https://docs.layr8.io/build/python-sdk Copies the Claude Code skill for building Layr8 Python agents into the project's .claude/skills directory. This enables Claude Code to assist in agent development. ```bash mkdir -p .claude/skills cp /path/to/python-sdk/.claude/skills/build-layr8-agent-python.md .claude/skills/ ``` -------------------------------- ### Configure Layr8 Client Source: https://docs.layr8.io/build/go-sdk Initializes a new Layr8 client with configuration options. Node URL, API Key, and Agent DID are required. Fields can fall back to environment variables if not provided. ```go 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", }) ``` -------------------------------- ### Create and Run an Echo Agent in Go Source: https://docs.layr8.io/build/getting-started This Go code snippet demonstrates how to create a Layr8 client, register a handler for echo requests, connect to the Layr8 network, send a request to the echo agent, and process the response. It utilizes the 'go-sdk' and handles graceful shutdown on interrupt signals. ```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() } ``` -------------------------------- ### Create and Run an Echo Agent in Python Source: https://docs.layr8.io/build/getting-started This Python code snippet illustrates how to set up a Layr8 client, register a handler for echo requests using a decorator, connect to the network, send a request to the echo agent, and print the received reply. It uses the 'layr8' library and asynchronous programming patterns. ```python import asyncio from layr8 import Client, Config, Message client = Client(Config()) # Register as an echo protocol speaker — required to connect @client.handle("https://layr8.io/protocols/echo/1.0/request") async def echo(msg: Message) -> Message | None: print(f"received echo request: {msg.body}") return Message( type="https://layr8.io/protocols/echo/1.0/response", body=msg.body, ) async def main(): async with client: print(f"agent running as {client.did}") # Send a message to the sandbox echo agent resp = await client.request( Message( type="https://layr8.io/protocols/echo/1.0/request", to=["did:web:alice-sandbox.layr8.cloud:echo"], body={"message": "hello from my first agent!"}, ), timeout=15.0, ) print(f"Echo replied: {resp.body}") # Keep running — press Ctrl+C to exit print("listening for messages (Ctrl+C to exit)") await asyncio.Event().wait() asyncio.run(main()) ``` -------------------------------- ### Register and Send Messages with Layr8 Client (Go) Source: https://docs.layr8.io/faq Demonstrates how to register a handler for incoming messages and send outgoing messages using the Layr8 client library. The client abstracts away the complexities of encryption, authentication, and authorization, allowing developers to focus on passing plaintext JSON. ```go // Register a handler client.Handle("https://acme.com/protocols/orders/1.0/query", func(msg *layr8.Message) (*layr8.Message, error) { // msg.Body is your plaintext JSON — process it }) // Send a message client.Send(ctx, layr8.Message{ Type: "https://acme.com/protocols/orders/1.0/query", To: "did:web:widgets.layr8.io:catalog", Body: map[string]any{"status": "open"}, }) ``` -------------------------------- ### Nginx High Availability Setup for DID Webservers Source: https://docs.layr8.io/reference/hosting-dids-on-your-domain Configures Nginx to distribute traffic across multiple DID Webserver instances using an upstream block for high availability. It specifies failover and timeout settings. ```nginx upstream did_webservers { server did-webserver-1:4000 max_fails=3 fail_timeout=30s; server did-webserver-2:4000 max_fails=3 fail_timeout=30s; server did-webserver-3:4000 max_fails=3 fail_timeout=30s; } location /.well-known/did.json { proxy_pass http://did_webservers; proxy_next_upstream error timeout http_500 http_502 http_503; } ``` -------------------------------- ### Configure Layr8 Client in Python Source: https://docs.layr8.io/build/python-sdk Initializes the Layr8 client with configuration, including node URL, API key, and agent DID. Configuration can also be provided via environment variables. ```python from layr8 import Client, Config client = Client(Config( node_url="wss://your-node.node.layr8.io/plugin_socket/websocket", api_key="your-api-key", agent_did="did:web:your-node.node.layr8.io:my-agent", )) ``` -------------------------------- ### Cloudflare Page Rule for DID Document Caching Source: https://docs.layr8.io/reference/hosting-dids-on-your-domain An example of a Cloudflare Page Rule configuration to cache DID documents served from a specific URL pattern. It sets edge and browser cache TTLs to 1 hour. ```json { "url": "example.com/.well-known/did.json", "actions": { "cache_level": "cache_everything", "edge_cache_ttl": 3600, "browser_cache_ttl": 3600 } } ``` -------------------------------- ### Create and Run an Echo Agent in Node.js Source: https://docs.layr8.io/build/getting-started This Node.js code snippet shows how to initialize a Layr8 client, define a handler for echo requests, establish a connection, send a request to the echo agent, and display the response. It uses the '@layr8/sdk' and includes logic for graceful shutdown. ```javascript import { Layr8Client } from "@layr8/sdk"; const client = new Layr8Client(); // Register as an echo protocol speaker — required to connect client.handle( "https://layr8.io/protocols/echo/1.0/request", async (msg) => { console.log("received echo request:", msg.body); return { type: "https://layr8.io/protocols/echo/1.0/response", body: msg.body, }; }, ); await client.connect(); console.log(`agent running as ${client.did}`); // Send a message to the sandbox echo agent const resp = await client.request( { type: "https://layr8.io/protocols/echo/1.0/request", to: ["did:web:alice-sandbox.layr8.cloud:echo"], body: { message: "hello from my first agent!" }, }, { signal: AbortSignal.timeout(15_000) }, ); console.log("Echo replied:", resp.body); // Keep running — press Ctrl+C to exit console.log("listening for messages (Ctrl+C to exit)"); process.on("SIGINT", () => { client.close(); process.exit(0); }); ``` -------------------------------- ### Configuration Source: https://docs.layr8.io/build/python-sdk Details on how to configure the Layr8 client with node URL, API key, and agent DID. ```APIDOC ## Configuration ### Description Configure the Layr8 client using the `Config` object. Environment variables can be used as fallbacks. ### Code Example ```python from layr8 import Client, Config client = Client(Config( node_url="wss://your-node.node.layr8.io/plugin_socket/websocket", api_key="your-api-key", agent_did="did:web:your-node.node.layr8.io:my-agent", )) ``` ### Environment Variables Fallback - `LAYR8_NODE_URL` - `LAYR8_API_KEY` - `LAYR8_AGENT_DID` If `agent_did` is omitted, the node assigns an ephemeral DID on connect. ``` -------------------------------- ### Send Message Using Application Protocol in Go Source: https://docs.layr8.io/concepts/layr8 Illustrates sending a message of a specific type to a recipient using the Layr8 client. This abstracts away authentication, encryption, and delivery details. ```go client.Request(ctx, &layr8.Message{ Type: "https://acme.com/protocols/orders/1.0/create", To: []string{"did:web:partner-a.com:orders"}, Body: orderData, }) ``` -------------------------------- ### Troubleshoot Python SSL Certificate Verification Error on macOS Source: https://docs.layr8.io/build/getting-started Resolve SSL certificate verification errors in Python on macOS by installing the `certifi` package and setting the `SSL_CERT_FILE` environment variable to point to the correct certificate bundle. ```bash pip install certifi export SSL_CERT_FILE=$(python -c "import certifi; print(certifi.where())") ``` -------------------------------- ### Integrate Claude Code Skills for Layr8 Agent Development Source: https://docs.layr8.io/build/getting-started Set up Claude Code to help build Layr8 agents by cloning the relevant SDK repository and copying the agent building skill into your project's .claude/skills directory. This enables Claude to generate agents for you. ```go # 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/ ``` ```node # Clone the SDK repo (if you haven't already) git clone https://github.com/layr8/node-sdk.git /tmp/layr8-node-sdk # Copy the skill into your project mkdir -p .claude/skills cp /tmp/layr8-node-sdk/.claude/skills/build-layr8-agent-node.md .claude/skills/ ``` ```python # Clone the SDK repo (if you haven't already) git clone https://github.com/layr8/python-sdk.git /tmp/layr8-python-sdk # Copy the skill into your project mkdir -p .claude/skills cp /tmp/layr8-python-sdk/.claude/skills/build-layr8-agent-python.md .claude/skills/ ``` -------------------------------- ### Async Context Manager Source: https://docs.layr8.io/build/python-sdk How to use the client as an async context manager for managing connection lifecycle. ```APIDOC ## Async Context Manager ### Description Use the Layr8 client as an asynchronous context manager to automatically handle connection and disconnection. ### Code Example ```python import asyncio async with client: print(f"running as {client.did}") await asyncio.Event().wait() # run forever ``` ### Behavior - `async with client:` calls `client.connect()` upon entering the block. - `async with client:` calls `client.close()` upon exiting the block. ``` -------------------------------- ### Run Layr8 Agent in Different Languages Source: https://docs.layr8.io/build/getting-started Execute your Layr8 agent using the command-line interface specific to its programming language. This section covers running agents written in Go, Node.js, and Python. ```go go run . ``` ```node node index.mjs ``` ```python python main.py ``` -------------------------------- ### Layr8 Node Connection Consolidation (Diagram) Source: https://docs.layr8.io/concepts/layr8 Demonstrates how a single service endpoint can serve multiple DIDs hosted on the same node, leading to connection consolidation. This optimizes network traffic by using one connection for all DIDs on a node. ```text did:web:acme.layr8.io:sales ─────┐ │ one connection did:web:acme.layr8.io:purchasing ─┼────────────────────► acme.node.layr8.io │ did:web:acme.layr8.io:support ────┘ ``` -------------------------------- ### Set Environment Variables for Layr8 Agent Source: https://docs.layr8.io/build/getting-started Configure essential environment variables required to run a Layr8 agent. These include the node URL, API key, and an optional agent DID for stable identity. Ensure these are correctly set before running your agent. ```bash 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" ``` -------------------------------- ### PostgreSQL Query via Local Proxy Source: https://docs.layr8.io/concepts/layr8 Demonstrates how a user can query a remote PostgreSQL database as if it were local, using a proxy agent. The process involves the local agent encapsulating the SQL query into a DIDComm message, which then travels through Layr8's secure node pipeline for encryption, authentication, authorization, and auditing before reaching the remote database agent. ```plaintext psql -h localhost -p 5433 ``` -------------------------------- ### Configure Go Private Repository Access for GitHub Source: https://docs.layr8.io/build/getting-started Address 'could not read Username for 'https://github.com'' errors in Go by setting the `GOPRIVATE` environment variable to include Layr8's private repositories and configuring Git to use SSH for GitHub access. ```bash export GOPRIVATE=github.com/layr8/* git config --global url."git@github.com:".insteadOf "https://github.com/" ``` -------------------------------- ### DID Webserver Cache TTL Configuration Source: https://docs.layr8.io/reference/hosting-dids-on-your-domain Demonstrates how to adjust the cache Time-To-Live (TTL) for the DID Webserver by setting the CACHE_TTL environment variable. This allows for shorter TTLs for frequently changing DIDs or longer TTLs for stable ones. ```shell # Shorter TTL for frequently changing DIDs CACHE_TTL=300 ./did-webserver # 5 minutes # Longer TTL for stable DIDs CACHE_TTL=86400 ./did-webserver # 24 hours ``` -------------------------------- ### Layr8 Node Peer-to-Peer Connection Flow (Diagram) Source: https://docs.layr8.io/concepts/layr8 Illustrates the step-by-step process of how a sender's node connects to a recipient's node to deliver a message. It highlights DID document resolution, connection establishment, and message delivery. ```text Sender's Node Recipient's Node │ │ │ 1. Resolve recipient DID Document │ │ → find service endpoint │ │ │ │ 2. Connect (gRPC or HTTPS) │ │─────────────────────────────────────────────► │ │ │ │ 3. Deliver encrypted JWE │ │═════════════════════════════════════════════► │ │ │ │ 4. Same connection, different DID │ │═════════════════════════════════════════════► │ │ │ ``` -------------------------------- ### Verify DID Resolution and Messaging Source: https://docs.layr8.io/reference/hosting-dids-on-your-domain Verify that your new DID is correctly resolving and that messaging is functioning. This involves using cURL to fetch the DID document and Layr8 tools to resolve the DID and send test messages. ```bash # Resolve your new DID curl https://example.com/.well-known/did.json # Test with Layr8 tools layr8 did resolve did:web:example.com # Verify messaging works layr8 message send --to did:web:example.com --type test ``` -------------------------------- ### Handle Application Protocol Messages in Go Source: https://docs.layr8.io/concepts/layr8 Demonstrates how to register a handler for a specific message type within an application protocol using the Layr8 library. This function processes incoming messages of a defined type. ```go client.Handle("https://acme.com/protocols/procurement/1.0/rfq", func(msg *layr8.Message) (*layr8.Message, error) { // process the RFQ... }) ``` -------------------------------- ### Configure Nginx for Multi-Domain Hosting Source: https://docs.layr8.io/reference/hosting-dids-on-your-domain Set up Nginx to host multiple domains on a single webserver, directing requests for /.well-known/did.json to the DID Webserver. This configuration allows for efficient management of multiple DIDs. ```nginx server { server_name example.com example.org example.net; location /.well-known/did.json { proxy_pass http://localhost:4000; proxy_set_header Host $host; } } ```