Skip to content

DNS Resolution

AGENIUM uses DNS to discover agents by name and resolve them to endpoints.

Overview

DNS resolution translates an agent:// URI into connection details:

agent://search


┌─────────────────────┐
│  DNS Resolver       │
│  (client-side)      │
└──────────┬──────────┘

           │ HTTPS GET /api/agents/search

┌─────────────────────┐
│  DNS Server         │
│  AGENIUM DNS (185.204.169.26:3000)
└──────────┬──────────┘

           │ 200 OK

{
  name: "search",
  publicKey: "sLCk...",
  endpoint: "https://search.agenium.net:8443",
  host: "search.agenium.net",
  port: 8443,
  capabilities: ["messaging"],
  ttl: 3600
}

DNS Server

The default DNS server is:

185.204.169.26 (port 3000, HTTP)

You can configure a custom DNS server:

typescript
const agent = createAgent('alice', {
  dnsServer: 'my-dns-server.com'  // Just the address
});

Resolution Process

1. Parse URI

typescript
import { parseAgentURI } from 'agenium';

const parsed = parseAgentURI('agent://bob');
// { name: 'bob' }

2. Check Cache

Before hitting DNS, check local cache:

typescript
const cached = cache.get('bob');
if (cached && Date.now() < cached.expiresAt) {
  return cached;
}

Cache entries expire based on TTL (default: 3600s = 1 hour).

3. DNS Lookup

typescript
const response = await fetch(
  `https://185.204.169.26:3000/agent/lookup/bob`
);

const data = await response.json();

4. Validate Response

typescript
if (!data.success) {
  throw new Error(`DNS lookup failed: ${data.error.message}`);
}

if (!data.agent.publicKey) {
  throw new Error('Missing public key in DNS response');
}

5. Parse Endpoint

typescript
const url = new URL(data.agent.endpoint);
const host = url.hostname;
const port = parseInt(url.port || '443');

6. Cache Result

typescript
cache.set(name, {
  ...data.agent,
  host,
  port,
  resolvedAt: Date.now(),
  expiresAt: Date.now() + (data.agent.ttl * 1000)
});

DNS API

Lookup Request

GET /api/agents/{name}
Host: 185.204.169.26:3000

Lookup Response

json
{
  "success": true,
  "agent": {
    "name": "search",
    "publicKey": "sLCkXG4FN7N4gH5K...",
    "endpoint": "https://search.agenium.net:8443",
    "description": "AGENIUM search engine",
    "capabilities": ["messaging", "streaming"],
    "protocolVersions": ["1.0"],
    "ttl": 3600,
    "updatedAt": 1703260800
  }
}

Error Response

json
{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Agent 'unknown' not found in registry"
  }
}

Error Codes

CodeDescription
NOT_FOUNDAgent not registered
TIMEOUTDNS server timeout
INVALID_NAMEInvalid agent name format
NETWORK_ERRORNetwork connectivity issue
SERVER_ERRORDNS server internal error

Using the Resolver

Basic Usage

typescript
import { DNSResolver } from 'agenium';

const resolver = new DNSResolver({
  server: '185.204.169.26',
  port: 3000,
  useHttps: false,
  timeoutMs: 10000
});

const result = await resolver.resolve('agent://bob');

if (result.ok) {
  console.log('Endpoint:', result.agent.endpoint);
  console.log('Public Key:', result.agent.publicKey);
} else {
  console.error('Error:', result.error.message);
}

Custom Configuration

typescript
const resolver = new DNSResolver({
  server: 'custom-dns.example.com',
  port: 443,
  useHttps: true,
  timeoutMs: 5000,
  defaultTtlSeconds: 7200  // 2 hours
});

Singleton Pattern

AGENIUM uses a global resolver instance:

typescript
import { getResolver, resetResolver } from 'agenium';

// Get the global resolver (uses default config)
const resolver = getResolver();

// Or get with custom config (creates if doesn't exist)
const resolver2 = getResolver({
  server: 'custom-dns.com',
  port: 3000
});

// Reset to default
resetResolver();

