Skip to Content
Naylence Docs are in active development. Share feedback in Discord.
ReferenceConfiguration

Configuration

This guide covers how to configure Naylence components. The SDK provides pre-built configuration objects that work out of the box while allowing customization through environment variables and configuration profiles.

Overview

Naylence uses a profile-based configuration system that simplifies setup while providing flexibility:

  1. Pre-built configs - The SDK exports ready-to-use configurations for sentinels, nodes (agents), and clients
  2. Configuration profiles - Each aspect of the system (security, storage, delivery, etc.) can be configured via named profiles
  3. Environment variable interpolation - All profiles support ${env:VAR_NAME:default} syntax for runtime customization

This approach means you can start with zero configuration and gradually customize as your requirements grow.

Pre-built Configurations

Both SDKs provide three configuration objects that you can use directly:

ConfigUse Case
SENTINEL_CONFIGFor standalone sentinels that accept connections
NODE_CONFIGFor agents that connect to a sentinel
CLIENT_CONFIGFor clients that invoke agents
import { SENTINEL_CONFIG, NODE_CONFIG, CLIENT_CONFIG } from '@naylence/agent-sdk'; // Start a sentinel with default configuration const sentinel = new Sentinel(SENTINEL_CONFIG); await sentinel.start(); // Create an agent using the node config const agent = new MyAgent(NODE_CONFIG); await agent.start(); // Create a client const client = new Client(CLIENT_CONFIG); await client.start();
from naylence.agent import SENTINEL_CONFIG, NODE_CONFIG, CLIENT_CONFIG from naylence.agent import Sentinel, BaseAgent, Client # Start a sentinel with default configuration sentinel = Sentinel(SENTINEL_CONFIG) await sentinel.start() # Create an agent using the node config agent = MyAgent(NODE_CONFIG) await agent.start() # Create a client client = Client(CLIENT_CONFIG) await client.start()

The pre-built configs include sensible defaults and support environment variable interpolation, so you can customize them at runtime without changing code.

Configuration Profiles

Naylence uses profiles to configure different aspects of the system. Each profile type has a default value that can be overridden via environment variables.

Profile Types

ProfilePurposeDefault
SecurityMessage signing and encryptionopen
AdmissionConnection authenticationopen (client/node), none (sentinel)
StorageState and message persistencememory
DeliveryMessage delivery guaranteesat-most-once
Node IdentityIdentity management (TypeScript only)default

How Profiles Work

Each configuration section uses a profile reference that looks like this:

security: type: SecurityProfile profile: "${env:FAME_SECURITY_PROFILE:open}"

This means:

  1. Look for FAME_SECURITY_PROFILE environment variable
  2. If not set, use open as the default
  3. The runtime loads the corresponding profile implementation

Available Profile Values

Security Profiles

ProfileDescription
openNo message signing, encryption, or authorization (development only)
overlayMessage signing with OAuth2 JWT authorization
overlay-callbackOverlay with HMAC-based reverse authorization (callback flow)
strict-overlayFull X.509 certificate chain signing with JWKS verification
gatedOAuth2 authorization without message signing
gated-callbackGated with HMAC-based reverse authorization

Admission Profiles

ProfileDescription
openDirect WebSocket connection without authentication
none / noopNo outbound connections
directOAuth2 client credentials over WebSocket
direct-pkceOAuth2 PKCE flow over WebSocket (browser-friendly)
direct-httpOAuth2 client credentials over HTTP
direct-inpageIn-page channel connection (same-origin browser)
welcomeWelcome service with OAuth2 client credentials
welcome-pkceWelcome service with OAuth2 PKCE flow

Storage Profiles

ProfileDescription
memoryIn-memory storage (data lost on restart)
indexeddbBrowser IndexedDB storage (browser environments only)
sqliteSQLite file-based storage (Node.js only)
encrypted-sqliteSQLite with AES-256 encryption (Node.js only)

Delivery Profiles

ProfileDescription
at-most-onceFire-and-forget, no retries
at-least-onceRetry until acknowledged (with configurable backoff)

Config Structure

The configuration is a JSON/dictionary object with a node section containing the component settings:

