Skip to main content

Overview

CopilotRuntime is the central runtime object that manages agents, transcription services, middleware, and agent runners on the server side. It’s passed to all request handlers and provides the execution environment for agents.

Constructor

new CopilotRuntime(options: CopilotRuntimeOptions)

Parameters

agents
MaybePromise<NonEmptyRecord<Record<string, AbstractAgent>>>
required
Map of available agents indexed by agent ID. Can be a Promise that resolves to the agent map (for lazy loading).
agents: {
  'default': new BuiltInAgent({
    model: 'openai/gpt-4o',
    apiKey: process.env.OPENAI_API_KEY
  }),
  'research': new BuiltInAgent({
    model: 'anthropic/claude-sonnet-4.5',
    apiKey: process.env.ANTHROPIC_API_KEY
  })
}
runner
AgentRunner
The runner implementation to use for executing agents. Defaults to InMemoryAgentRunner.
runner: new InMemoryAgentRunner()
transcriptionService
TranscriptionService
Optional service for audio transcription (for voice input features).
transcriptionService: new OpenAITranscriptionService({
  apiKey: process.env.OPENAI_API_KEY
})
beforeRequestMiddleware
BeforeRequestMiddleware
Optional middleware function or webhook URL called before processing requests. Can modify requests or reject them.
beforeRequestMiddleware: async (request, path) => {
  // Validate authentication
  const token = request.headers.get('Authorization');
  if (!token) {
    return new Response('Unauthorized', { status: 401 });
  }
  // Modify request
  return new Request(request.url, {
    ...request,
    headers: {
      ...request.headers,
      'X-User-Id': getUserIdFromToken(token)
    }
  });
}
afterRequestMiddleware
AfterRequestMiddleware
Optional middleware function or webhook URL called after processing requests. Useful for logging, analytics, etc.
afterRequestMiddleware: async (response, path) => {
  console.log(`Request to ${path} completed with status ${response.status}`);
}
a2ui
A2UIMiddlewareConfig
Auto-apply A2UI middleware to agents at runtime for computer use capabilities.
a2ui: {
  agents: ['default'], // Apply only to specific agents
  // A2UI-specific configuration
}
mcpApps
McpAppsConfig
Auto-apply MCP (Model Context Protocol) Apps middleware to agents.
mcpApps: {
  servers: [
    {
      type: 'http',
      url: 'https://mcp-server.example.com',
      agentId: 'research' // Bind to specific agent
    }
  ]
}

Properties

agents

public agents: MaybePromise<NonEmptyRecord<Record<string, AbstractAgent>>>
Map of available agents, indexed by agent ID.

runner

public runner: AgentRunner
The agent runner instance used for executing agents.

transcriptionService

public transcriptionService?: TranscriptionService
Optional transcription service for voice input.

beforeRequestMiddleware

public beforeRequestMiddleware?: BeforeRequestMiddleware
Optional before-request middleware.

afterRequestMiddleware

public afterRequestMiddleware?: AfterRequestMiddleware
Optional after-request middleware.

a2ui

public a2ui?: A2UIMiddlewareConfig
A2UI middleware configuration.

mcpApps

public mcpApps?: McpAppsConfig
MCP Apps middleware configuration.

Usage Examples

Basic Runtime

import { CopilotRuntime } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/agent';

const runtime = new CopilotRuntime({
  agents: {
    'default': new BuiltInAgent({
      model: 'openai/gpt-4o',
      apiKey: process.env.OPENAI_API_KEY,
      prompt: 'You are a helpful assistant.'
    })
  }
});

With Custom Runner

import { CopilotRuntime, InMemoryAgentRunner } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/agent';

const runtime = new CopilotRuntime({
  agents: {
    'default': new BuiltInAgent({
      model: 'openai/gpt-4o',
      apiKey: process.env.OPENAI_API_KEY
    })
  },
  runner: new InMemoryAgentRunner()
});

With Middleware

import { CopilotRuntime } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/agent';

const runtime = new CopilotRuntime({
  agents: {
    'default': new BuiltInAgent({
      model: 'openai/gpt-4o',
      apiKey: process.env.OPENAI_API_KEY
    })
  },
  
  beforeRequestMiddleware: async (request, path) => {
    // Log incoming requests
    console.log(`[${new Date().toISOString()}] ${request.method} ${path}`);
    
    // Validate authentication
    const apiKey = request.headers.get('X-API-Key');
    if (!apiKey || !isValidApiKey(apiKey)) {
      return new Response('Unauthorized', { status: 401 });
    }
    
    // Add user context
    const userId = getUserIdFromApiKey(apiKey);
    const modifiedRequest = new Request(request.url, {
      method: request.method,
      headers: {
        ...Object.fromEntries(request.headers.entries()),
        'X-User-Id': userId
      },
      body: request.body,
      duplex: 'half'
    });
    
    return modifiedRequest;
  },
  
  afterRequestMiddleware: async (response, path) => {
    // Log response status
    console.log(`[${new Date().toISOString()}] Response ${response.status} for ${path}`);
    
    // Track usage
    await trackUsage({
      path,
      status: response.status,
      timestamp: new Date()
    });
  }
});