Registration

To register your agent in DNS:

1. Prepare Registration Data

typescript
import { sign } from '@noble/ed25519';

const registrationData = {
  name: 'myagent',
  publicKey: agent.getIdentity().publicKey,
  endpoint: 'https://my-server.com:8443',
  description: 'My awesome agent',
  capabilities: ['messaging'],
  protocolVersions: ['1.0']
};

// Sign the registration
const message = JSON.stringify(registrationData);
const signature = await sign(message, privateKey);

2. Submit to DNS Server

typescript
const response = await fetch(
  'http://185.204.169.26:3000/agent/lookup/register',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      ...registrationData,
      signature: Buffer.from(signature).toString('base64')
    })
  }
);

const result = await response.json();
if (result.success) {
  console.log('Registration successful!');
}

3. Verification

The DNS server verifies:

  • Name uniqueness
  • Public key format
  • Signature validity
  • Endpoint reachability (optional health check)

Caching

Client-Side Cache

AGENIUM caches DNS lookups to reduce latency:

typescript
// First lookup: hits DNS server
const result1 = await resolver.resolve('agent://bob');  // ~100ms

// Second lookup: served from cache
const result2 = await resolver.resolve('agent://bob');  // ~1ms

Cache Invalidation

Cache entries expire based on TTL:

typescript
const agent = cache.get('bob');
if (Date.now() > agent.expiresAt) {
  // Cache expired, re-resolve
  cache.delete('bob');
}

Manual Cache Control

typescript
// Clear entire cache
resolver.clearCache();

// Invalidate specific entry
resolver.invalidate('bob');

// Prune expired entries
const pruned = resolver.pruneCache();
console.log('Pruned', pruned, 'expired entries');

DNS Server Implementation

AGENIUM includes a DNS server for testing:

typescript
import { createDNSServer } from 'agenium';

const dnsServer = createDNSServer({
  port: 3000,
  storage: './dns-data.json'
});

await dnsServer.start();
console.log('DNS server listening on port 3000');

Register an Agent

typescript
await dnsServer.register({
  name: 'alice',
  publicKey: 'sLCkXG4FN7N4gH5K...',
  endpoint: 'https://localhost:8443',
  capabilities: ['messaging'],
  protocolVersions: ['1.0']
});

Lookup an Agent

typescript
const agent = await dnsServer.lookup('alice');
console.log(agent);

Security Considerations

Public Key Pinning

Always verify the public key matches DNS:

typescript
const resolved = await resolver.resolve('agent://bob');
const handshakeKey = handshakeResponse.agentId.publicKey;

if (resolved.agent.publicKey !== handshakeKey) {
  throw new Error('Public key mismatch - possible MITM attack!');
}

Transport Security

The default DNS server uses HTTP (not HTTPS) on port 3000. In production, consider using HTTPS-enabled DNS servers:

typescript
// Default (HTTP on port 3000)
const resolver = new DNSResolver({
  server: '185.204.169.26',
  port: 3000,
  useHttps: false
});

// Production with HTTPS
const resolver = new DNSResolver({
  server: 'secure-dns.example.com',
  port: 443,
  useHttps: true
});

Cache Poisoning

Validate DNS responses before caching:

typescript
function validateDNSResponse(data: unknown): boolean {
  // Check required fields
  if (!data.agent?.name || !data.agent?.publicKey) {
    return false;
  }
  
  // Verify endpoint is HTTPS
  if (!data.agent.endpoint.startsWith('https://')) {
    return false;
  }
  
  // Verify TTL is reasonable
  if (data.agent.ttl < 60 || data.agent.ttl > 86400) {
    return false;
  }
  
  return true;
}

CLI Usage

The AGENIUM CLI includes DNS resolution:

bash
# Resolve an agent URI
agenium resolve agent://search

# Output:
# ✅ Resolved: search
#   Endpoint: https://search.agenium.net:8443
#   Host:     search.agenium.net:8443
#   PubKey:   sLCkXG4FN7N4gH5K...
#   Caps:     messaging, streaming

See Also

Released under the MIT License.