Skip to content

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 certificate

TLS 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

  1. Verify certificate chain: Cert signed by CA
  2. Verify not expired: Check validity period
  3. Extract public key: Ed25519 from cert
  4. 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, { ... });  // ~10ms

Timeouts

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/complete

Messaging

POST /message

Health Check

GET /health

Metrics (optional)

GET /metrics

Security 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_SHA256

4. 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

Released under the MIT License.