"" ""

Tritium Web API (v 1.0.0)


Initialize Tritium

Tritium can be embedded in a web application as a WebAssembly-powered editor. Follow the basic installation instructions at tritium.legal/wasm, including adding a canvas with the ID tritium-canvas. Import the bundle as an ES module and await the import before using the API:

<canvas id="tritium-canvas"></canvas>

<script type="module">
  const tritium = await import("https://tritium.legal/static/init.js");

  await tritium.start();
</script>

The awaited import initializes the WebAssembly bundle. Awaiting start() then launches Tritium in the canvas and resolves when the editor is ready. Calling it without an argument uses the default launch settings.

Adjust Settings

Each setting is optional. Omitted settings retain their default value.

interface Identity {
  firstName?: string | null;
  lastName?: string | null;
  organization?: string | null;
}

interface Settings {
  installId?: string;
  identity?: Identity;
  darkMode?: boolean;
  formattingMarks?: boolean;
  blacklineMode?: boolean;
  provider?: Provider | null;
  recentFolders?: string[];
  recentFiles?: string[];
  panels?: string[][];
  cleanExit?: boolean;
  authToken?: string | null;
}

The main user-facing settings are:

PropertyDefaultPurpose
identityEmpty identityAuthor information used for document changes and comments.
darkModefalseShow white text on a dark page background.
formattingMarkstrueShows formatting marks in documents.
blacklineModefalseProduce blacklines instead of redlines.
providernullConfigures and enables the in-app assistant.

The remaining properties represent installation, authentication, or session state and are for internal use.

Configure the Assistant

The in-application assistant is disabled by default in the WebAssembly build. It is enabled only when settings.provider is supplied.

To connect the assistant to your own backend, use a Custom provider and set its url to your endpoint:

await tritium.start({
  settings: {
    provider: {
      Custom: {
        name: "Example assistant",
        url: "https://assistant.example.com/v1/chat/completions",
        model: "example-model",
        token: "optional-bearer-token",
        location: "memory",
        payloadType: "json",
      },
    },
  },
});

The provider schema is:

type Provider =
  | { Tritium: ProviderConfiguration }
  | { OpenAI: ProviderConfiguration }
  | { Claude: ProviderConfiguration }
  | { DeepSeek: ProviderConfiguration }
  | { Gemini: ProviderConfiguration }
  | { Custom: ProviderConfiguration };

interface ProviderConfiguration {
  name?: string;
  token?: string | null;
  model?: string | null;
  url?: string;
  queryParameters?: [string, string][];
  location?: "memory" | { file: string };
  payloadType?: "json" | "form";
}

A custom endpoint must implement the OpenAI Chat Completions API, including streamed Server-Sent Events and OpenAI-style tool calls. The integration will not work with an incompatible request or response format.

Tritium sends token, when present, as a bearer token. Because WebAssembly runs in the browser, the endpoint must also permit requests from the embedding application's origin. Avoid placing long-lived secrets in client-side code; a backend-controlled short-lived credential or authenticated proxy is preferable.

Start Tritium

start(options?: LaunchOptions): Promise<void>

All launch options are optional:

interface LaunchOptions {
  folder?: string;
  files?: File[];
  settings?: Settings;
}
  • folder is the logical path of the folder to show in Tritium's library.
  • files contains browser File objects to load. Without folder, the files are opened directly. With folder, they are loaded as files in that folder.
  • settings overrides Tritium's defaults for this launch.

For example, an application can start Tritium with files selected by the user:

const files = Array.from(fileInput.files ?? []);

await tritium.start({
  folder: "matter-123",
  files,
  settings: {
    darkMode: true,
    formattingMarks: false,
    identity: {
      firstName: "Alex",
      lastName: "Morgan",
      organization: "Example LLP",
    },
  },
});

Always await start() before calling other session APIs.

Open Files and Folders

The following APIs add documents to a running Tritium session. Await start() before using them.

openFile

openFile(file: File): Promise<void>

Reads and opens a browser File, making it the active document.