// Structure of SENTINEL_CONFIG export const SENTINEL_CONFIG = { plugins: ['@naylence/runtime', '@naylence/agent-sdk'], node: { type: 'Sentinel', id: '${env:FAME_NODE_ID:}', public_url: '${env:FAME_PUBLIC_URL:}', listeners: [ { type: 'HttpListener', port: 8000 }, { type: 'WebSocketListener', port: 8000 }, ], requested_logicals: ['fame.fabric'], security: { type: 'SecurityProfile', profile: '${env:FAME_SECURITY_PROFILE:open}', }, admission: { type: 'AdmissionProfile', profile: '${env:FAME_ADMISSION_PROFILE:none}', }, identity_policy: { type: 'NodeIdentityPolicyProfile', profile: '${env:FAME_NODE_IDENTITY_PROFILE:default}', }, storage: { type: 'StorageProfile', profile: '${env:FAME_STORAGE_PROFILE:memory}', }, delivery: { type: 'DeliveryProfile', profile: '${env:FAME_DELIVERY_PROFILE:at-most-once}', }, }, };
# Structure of SENTINEL_CONFIG SENTINEL_CONFIG = { "node": { "type": "Sentinel", "id": "${env:FAME_NODE_ID:}", "public_url": "${env:FAME_PUBLIC_URL:}", "listeners": [ {"type": "HttpListener", "port": 8000}, {"type": "WebSocketListener", "port": 8000}, ], "requested_logicals": ["fame.fabric"], "security": { "type": "SecurityProfile", "profile": "${env:FAME_SECURITY_PROFILE:open}", }, "admission": { "type": "AdmissionProfile", "profile": "${env:FAME_ADMISSION_PROFILE:none}", }, "storage": { "type": "StorageProfile", "profile": "${env:FAME_STORAGE_PROFILE:memory}", }, "delivery": { "type": "DeliveryProfile", "profile": "${env:FAME_DELIVERY_PROFILE:at-most-once}", }, }, }

Key Differences by Config Type

SettingSENTINEL_CONFIGNODE_CONFIGCLIENT_CONFIG
typeSentinelNode(implicit)
listenersHTTP + WebSocket on 8000NoneNone
admission defaultnoneopenopen
idOptionalOptionalN/A
public_urlOptionalOptionalN/A

Custom Configuration

You can extend or modify the pre-built configs for specific needs:

import { SENTINEL_CONFIG } from '@naylence/agent-sdk'; // Create a custom config based on SENTINEL_CONFIG const customConfig = { ...SENTINEL_CONFIG, node: { ...SENTINEL_CONFIG.node, listeners: [ { type: 'HttpListener', port: 9000 }, // Custom port { type: 'WebSocketListener', port: 9000 }, ], // Add telemetry configuration telemetry: { type: 'OpenTelemetryTraceEmitter', service_name: 'my-service', endpoint: '${env:OTEL_ENDPOINT:}', }, }, }; const sentinel = new Sentinel(customConfig);
from naylence.agent import SENTINEL_CONFIG # Create a custom config based on SENTINEL_CONFIG custom_config = { **SENTINEL_CONFIG, "node": { **SENTINEL_CONFIG["node"], "listeners": [ {"type": "HttpListener", "port": 9000}, # Custom port {"type": "WebSocketListener", "port": 9000}, ], # Add telemetry configuration "telemetry": { "type": "OpenTelemetryTraceEmitter", "service_name": "my-service", "endpoint": "${env:OTEL_ENDPOINT:}", }, }, } sentinel = Sentinel(custom_config)

YAML Configuration Files

For complex configurations, you can use YAML files instead of inline configs:

config/sentinel-config.yml
node: type: Sentinel id: "${env:FAME_NODE_ID:}" public_url: "${env:FAME_PUBLIC_URL:}" listeners: - type: HttpListener port: 8000 - type: WebSocketListener port: 8000 requested_logicals: - fame.fabric security: type: SecurityProfile profile: "${env:FAME_SECURITY_PROFILE:open}" admission: type: AdmissionProfile profile: "${env:FAME_ADMISSION_PROFILE:none}" storage: type: StorageProfile profile: "${env:FAME_STORAGE_PROFILE:memory}" delivery: type: DeliveryProfile profile: "${env:FAME_DELIVERY_PROFILE:at-most-once}"

Environment Variable Reference

All environment variables use the FAME_ prefix. This section provides a comprehensive reference of supported variables.

Connection Variables

VariableDescriptionExample
FAME_DIRECT_ADMISSION_URLWebSocket URL to connect to a sentinelws://sentinel:8000/fame/v1/attach/ws/downstream
FAME_PEER_WS_URLWebSocket URL for sentinel peeringws://peer:8000/fame/v1/attach/ws/peer
FAME_PUBLIC_URLPublic URL for this nodewss://my-service.example.com