With Transcription Service

import { CopilotRuntime } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/agent';
import { OpenAITranscriptionService } from '@copilotkit/runtime/transcription';

const runtime = new CopilotRuntime({
  agents: {
    'default': new BuiltInAgent({
      model: 'openai/gpt-4o',
      apiKey: process.env.OPENAI_API_KEY
    })
  },
  
  transcriptionService: new OpenAITranscriptionService({
    apiKey: process.env.OPENAI_API_KEY,
    model: 'whisper-1'
  })
});

With MCP Apps

import { CopilotRuntime } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/agent';

const runtime = new CopilotRuntime({
  agents: {
    'research': new BuiltInAgent({
      model: 'openai/gpt-4o',
      apiKey: process.env.OPENAI_API_KEY
    })
  },
  
  mcpApps: {
    servers: [
      {
        type: 'http',
        url: 'https://filesystem-mcp.example.com',
        agentId: 'research', // Only available to research agent
        options: {
          headers: {
            'Authorization': 'Bearer mcp-token'
          }
        }
      },
      {
        type: 'sse',
        url: 'https://database-mcp.example.com',
        // No agentId - available to all agents
        headers: {
          'X-API-Key': process.env.MCP_API_KEY
        }
      }
    ]
  }
});

Lazy Loading Agents

import { CopilotRuntime } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/agent';

const runtime = new CopilotRuntime({
  // Agents are loaded lazily
  agents: (async () => {
    const config = await loadAgentConfig();
    
    return {
      'default': new BuiltInAgent({
        model: config.defaultModel,
        apiKey: config.apiKey,
        prompt: config.systemPrompt
      }),
      'specialized': new BuiltInAgent({
        model: config.specializedModel,
        apiKey: config.apiKey,
        tools: await loadSpecializedTools()
      })
    };
  })()
});

Multiple Agents

import { CopilotRuntime } from '@copilotkit/runtime';
import { BuiltInAgent } from '@copilotkit/agent';

const runtime = new CopilotRuntime({
  agents: {
    'customer-service': new BuiltInAgent({
      model: 'openai/gpt-4o',
      apiKey: process.env.OPENAI_API_KEY,
      prompt: 'You are a friendly customer service agent.'
    }),
    
    'technical-support': new BuiltInAgent({
      model: 'anthropic/claude-sonnet-4.5',
      apiKey: process.env.ANTHROPIC_API_KEY,
      prompt: 'You are a technical support specialist.',
      tools: [technicalTools]
    }),
    
    'sales': new BuiltInAgent({
      model: 'openai/gpt-4o-mini',
      apiKey: process.env.OPENAI_API_KEY,
      prompt: 'You are a sales assistant.',
      maxSteps: 5
    })
  }
});

Middleware Types

BeforeRequestMiddleware

type BeforeRequestMiddleware = 
  | string // Webhook URL
  | ((request: Request, path: string) => Promise<Request | Response | undefined>);
  • Webhook URL: POST request sent to URL with request details
  • Function: Can modify request or return Response to short-circuit
  • Return undefined: Continue with original request
  • Return Request: Use modified request
  • Return Response: Short-circuit and return response

AfterRequestMiddleware

type AfterRequestMiddleware = 
  | string // Webhook URL
  | ((response: Response, path: string) => Promise<void>);
  • Webhook URL: POST request sent to URL with response details
  • Function: Called after response is generated (fire-and-forget)
  • Note: Cannot modify the response

Endpoint Integration

Use the runtime with endpoint adapters:
// Express
import { createCopilotEndpointExpress } from '@copilotkit/runtime/express';
import express from 'express';

const app = express();
const copilotEndpoint = createCopilotEndpointExpress({
  runtime,
  basePath: '/api/copilotkit'
});
app.use(copilotEndpoint);

// Hono
import { createCopilotEndpoint } from '@copilotkit/runtime/hono';
import { Hono } from 'hono';

const app = new Hono();
const copilotEndpoint = createCopilotEndpoint({
  runtime,
  basePath: '/api/copilotkit'
});
app.route('/api/copilotkit', copilotEndpoint);

See Also