openFolder

openFolder(path: string, files: File[]): Promise<void>

Sets the logical library folder and opens its files.

openArrayBuffer

openArrayBuffer(path: string, buffer: ArrayBuffer, activate: boolean): void

Opens an in-memory document. Set activate to true to make it active.

openBytes

openBytes(path: string, bytes: Uint8Array, activate: boolean): void

This is the byte-array equivalent of openArrayBuffer.

Use Tools

After Tritium has been started, getToolCatalog() returns the available tools. Each entry includes the tool's name, description, input schema, and whether it can modify a document:

interface ToolCatalog {
  apiVersion: "1.0.0";
  tools: ToolDefinition[];
}

interface ToolDefinition {
  name: string;
  description: string;
  modifiesDocument: boolean;
  inputSchema: Record<string, unknown>;
}

Use the returned inputSchema to construct valid arguments, then invoke the tool by name with callTool(name, args). Arguments must be JSON-serializable. Tool names such as list_documents remain snake_case protocol identifiers; argument and result properties use camelCase.

const catalog = tritium.getToolCatalog();
const tool = catalog.tools.find(({ name }) => name === "list_documents");

if (!tool) {
  throw new Error("This Tritium build does not provide list_documents");
}

const result = await tritium.callTool(tool.name /* i.e., "list_documents" */, {});
const outcome = result.output;

if (outcome.ok) {
  console.log(outcome.data);
  console.log(result.displayText);
} else {
  console.error(outcome.error.code, outcome.error.message);
}

callTool() always resolves to a ToolResult, including for invalid calls and execution failures. Inspect the discriminated output union to determine whether the call succeeded:

interface ToolResult {
  output: ToolCallOutput;
  displayText: string;
}

type ToolCallOutput =
  | {
      ok: true;
      data: unknown;
    }
  | {
      ok: false;
      error: {
        code:
          | "not_running"
          | "not_ready"
          | "cancelled"
          | "unknown_tool"
          | "invalid_arguments"
          | "execution_failed"
          | "apply_failed"
          | "unsupported_effect"
          | "stale_segment_ids";
        message: string;
        retryable: boolean;
      };
    };

displayText is a short human-readable summary for logs or UI. The structured output.data value is the result intended for programmatic use or for returning to an LLM. Tool-specific data uses camelCase property names, for example documentIndex, segmentCount, and segmentIdsStale.

The catalog is the source of truth for the tools and argument schemas in the loaded bundle. Check result.output.ok before accessing data, and do not assume that every release exposes the same catalog.

Document and segment identifiers

Call list_documents to obtain document indexes before invoking document-specific tools. read_document returns structured data in this form:

interface ReadDocumentData {
  documentIndex: number;
  filename: string;
  segmentCount: number;
  segments: Array<{ id: number; text: string }>;
}

Call read_document with camelCase arguments, for example callTool("read_document", { documentIndex: 0 }).

Segment IDs describe the document state returned by the read call. After a modifying tool succeeds, its data contains segmentIdsStale: true; read the document again before issuing another segment-based edit.

Save and Exit

setSaveHandler

setSaveHandler(handler: (file: File) => void): void

Register a save handler so the host application can persist documents. Tritium calls this handler whenever a document is saved and passes the complete saved document as a browser File. The file's name, type, size, and contents are available through the standard File API.

tritium.setSaveHandler((file) => {
  console.log(`Saving ${file.name} (${file.size} bytes)`);
  uploadSavedFile(file);
});

The callback transfers responsibility for persistence to the host application. Its return value is not awaited, so the host should handle and report asynchronous upload failures itself.

setExitHandler

setExitHandler(handler: () => void): void

Register an exit handler to restore the host application's UI or perform other cleanup after Tritium shuts down:

tritium.setExitHandler(() => {
  document.querySelector("#host-application").hidden = false;
});

Call tritium.shutdown() to close the current Tritium session. Shutdown removes the editor session, returns browser history to the entry preceding Tritium's launch, and then invokes the registered exit handler.