Node Identity Variables

VariableDescriptionDefault
FAME_NODE_IDUnique identifier for this nodeAuto-generated
FAME_NODE_IDENTITY_PROFILENode identity management profile (TS only)default

Profile Variables

VariableDescriptionDefaultValues
FAME_SECURITY_PROFILESecurity profile to useopenopen, overlay, overlay-callback, strict-overlay, gated, gated-callback
FAME_ADMISSION_PROFILEAdmission profile to useopen/noneopen, none, direct, direct-pkce, direct-http, direct-inpage, welcome, welcome-pkce
FAME_STORAGE_PROFILEStorage profile to usememorymemory, indexeddb, sqlite, encrypted-sqlite
FAME_DELIVERY_PROFILEDelivery profile to useat-most-onceat-most-once, at-least-once

Storage Variables

VariableDescriptionRequired For
FAME_STORAGE_DB_DIRECTORYDirectory for SQLite database filessqlite, encrypted-sqlite
FAME_STORAGE_MASTER_KEY32-byte hex encryption keyencrypted-sqlite

Security: The FAME_STORAGE_MASTER_KEY should be a secure 32-byte (64 hex character) key. Generate one using:

openssl rand -hex 32

Never commit this key to version control.

Authentication Variables

Used with direct, direct-pkce, welcome, and welcome-pkce admission profiles:

VariableDescriptionUsed With
FAME_ADMISSION_TOKEN_URLOAuth2 token endpoint URLdirect, direct-pkce, welcome, welcome-pkce
FAME_ADMISSION_CLIENT_IDOAuth2 client IDAll OAuth2 profiles
FAME_ADMISSION_CLIENT_SECRETOAuth2 client secretdirect, welcome (not PKCE)
FAME_ADMISSION_AUTHORIZE_URLOAuth2 authorization endpointdirect-pkce, welcome-pkce
FAME_ADMISSION_REDIRECT_URLOAuth2 redirect URIdirect-pkce, welcome-pkce
FAME_ADMISSION_SERVICE_URLWelcome service URLwelcome, welcome-pkce
FAME_JWT_AUDIENCEJWT audience claimAll OAuth2 profiles
FAME_ADMISSION_LOGIN_HINT_PARAMLogin hint parameter namePKCE profiles (default: login_hint)
FAME_ADMISSION_CODE_CHALLENGE_METHODPKCE code challenge methodPKCE profiles (default: S256)

Security Variables

Used with security profiles for message signing and authorization:

VariableDescriptionUsed With
FAME_HMAC_SECRETHMAC secret for JWT signingoverlay-callback, gated-callback
FAME_JWT_TRUSTED_ISSUERTrusted JWT issueroverlay, gated, strict-overlay
FAME_JWT_ALGORITHMJWT signing algorithmoverlay, gated (default: RS256)
FAME_JWKS_URLJWKS endpoint for key verificationstrict-overlay
FAME_DEFAULT_ENCRYPTION_LEVELDefault message encryption levelstrict-overlay (default: channel)
FAME_JWT_REVERSE_AUTH_TRUSTED_ISSUERIssuer for reverse auth JWTsoverlay-callback, gated-callback
FAME_JWT_REVERSE_AUTH_AUDIENCEAudience for reverse auth JWTsoverlay-callback, gated-callback

Debugging Variables

VariableDescriptionValues
FAME_LOG_LEVELLogging verbosityDEBUG, INFO, WARNING, ERROR
FAME_SHOW_ENVELOPESLog message envelopestrue, false

Plugin Variables (TypeScript Only)

VariableDescriptionDefault
FAME_PLUGINSComma-separated list of plugins to load@naylence/runtime

The TypeScript SDK automatically adds @naylence/agent-sdk to FAME_PLUGINS when imported.

Telemetry Variables

Used when configuring OpenTelemetry:

VariableDescription
FAME_TELEMETRY_OTLP_ENDPOINTOTLP collector endpoint
FAME_TELEMETRY_TOKEN_URLToken URL for telemetry auth
FAME_TELEMETRY_CLIENT_IDClient ID for telemetry auth
FAME_TELEMETRY_CLIENT_SECRETClient secret for telemetry auth
FAME_TELEMETRY_JWT_AUDIENCEJWT audience for telemetry

Delivery Variables

Used with at-least-once delivery profile for retry configuration:

