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:
| Property | Default | Purpose |
|---|---|---|
identity | Empty identity | Author information used for document changes and comments. |
darkMode | false | Show white text on a dark page background. |
formattingMarks | true | Shows formatting marks in documents. |
blacklineMode | false | Produce blacklines instead of redlines. |
provider | null | Configures 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;
}
folderis the logical path of the folder to show in Tritium's library.filescontains browserFileobjects to load. Withoutfolder, the files are opened directly. Withfolder, they are loaded as files in that folder.settingsoverrides 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"
]
}
}
}