Register save and exit handlers before calling start() when the host must observe the entire session:

const tritium = await import("https://tritium.legal/static/init.js");

tritium.setSaveHandler(handleSavedFile);
tritium.setExitHandler(handleTritiumExit);
await tritium.start();

Future versions of this API will add these handlers to the launch settings.

Tool Description

The following tools are available in the current build, but they may be added, removed, or changed in future releases.

Agents should call getToolCatalog() at runtime and treat its returned names, descriptions, and input schemas as canonical. This section describes the current API, but runtime discovery is preferred.

Every tool is invoked with callTool(name, args) and returns a ToolResult.

list_documents

callTool(name: "list_documents", args: Record<string, never>): Promise<ToolResult>

Lists the open documents. Successful result data contains a documents array whose entries have index, filename, active, and nullable path properties. Use these indexes in calls to document-specific tools.

await tritium.callTool("list_documents", {})
/*
{
  output: {
    ok: true,
    data: {
      documents: [
        { index: 0, filename: "contract.docx", active: true, path: "/matter/contract.docx" },
        { index: 1, filename: "schedule.docx", active: false, path: null }
      ]
    }
  },
  displayText: "Listed 2 open document(s)."
}
*/

read_document

callTool(name: "read_document", args: { documentIndex: number }): Promise<ToolResult>

Reads every segment in a document. Successful result data contains documentIndex, filename, segmentCount, and a segments array of { id, text } objects.

await tritium.callTool("read_document", {
  documentIndex: 0,
})
/*
{
  output: {
    ok: true,
    data: {
      documentIndex: 0,
      filename: "contract.docx",
      segmentCount: 2,
      segments: [
        { id: 0, text: "Services Agreement" },
        { id: 1, text: "This agreement begins on 1 September 2026." }
      ]
    }
  },
  displayText: "Read 2 segment(s) from \"contract.docx\"."
}
*/

read_segments

callTool(name: "read_segments", args: { documentIndex: number; startId: number; endId: number }): Promise<ToolResult>

Reads an inclusive range of segments. Successful result data contains documentIndex, the requestedRange, and the matching segments.

await tritium.callTool("read_segments", {
  documentIndex: 0,
  startId: 10,
  endId: 20,
})
/*
{
  output: {
    ok: true,
    data: {
      documentIndex: 0,
      requestedRange: { startId: 10, endId: 20 },
      segments: [
        { id: 10, text: "10. Confidentiality" },
        { id: 11, text: "Each party must keep information confidential." }
      ]
    }
  },
  displayText: "Read 2 segment(s) from range [10, 20]."
}
*/

search_text

callTool(name: "search_text", args: { query: string; documentIndex?: number }): Promise<ToolResult>

Searches for a case-insensitive substring across every open document, or within one document when documentIndex is supplied. Successful result data contains query, totalMatches, and matching documents and segments.

await tritium.callTool("search_text", {
  query: "termination",
  documentIndex: 0,
})
/*
{
  output: {
    ok: true,
    data: {
      query: "termination",
      totalMatches: 1,
      documents: [{
        index: 0,
        filename: "contract.docx",
        segments: [{ id: 24, text: "Either party may terminate on 30 days' notice." }]
      }]
    }
  },
  displayText: "Found 1 matching segment(s)."
}
*/

compare_documents

callTool(name: "compare_documents", args: { originalIndex: number; modifiedIndex: number }): Promise<ToolResult>

Requests a redline comparison between two open documents. Successful result data confirms the accepted originalIndex and modifiedIndex.

await tritium.callTool("compare_documents", {
  originalIndex: 0,
  modifiedIndex: 1,
})
/*
{
  output: {
    ok: true,
    data: { status: "accepted", originalIndex: 0, modifiedIndex: 1 }
  },
  displayText: "Queued redline comparison: \"contract.docx\" (original) vs \"revised-contract.docx\" (modified)."
}
*/

replace_segment