VariableDescriptionDefault
FAME_DELIVERY_MAX_RETRIESMaximum retry attempts5 (sender), 6 (receiver)
FAME_DELIVERY_BASE_DELAY_MSInitial retry delay in milliseconds1000 (sender), 100 (receiver)
FAME_DELIVERY_MAX_DELAY_MSMaximum retry delay in milliseconds10000 (sender), 2000 (receiver)
FAME_DELIVERY_JITTER_MSRandom jitter added to delays200 (sender), 50 (receiver)
FAME_DELIVERY_BACKOFF_FACTORExponential backoff multiplier2.0 (sender), 1.8 (receiver)

Flow Control Variables

VariableDescriptionDefault
FAME_FLOW_CONTROLFlow control buffer size (0 = disabled)(varies)

Configuration Patterns

Development Setup

Minimal configuration for local development:

# No env vars needed - defaults work out of the box # Optionally enable debug logging: export FAME_LOG_LEVEL=DEBUG export FAME_SHOW_ENVELOPES=true

Distributed Setup

For agents connecting to a remote sentinel:

# Agent/Client connecting to sentinel export FAME_DIRECT_ADMISSION_URL=ws://sentinel:8000/fame/v1/attach/ws/downstream

Persistent Storage Setup

For agents that need to persist state:

export FAME_STORAGE_PROFILE=encrypted-sqlite export FAME_STORAGE_MASTER_KEY=$(openssl rand -hex 32) export FAME_STORAGE_DB_DIRECTORY=./data

Production Setup

Recommended configuration for production:

# Security export FAME_SECURITY_PROFILE=overlay export FAME_ADMISSION_PROFILE=direct export FAME_ADMISSION_TOKEN_URL=https://auth.example.com/oauth/token export FAME_ADMISSION_CLIENT_ID=your-client-id export FAME_ADMISSION_CLIENT_SECRET=your-client-secret # Storage export FAME_STORAGE_PROFILE=encrypted-sqlite export FAME_STORAGE_MASTER_KEY=<secure-32-byte-hex-key> export FAME_STORAGE_DB_DIRECTORY=/var/data/naylence # Delivery export FAME_DELIVERY_PROFILE=at-least-once # Connection (for agents/clients) export FAME_DIRECT_ADMISSION_URL=wss://sentinel.example.com/fame/v1/attach/ws/downstream

Docker Compose Pattern

Using .env files with Docker Compose:

docker-compose.yml
services: sentinel: image: naylence/agent-sdk-node:0.3.5 env_file: - config/.env.sentinel # ... agent: image: naylence/agent-sdk-node:0.3.5 env_file: - config/.env.agent # ...
config/.env.sentinel
FAME_STORAGE_PROFILE=encrypted-sqlite FAME_STORAGE_MASTER_KEY=${FAME_STORAGE_MASTER_KEY} FAME_STORAGE_DB_DIRECTORY=/work/data/sentinel
config/.env.agent
FAME_DIRECT_ADMISSION_URL=ws://sentinel:8000/fame/v1/attach/ws/downstream FAME_STORAGE_PROFILE=encrypted-sqlite FAME_STORAGE_MASTER_KEY=${FAME_STORAGE_MASTER_KEY} FAME_STORAGE_DB_DIRECTORY=/work/data/agent

Browser Environment

For browser clients, set environment variables via a global object:

<script> window.__ENV__ = { FAME_DIRECT_ADMISSION_URL: "ws://localhost:8000/fame/v1/attach/ws/downstream", FAME_LOG_LEVEL: "WARNING", FAME_SHOW_ENVELOPES: "false" }; </script>

Or in a separate file:

public/env.js
window.__ENV__ = window.__ENV__ || {}; window.__ENV__.FAME_DIRECT_ADMISSION_URL = "ws://localhost:8000/fame/v1/attach/ws/downstream"; window.__ENV__.FAME_LOG_LEVEL = "WARNING";

Best Practices

  1. Start with defaults - The pre-built configs work for most development scenarios
  2. Use environment variables - Never hardcode secrets or URLs in code
  3. Use .env.example files - Document required variables with placeholders
  4. Separate configs per component - Each sentinel/agent/client should have its own env file
  5. Secure production secrets - Use secret management tools, never commit keys
  6. Enable at-least-once delivery for reliability - Combined with persistent storage for crash recovery
  7. Use overlay security in production - Provides message signing and encryption
Last updated on