Technical guide

Functionality, interface, and integration model.

This page explains what the extension exposes to trusted callers, how the options UI is organized, and how browser apps connect to the runtime.

Runtime surface

One AI runtime, two caller experiences.

AI runtime

Trusted Chrome extensions call a small helper in their own code. The helper sends runtime.call through chrome.runtime.sendMessage, receives the current policy and capabilities when needed, and sends chat requests with optional provider, model, output limit, temperature, response format, reasoning mode, and attachments.

In-page module

Trusted web pages activate the content script to show the in-page module with provider/model selectors and an options button. They can also send a single prompt event with optional attachments and receive the result as a page event.

Attachments

Requests may include text files, JSON/XML/CSV-style files, PDFs, and common image formats. Text-like files are sent as text content. Binary files are sent as base64 attachment payloads.

Options interface

The extension is configured from one options page.

AI providers

Enable or disable OpenRouter, Anthropic, Ollama, LM Studio, and WebLLM. Store API keys, base URLs, and default models locally in Chrome extension storage. Ollama discovery and chat calls are sent through the extension-backed CORS proxy, which is covered by wildcard HTTP and HTTPS port entries in the extension CSP.

AI settings

Control AI audit storage. The extension does not apply extension-level input, output, or execution-time limits to AI requests.

Test console

Run a prompt directly from the options page, attach small files, choose provider/model behavior, and inspect the selected provider, model, usage, response, or error.

Audit log

Review the latest 20 local runtime calls with origin, app ID, provider, model, status, timing, request metadata, truncated prompt text, truncated response text, and attachment metadata.

Authorized callers

Authorized callers are managed from the AI area. Each trusted site or extension ID can be enabled, assigned allowed providers, and given app-specific provider/model defaults.

Extension API

The public API is intentionally small.

Web pages can activate the in-page module or send prompt requests with optional attachments. Chrome extensions can expose a single async function in their own code. That function should use chrome.runtime.sendMessage with runtime.call. No company name is required.

Extension call API

Use a call-style helper that sends runtime.call through chrome.runtime.sendMessage(extensionId, ...). The wrapped payload can be runtime.chat, runtime.capabilities, or runtime.appConfig.update. The extension API does not expose a long-lived runtime port.

Content script events

Pages with the content script can use custom events: ai-runtime-extension:ping, ai-runtime-extension:activate, and ai-runtime-extension:prompt. Ping is used for discovery. Activate mounts the in-page AI module. Prompt sends an AI request and returns ai-runtime-extension:prompt-result.

Provider selection

Extensions send runtime.capabilities to read available providers and model lists, then send runtime.appConfig.update or pass provider and model on each chat request.

App identity

Extension callers only need a stable app.id on runtime.call. app.name and app.version are optional metadata; they are not company fields.

// Web page activation
window.dispatchEvent(
  new CustomEvent('ai-runtime-extension:activate', {
    detail: { target: 'ai-runtime-extension' },
  }),
);

// Web page prompt request
const requestId = crypto.randomUUID();

window.dispatchEvent(
  new CustomEvent('ai-runtime-extension:prompt', {
    detail: {
      target: 'ai-runtime-extension',
      payload: {
        requestId,
        prompt: 'Analyze this attachment.',
        attachments: [
          {
            name: 'notes.txt',
            mimeType: 'text/plain',
            text: 'Notes to analyze',
          },
        ],
      },
    },
  }),
);

window.addEventListener('ai-runtime-extension:prompt-result', (event) => {
  if (event.detail.requestId === requestId) {
    console.log(event.detail.response ?? event.detail.error);
  }
});

// Chrome extension call-style helper usage
const result = await askAiRuntime({
  extensionId: 'AI_RUNTIME_EXTENSION_ID',
  appId: 'my-extension',
  messages: [{ role: 'user', content: 'Analyze these files.' }],
  files: [
    {
      id: crypto.randomUUID(),
      name: 'notes.txt',
      mimeType: 'text/plain',
      sizeBytes: 16,
      textContent: 'Notes to analyze',
    },
  ],
});

console.log(result.text);

Extension integration

Expose one function in the caller extension.

A trusted extension page can expose one async function backed by runtime.call. The runtime validates the caller extension ID before returning capabilities or executing chat requests.

async function askAiRuntime(input) {
  const requestId = crypto.randomUUID();
  const { extensionId, appId, ...chat } = input;

  return new Promise((resolve, reject) => {
    chrome.runtime.sendMessage(
      extensionId,
      {
        type: 'runtime.call',
        requestId,
        app: { id: appId },
        payload: { ...chat, type: 'runtime.chat', requestId },
      },
      (response) => {
        const runtimeError = chrome.runtime.lastError?.message;
        if (runtimeError) {
          reject(new Error(runtimeError));
          return;
        }
        if (!response || response.type === 'runtime.error') {
          reject(new Error(response?.error?.message ?? 'AI runtime call failed.'));
          return;
        }
        resolve(response);
      },
    );
  });
}

Operational notes

Publication-sensitive behavior to disclose clearly.

Cloud AI requests can send prompts, files, and generated context to OpenRouter or Anthropic.

Local HTTP providers use localhost endpoints and may still process sensitive user data locally.

WebLLM downloads model assets and runs inference in an offscreen extension document.

Internal proxy requests can reach only URLs covered by extension host permissions.

The extension CSP explicitly allows non-standard HTTP and HTTPS ports so local endpoints such as http://localhost:11434/api/tags can be reached by the background worker.