callTool(name: "replace_segment", args: { documentIndex: number; segmentId: number; newText: string }): Promise<ToolResult>

Replaces the text of one segment. Read the document first to obtain its current segment IDs.

await tritium.callTool("replace_segment", {
  documentIndex: 0,
  segmentId: 12,
  newText: "The replacement paragraph text.",
})
/*
{
  output: {
    ok: true,
    data: { status: "accepted", documentIndex: 0, segmentId: 12, segmentIdsStale: true }
  },
  displayText: "Queued replacement of segment 12."
}
*/

insert_segment

callTool(name: "insert_segment", args: { documentIndex: number; beforeId: number; text: string }): Promise<ToolResult>

Inserts one segment before beforeId. Use the document's segment count as beforeId to append at the end.

await tritium.callTool("insert_segment", {
  documentIndex: 0,
  beforeId: 12,
  text: "A newly inserted paragraph.",
})
/*
{
  output: {
    ok: true,
    data: { status: "accepted", documentIndex: 0, beforeId: 12, segmentIdsStale: true }
  },
  displayText: "Queued segment insertion before position 12."
}
*/

delete_segment

callTool(name: "delete_segment", args: { documentIndex: number; segmentId: number }): Promise<ToolResult>

Deletes one segment using its current segment ID.

await tritium.callTool("delete_segment", {
  documentIndex: 0,
  segmentId: 12,
})
/*
{
  output: {
    ok: true,
    data: { status: "accepted", documentIndex: 0, segmentId: 12, segmentIdsStale: true }
  },
  displayText: "Queued deletion of segment 12."
}
*/

batch_edit

callTool(name: "batch_edit", args: { documentIndex: number; edits: Array<{ segmentId: number; newText: string }> }): Promise<ToolResult>

Replaces several segments in one operation. Passing an empty edits array succeeds as a no-op.

await tritium.callTool("batch_edit", {
  documentIndex: 0,
  edits: [
    { segmentId: 12, newText: "First replacement." },
    { segmentId: 15, newText: "Second replacement." },
  ],
})
/*
{
  output: {
    ok: true,
    data: { status: "accepted", documentIndex: 0, editCount: 2, segmentIdsStale: true }
  },
  displayText: "Queued 2 edit(s) for document 0."
}
*/

create_document

callTool(name: "create_document", args: { filename: string; segments: string[] }): Promise<ToolResult>

Creates a DOCX document. Each string in segments becomes one document segment, and at least one segment is required.

await tritium.callTool("create_document", {
  filename: "draft.docx",
  segments: ["Draft agreement", "1. Definitions", "2. Term"],
})
/*
{
  output: {
    ok: true,
    data: { status: "accepted", filename: "draft.docx", segmentCount: 3 }
  },
  displayText: "Queued creation of \"draft.docx\" with 3 segment(s)."
}
*/

draft_section

callTool(name: "draft_section", args: { documentIndex: number; beforeId: number; segments: string[] }): Promise<ToolResult>

Inserts several new segments before beforeId. Use the current segment count to append the section at the end.

await tritium.callTool("draft_section", {
  documentIndex: 0,
  beforeId: 12,
  segments: ["3. Confidentiality", "Each party must keep information confidential."],
})
/*
{
  output: {
    ok: true,
    data: {
      status: "accepted",
      documentIndex: 0,
      beforeId: 12,
      segmentCount: 2,
      segmentIdsStale: true
    }
  },
  displayText: "Queued 2 drafted segment(s) at position 12 in document 0."
}
*/

Segment IDs are positional identifiers for the document state returned by read_document or read_segments. After an edit succeeds with segmentIdsStale: true, read the document again before making another segment-based call.

TypeScript Declarations

TypeScript declarations are available at https://tritium.legal/static/init.d.ts

Download the declaration file into your project, for example:

curl -fsSL https://tritium.legal/static/init.d.ts -o src/types/init.d.ts

Then, add it to your tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "https://tritium.legal/static/init.js": [
        "./src/types/init.d.ts"
      ]
    }
  }
}