Transport Layer
AGENIUM uses HTTP/2 over mutual TLS (mTLS) for secure agent-to-agent communication.
Overview
The transport layer provides:
- HTTP/2: Multiplexing, server push, header compression
- TLS 1.3: Encryption and authentication
- Mutual TLS: Both parties verify each other's identity
- Certificate Pinning: Ed25519 public keys embedded in certs
Architecture
┌─────────────────────────────────────────┐
│ Application Layer │
│ (Requests, Responses, Events) │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Protocol Layer │
│ (Frame serialization, validation) │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Transport Layer │
│ • HTTP/2 multiplexing │
│ • TLS 1.3 encryption │
│ • mTLS authentication │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Network (TCP/IP) │
└─────────────────────────────────────────┘HTTP/2 Features
Multiplexing
Multiple streams over a single connection:
┌─────────────────────┐
│ TCP Connection │
│ │
│ Stream 1: Request │───▶ POST /message
│ Stream 2: Request │───▶ POST /message
│ Stream 3: Response │◀─── 200 OK
│ Stream 4: Request │───▶ POST /message
│ Stream 5: Response │◀─── 200 OK
│ │
└─────────────────────┘Benefits:
- No head-of-line blocking
- Better resource utilization
- Lower latency
Configuration
typescript
const client = createClient({
maxConnectionsPerHost: 4,
maxStreamsPerConnection: 100,
connectionTimeout: 10000,
requestTimeout: 30000
});Mutual TLS (mTLS)
Both client and server authenticate each other using X.509 certificates.
Certificate Structure
┌───────────────────────────────────────┐
│ Agent Certificate │
├───────────────────────────────────────┤
│ Subject: CN=alice │
│ Issuer: CN=alice-ca │
│ Valid: 2026-01-01 to 2027-01-01 │
│ Public Key: Ed25519 │
│ • sLCkXG4FN7N4gH5K... │
└───────────────────────────────────────┘Certificate Generation
AGENIUM automatically generates certificates:
typescript
import { initializeKeys, initializeCA, createAgentCert } from 'agenium';
const dataDir = './data';
// 1. Generate keys (Ed25519)
const keys = initializeKeys(dataDir);
// - Agent signing key
// - TLS certificate key
// 2. Create self-signed CA
const ca = initializeCA('alice', dataDir);
// 3. Generate agent certificate
const cert = createAgentCert(
'alice',
keys.tlsKeys.publicKey,
ca
);Key Storage
Keys are stored in PEM format:
data/
├── agent-signing-key.pem # Ed25519 for protocol signatures
├── agent-signing-key.pub
├── tls-key.pem # Ed25519 for TLS
├── tls-key.pub
├── ca-cert.pem # Self-signed CA
├── ca-key.pem
└── agent-cert.pem # Agent certificateTLS Handshake
Client (Alice) Server (Bob)
│ │
├─── ClientHello ───────────────▶│
│ (TLS 1.3, ciphersuites) │
│ │
│◀── ServerHello ────────────────┤
│ (chosen ciphersuite) │
│◀── Certificate ────────────────┤
│ (Bob's cert + CA) │
│◀── CertificateRequest ─────────┤
│ │
├─── Certificate ───────────────▶│
│ (Alice's cert + CA) │
├─── Finished ──────────────────▶│
│ │
│◀── Finished ───────────────────┤
│ │
│ [Encrypted Application Data]│Verification Steps
- Verify certificate chain: Cert signed by CA
- Verify not expired: Check validity period
- Extract public key: Ed25519 from cert
- Pin verification: Match against DNS-resolved key
Transport Client
Creating a Client
typescript
import { createClient } from 'agenium';
const client = createClient({
cert: agentCert,
ca: caInfo,
maxConnectionsPerHost: 5,
connectionTimeout: 10000,
requestTimeout: 30000,
idleTimeout: 60000
});
client.start();Making Requests
typescript
const response = await client.request(
'bob.example.com',
8443,
{
method: 'POST',
path: '/message',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(messageFrame)
}
);
console.log('Status:', response.status);
console.log('Body:', response.body.toString());Connection Pooling
The client maintains a pool of connections:
typescript
// First request: creates connection
await client.request('bob.example.com', 8443, { ... }); // ~100ms
// Second request: reuses connection
await client.request('bob.example.com', 8443, { ... }); // ~10msTimeouts
Multiple timeout levels:
typescript
{
connectionTimeout: 10000, // TLS handshake timeout
requestTimeout: 30000, // Individual request timeout
idleTimeout: 60000 // Close idle connections
}Transport Server
Creating a Server
typescript
import { createServer } from 'agenium';
const server = createServer({
port: 8443,
host: '0.0.0.0',
cert: agentCert,
ca: caInfo,
requestTimeout: 30000
});
server.onRequest(async (req) => {
console.log('Request:', req.method, req.path);
return {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ok: true })
};
});
await server.start();Request Handler
typescript
interface IncomingRequest {
method: string; // 'GET', 'POST', etc.
path: string; // '/handshake/init'
headers: Record<string, string>; // HTTP headers
body: Buffer; // Request body
remoteAddress: string; // Client IP
remoteCert?: CertificateInfo; // Client certificate (mTLS)
}Response Format
typescript
{
status: number; // HTTP status code
headers?: Record<string, string>; // Response headers
body?: string | Buffer; // Response body
}Server Events
typescript
server.on('listening', (addr) => {
console.log('Server listening:', addr.address, addr.port);
});
server.on('connection', (info) => {
console.log('New connection:', info.remoteAddress);
});
server.on('error', (err) => {
console.error('Server error:', err.message);
});Protocol Endpoints
AGENIUM defines standard endpoints:
Handshake
POST /handshake/init
POST /handshake/completeMessaging
POST /messageHealth Check
GET /healthMetrics (optional)
GET /metricsSecurity Considerations
1. Public Key Pinning
Always verify certificates match DNS:
typescript
// After TLS handshake
const remoteCert = connection.getPeerCertificate();
const publicKey = extractPublicKey(remoteCert);
// Compare with DNS-resolved key
if (publicKey !== resolvedAgent.publicKey) {
throw new Error('Certificate pinning failed!');
}2. Certificate Validation
typescript
// Verify certificate is not expired
if (Date.now() < cert.validFrom || Date.now() > cert.validTo) {
throw new Error('Certificate expired');
}
// Verify CA signature
if (!verifyCertSignature(cert, ca)) {
throw new Error('Invalid certificate signature');
}3. Cipher Suites
AGENIUM uses strong, modern ciphers:
TLS_AES_256_GCM_SHA384
TLS_AES_128_GCM_SHA256
TLS_CHACHA20_POLY1305_SHA2564. TLS Version
Only TLS 1.3 is supported (TLS 1.2 and below are rejected).
Error Handling
Connection Errors
typescript
try {
const response = await client.request(host, port, { ... });
} catch (err) {
if (err.code === 'ECONNREFUSED') {
console.error('Connection refused - server not running?');
} else if (err.code === 'ETIMEDOUT') {
console.error('Connection timeout');
} else if (err.code === 'DEPTH_ZERO_SELF_SIGNED_CERT') {
console.error('Certificate error');
}
}Request Timeouts
typescript
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
try {
const response = await client.request(host, port, {
signal: controller.signal,
...
});
} catch (err) {
if (err.name === 'AbortError') {
console.error('Request aborted after 5s');
}
}Performance Optimization
Connection Reuse
typescript
// ✅ Good: Reuse connection
for (let i = 0; i < 100; i++) {
await client.request('bob.example.com', 8443, { ... });
}
// ❌ Bad: Create new connection each time
for (let i = 0; i < 100; i++) {
const newClient = createClient({ ... });
await newClient.request('bob.example.com', 8443, { ... });
}Stream Multiplexing
typescript
// ✅ Good: Concurrent requests on same connection
await Promise.all([
client.request(host, port, { path: '/message1' }),
client.request(host, port, { path: '/message2' }),
client.request(host, port, { path: '/message3' })
]);Keep-Alive
typescript
// Configure idle timeout
const client = createClient({
idleTimeout: 120_000 // Keep connections alive for 2 minutes
});Monitoring
Client Stats
typescript
const stats = client.getStats();
console.log(stats);
/*
{
totalConnections: 5,
activeConnections: 3,
idleConnections: 2,
totalRequests: 1234,
failedRequests: 12,
avgResponseTime: 45.6
}
*/Server Stats
typescript
const stats = server.getStats();
console.log(stats);
/*
{
activeConnections: 8,
totalRequests: 5678,
requestsPerSecond: 120,
avgProcessingTime: 12.3
}
*/Best Practices
1. Use Connection Pooling
typescript
// ✅ Reuse client instance
const client = createClient({ ... });
// Make many requests...2. Set Appropriate Timeouts
typescript
{
connectionTimeout: 10_000, // 10s for TLS handshake
requestTimeout: 30_000, // 30s for request/response
idleTimeout: 60_000 // 1min before closing idle
}3. Handle Errors Gracefully
typescript
async function robustRequest(client, host, port, request) {
let retries = 3;
while (retries > 0) {
try {
return await client.request(host, port, request);
} catch (err) {
retries--;
if (retries === 0) throw err;
await sleep(1000 * (4 - retries)); // Exponential backoff
}
}
}4. Monitor Connection Health
typescript
setInterval(() => {
const stats = client.getStats();
if (stats.failedRequests / stats.totalRequests > 0.1) {
console.warn('High error rate detected!');
}
}, 60_000);See Also
- Sessions - Session management
- Protocol - Message format
- Outbox Pattern - Reliable delivery