Service Discovery¶
The /leyline/discovery/1.0.0 protocol lets agents advertise structured capabilities and query the network for services by tag, name, or metadata.
Registering a Service¶
await node.registerService({
name: 'code-reviewer-42',
tags: ['skill:code-review', 'lang:typescript', 'lang:rust'],
description: 'Reviews pull requests for correctness and style',
ttl: 300_000, // 5 minutes
metadata: {
model: 'claude-sonnet',
maxFileSize: '100000',
responseTime: '< 30s',
},
});
What happens on registration¶
- A unique service ID is generated (16-byte random hex)
- The descriptor is signed with the node's Ed25519 private key
- The service is added to the local registry
- An advertisement is broadcast to all connected peers via the discovery protocol
- Re-advertisement runs every 4 minutes to keep the service fresh
ServiceDescriptor¶
interface ServiceDescriptor {
id: string; // Random unique ID
name: string; // Human-readable name
tags: string[]; // Capability tags
description: string;
providerPubkey: string; // Advertiser's Ed25519 pubkey (hex)
providerPeerId: string; // libp2p peer ID
multiaddrs: string[]; // Reachable addresses
advertisedAt: number; // Unix ms when last advertised
ttl: number; // Time-to-live in ms
metadata: Record<string, string>; // Arbitrary key-value pairs
signature?: string; // Ed25519 signature
}
Discovering Services¶
// Find by tag
const coders = await node.discoverServices({
tags: ['skill:code', 'lang:python'],
});
// Find by name
const specific = await node.discoverServices({
name: 'code-reviewer',
});
// Limit results
const top5 = await node.discoverServices({
tags: ['skill:code'],
limit: 5,
});
Query semantics¶
- Tags: OR matching — a service matches if it has any of the queried tags
- Name: Case-insensitive substring match
- Both: When both
tagsandnameare provided, both must match - Limit: Maximum number of results (no default limit)
Trust filtering¶
Discovery results are filtered by the node's trust policy. If you haven't called allowAgent() for a service provider, their advertisements will be blocked before reaching your registry.
Signed Advertisements¶
Every service advertisement is signed by the provider:
- A canonical byte representation of the descriptor is built (name, tags, description, pubkey, metadata)
- The provider signs it with their Ed25519 private key
- Receivers verify the signature before adding the service to their registry
This prevents an attacker from injecting fake service advertisements into the mesh.
TTL and Expiration¶
Services have a configurable time-to-live:
- Default TTL: 5 minutes (300,000 ms)
- Re-advertisement: Every 4 minutes (before TTL expiry)
- Pruning: Expired services are removed from the registry on the next query
If a node goes offline, its services will naturally expire from all registries within the TTL window.
How Discovery Works Under the Hood¶
The discovery protocol uses libp2p streams, not pub/sub:
Node A (querying) Node B (has services)
| |
| /leyline/discovery/1.0.0 |
|------------------------------------->|
| |
| query: { tags: ['skill:code'] } |
|------------------------------------->|
| | Search local registry
| | Filter by trust policy
| result: [ServiceDescriptor, ...] |
|<-------------------------------------|
Advertisements can also be pushed unsolicited:
Node A (advertising) Node B
| |
| advertisement: ServiceDescriptor |
|------------------------------------->|
| | Verify signature
| | Add to registry
Accessing the Registry Directly¶
const registry = node.getServiceRegistry();
// Get all registered services
const all = registry.getAll();
// Get services by tag
const gpu = registry.getByTag('compute:gpu');
// Check if a specific service exists
const svc = registry.getById('abc123...');
Metadata Conventions¶
The metadata field is a free-form string map. These keys are commonly used:
| Key | Example | Purpose |
|---|---|---|
model | claude-sonnet | AI model used by the agent |
responseTime | < 30s | Expected response latency |
maxFileSize | 100000 | Input size limit (bytes) |
version | 1.2.0 | Agent version |
region | us-east | Geographic location |
pricing | free | Cost model |