API Reference
The Lexic API enables you to integrate subject matter expert plugins into any AI agent. Every response is backed by source citations, decision-tree reasoning, and a hallucination guard. Multi-expert collaboration lets you pit domain experts against each other for adversarial reasoning.
Base URL
https://dawk-ps2.vercel.appSDK Package
lexic-sdkTwo auth modes: Dashboard routes use Clerk JWT sessions. The /api/v1/query and /api/v1/collaborate endpoints use Bearer token API key auth for external agent integrations.
Authentication
The external API endpoints (/api/v1/query and /api/v1/collaborate) authenticate via API key sent as a Bearer token. Generate keys from the API Keys page in the dashboard.
Authorization: Bearer lx_a1b2c3d4e5f6...All other /api/* endpoints (plugins, documents, trees, collaboration rooms, api-keys) require a Clerk session cookie — they are for the web dashboard, not for external agent calls.
/api/v1/query
The core endpoint. Send a question and a plugin slug, and get back a cited, decision-tree-backed expert answer. Supports both JSON and SSE streaming responses, conversation context for multi-turn dialogues, and per-request query options.
Request Body
| Param | Type | Required | Description |
|---|---|---|---|
plugin | string | Required | Slug of the expert plugin to query (e.g. "structural-eng-v1") |
query | string | Required | The domain question to ask. Max 4,000 characters. |
stream | boolean | Optional | Set to true to receive SSE streaming response. Also enabled by Accept: text/event-stream header. |
context | array | Optional | Conversation history for multi-turn dialogues. Array of { role: "user" | "assistant", content: string } objects. |
Example Request
curl -X POST https://dawk-ps2.vercel.app/api/v1/query \
-H "Authorization: Bearer lx_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"plugin": "structural-eng-v1",
"query": "What is the minimum cover for a beam in severe exposure?"
}'Multi-Turn Conversation
curl -X POST https://dawk-ps2.vercel.app/api/v1/query \
-H "Authorization: Bearer lx_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"plugin": "structural-eng-v1",
"query": "What about for a column instead?",
"context": [
{ "role": "user", "content": "What is the minimum cover for a beam in severe exposure?" },
{ "role": "assistant", "content": "According to IS 456 Table 16, the minimum nominal cover for a beam in severe exposure is 45mm." }
]
}'Streaming Request
curl -X POST https://dawk-ps2.vercel.app/api/v1/query \
-H "Authorization: Bearer lx_a1b2c3d4..." \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{
"plugin": "structural-eng-v1",
"query": "What is the minimum cover for a beam in severe exposure?",
"stream": true
}'JSON Response
{
"answer": "According to IS 456 Table 16, the minimum nominal cover for a beam in severe exposure is 45mm. [Source 1]",
"citations": [
{
"id": "chunk_abc123",
"document": "IS-456-2000.pdf",
"page": 34,
"section": "Table 16 — Nominal Cover",
"excerpt": "For severe exposure conditions, beams require 45mm minimum cover..."
}
],
"decisionPath": [
{ "step": 1, "node": "q1", "label": "Member Type", "value": "beam" },
{ "step": 2, "node": "q2", "label": "Exposure Class", "value": "severe" },
{ "step": 3, "node": "a1", "label": "Cover Recommendation", "result": "45mm nominal cover" }
],
"confidence": "high",
"pluginVersion": "1"
}SSE Stream Events
When streaming is enabled, events are delivered as Server-Sent Events:
data: {"type":"status","status":"retrieving","message":"Found 5 relevant sources","sourceCount":5}
data: {"type":"delta","text":"According to "}
data: {"type":"delta","text":"IS 456 Table 16..."}
data: {"type":"done","answer":"...full answer...","citations":[...],"decisionPath":[...],"confidence":"high","pluginVersion":"1"}Response Fields
| Field | Type | Description |
|---|---|---|
answer | string | The expert answer with inline [Source N] citations |
citations | Citation[] | Array of source references with document, page, section, and excerpt |
decisionPath | DecisionStep[] | Steps the decision tree walked to reach the answer |
confidence | "high" | "medium" | "low" | Hallucination guard score. Low = answer was refused/replaced. |
pluginVersion | string | Plugin version at time of query (for audit trails) |
Error Responses
plugin or query, or query exceeds 4,000 chars/api/v1/collaborate
Multi-expert adversarial reasoning. Send a query to multiple expert plugins simultaneously — they deliberate across rounds, critique each other, and an AI moderator synthesizes a final consensus. Supports three modes: debate (multi-round adversarial), consensus (single round + synthesis), and review (one leads, others critique).
Request Body
| Param | Type | Required | Description |
|---|---|---|---|
experts | string[] | Required | Array of 2–5 plugin slugs (e.g. ["structural-eng-v1", "geotech-v1"]) |
query | string | Required | The domain question. Max 4,000 characters. |
mode | string | Optional | "debate" (default), "consensus", or "review". Controls deliberation strategy. |
maxRounds | number | Optional | Max deliberation rounds (1–3). Default: 3. |
stream | boolean | Optional | Set to true for SSE streaming. Also enabled by Accept: text/event-stream header. |
Example Request
curl -X POST https://dawk-ps2.vercel.app/api/v1/collaborate \
-H "Authorization: Bearer lx_a1b2c3d4..." \
-H "Content-Type: application/json" \
-d '{
"experts": ["structural-eng-v1", "geotech-v1"],
"query": "What foundation type is best for a 5-story building on expansive clay soil?",
"mode": "debate",
"maxRounds": 2
}'JSON Response
{
"rounds": [
{
"roundNumber": 1,
"responses": [
{
"pluginSlug": "structural-eng-v1",
"pluginName": "Structural Engineering Expert",
"domain": "Structural Engineering",
"answer": "For a 5-story building on expansive clay...",
"citations": [...],
"confidence": "high",
"revised": false
},
{
"pluginSlug": "geotech-v1",
"pluginName": "Geotechnical Expert",
"domain": "Geotechnical Engineering",
"answer": "Expansive clay soils require...",
"citations": [...],
"confidence": "high",
"revised": false
}
]
}
],
"consensus": {
"answer": "Both experts agree that a mat/raft foundation is recommended...",
"confidence": "high",
"agreementLevel": 0.85,
"citations": [...],
"conflicts": [
{
"topic": "Pile depth requirements",
"positions": [
{ "expert": "structural-eng-v1", "stance": "Minimum 15m driven piles" },
{ "expert": "geotech-v1", "stance": "12m bored piles sufficient" }
],
"resolved": true,
"resolution": "Bored piles at 12-15m depth recommended pending soil investigation"
}
],
"expertContributions": [
{ "expert": "structural-eng-v1", "domain": "Structural Engineering", "keyPoints": ["Load analysis", "Foundation sizing"] },
{ "expert": "geotech-v1", "domain": "Geotechnical Engineering", "keyPoints": ["Soil bearing capacity", "Settlement analysis"] }
]
},
"latencyMs": 12450
}SSE Stream Events
Streaming delivers real-time progress through the deliberation:
data: {"type":"status","status":"resolving","message":"Resolving expert plugins..."}
data: {"type":"experts_resolved","experts":[{"slug":"structural-eng-v1","name":"Structural Engineering Expert","domain":"Structural Engineering","sourceCount":42,"hasDecisionTree":true},{"slug":"geotech-v1",...}]}
data: {"type":"round_start","round":1,"totalRounds":2}
data: {"type":"expert_thinking","expert":"structural-eng-v1","expertName":"Structural Engineering Expert","domain":"Structural Engineering","message":"Analyzing with 42 sources..."}
data: {"type":"expert_response","round":1,"expert":"structural-eng-v1","expertName":"Structural Engineering Expert","domain":"Structural Engineering","answer":"...","citations":[...],"confidence":"high","revised":false}
data: {"type":"round_complete","round":1}
data: {"type":"done","rounds":[...],"consensus":{...},"latencyMs":12450}Collaboration Modes
debate
Multi-round adversarial. Each expert independently answers, then in subsequent rounds they see all prior responses and can revise their positions. An AI moderator synthesizes the final consensus.
consensus
Single round only. All experts answer independently, then the moderator synthesizes a consensus without further deliberation.
review
One expert leads with a full answer, the remaining experts critique and suggest revisions. Best for getting peer review on a primary expert's analysis.
Error Responses
Plugins
CRUD endpoints for managing expert plugins. All require Clerk session auth (dashboard use only).
/api/pluginsList all plugins owned by the authenticated user, ordered by creation date (newest first).
Response
Array of plugin objects with all fields (id, name, slug, domain, description, systemPrompt, citationMode, version, isPublished, config, createdAt, updatedAt).
/api/pluginsCreate a new expert plugin. A unique slug is auto-generated from the name.
Request Body
name | string | Required | Display name of the plugin |
domain | string | Required | Domain/field of expertise (e.g. "Structural Engineering") |
systemPrompt | string | Required | Expert persona prompt for the LLM |
description | string | Optional | Optional description of the plugin |
citationMode | string | Optional | "mandatory" (default) or "optional" |
{
"name": "Structural Engineering Expert",
"domain": "Structural Engineering",
"systemPrompt": "You are an expert structural engineer specializing in IS 456 code compliance...",
"description": "Expert on IS 456 concrete design standards",
"citationMode": "mandatory"
}/api/plugins/:idGet a single plugin by UUID, including its related knowledge documents and decision trees. Must be the plugin owner.
/api/plugins/:idUpdate a plugin. Supports partial updates — only send the fields you want to change.
Updatable Fields
name | string | Optional | New display name |
description | string | Optional | New description |
domain | string | Optional | New domain |
systemPrompt | string | Optional | New system prompt |
citationMode | string | Optional | "mandatory" or "optional" |
isPublished | boolean | Optional | Publish/unpublish the plugin |
/api/plugins/:idDelete a plugin and all associated data (documents, chunks, decision trees) via cascade. Must be the plugin owner.
Knowledge Documents
Upload reference documents to a plugin's knowledge base. Documents are automatically chunked and embedded for vector similarity search.
/api/plugins/:id/documentsList all knowledge documents for a plugin. Requires ownership.
/api/plugins/:id/documentsUpload a document. Accepts multipart/form-data. The document is chunked, embedded with OpenAI text-embedding-3-small (1536 dimensions), and stored for pgvector retrieval.
Form Fields
file | File | Optional | A PDF, markdown, or text file to upload |
text | string | Optional | Alternatively, send raw text content directly |
fileName | string | Optional | Override the file name (defaults to uploaded file name) |
fileType | string | Optional | Document type: "pdf", "markdown", etc. (defaults to "markdown") |
Either file or text must be provided.
Response (201)
{
"id": "doc_uuid",
"pluginId": "plugin_uuid",
"fileName": "IS-456-2000.pdf",
"fileType": "pdf",
"rawText": "...",
"metadata": null,
"createdAt": "2026-02-28T...",
"chunksCreated": 42
}/api/plugins/:id/documents?docId=...Delete a document and all its chunks (cascade). Requires docId query param.
Decision Trees
Decision trees add structured reasoning on top of RAG retrieval. Define condition/question/action nodes as JSON, and the engine walks the tree during each query. The decision path is included in every query response, giving full auditability of the reasoning chain.
/api/plugins/:id/treesList all decision trees for a plugin. Returns an array of tree objects with id, name, description, treeData, isActive, and createdAt.
/api/plugins/:id/treesCreate a new decision tree for the plugin.
Request Body
name | string | Required | Name of the decision tree |
treeData | object | Required | JSON decision graph (see structure below) |
description | string | Optional | Optional description |
Tree Data Structure
{
"rootNodeId": "q1",
"nodes": {
"q1": {
"type": "question",
"label": "Member Type",
"question": { "text": "What type of member?", "options": ["beam", "column", "slab"], "extractFrom": "member_type" },
"childrenByAnswer": { "beam": "q2", "column": "q3", "slab": "a3" }
},
"q2": {
"type": "condition",
"label": "Check Exposure",
"condition": { "field": "exposure", "operator": "eq", "value": "severe" },
"trueChildId": "a2",
"falseChildId": "a1"
},
"a1": {
"type": "action",
"label": "Cover Recommendation",
"action": { "recommendation": "20mm nominal cover", "severity": "info" }
},
"a2": {
"type": "action",
"label": "Cover Recommendation",
"action": { "recommendation": "45mm nominal cover", "severity": "warning" }
}
}
}Node Types
condition
Evaluates a field with an operator (eq, gt, lt, contains, in). Branches to trueChildId or falseChildId.
question
Extracts an answer from the query parameters. Routes to the matching child in childrenByAnswer.
action
Terminal node. Returns a recommendation with optional severity and sourceHint. Ends the tree walk.
/api/plugins/:id/trees/:treeIdGet a single decision tree by ID. Returns the full tree object including treeData.
/api/plugins/:id/trees/:treeIdUpdate a decision tree. Supports partial updates.
Updatable Fields
name | string | Optional | New tree name |
description | string | Optional | New description |
treeData | object | Optional | Updated decision graph JSON |
isActive | boolean | Optional | Activate/deactivate the tree |
/api/plugins/:id/trees/:treeIdDelete a decision tree permanently.
Collaboration Rooms
Persistent rooms for multi-expert collaboration sessions. Create a room with a set of experts, then run multiple queries against it. Sessions are stored with full round history and consensus results. All endpoints require Clerk session auth.
/api/collaboration-roomsList all collaboration rooms owned by the authenticated user. Returns rooms with session counts and resolved expert names.
Response
[
{
"id": "room_uuid",
"name": "Foundation Design Panel",
"mode": "debate",
"expertSlugs": ["structural-eng-v1", "geotech-v1"],
"maxRounds": 3,
"createdAt": "2026-02-28T...",
"updatedAt": "2026-02-28T...",
"sessionCount": 5,
"expertNames": ["Structural Engineering Expert", "Geotechnical Expert"]
}
]/api/collaboration-roomsCreate a new collaboration room.
Request Body
name | string | Required | Room display name |
expertSlugs | string[] | Required | Array of 2–5 expert plugin slugs |
mode | string | Optional | "debate" (default), "consensus", or "review" |
maxRounds | number | Optional | Max deliberation rounds (1–3). Default: 3. |
Response (201)
{
"id": "room_uuid",
"creatorId": "user_uuid",
"name": "Foundation Design Panel",
"mode": "debate",
"expertSlugs": ["structural-eng-v1", "geotech-v1"],
"maxRounds": 3,
"createdAt": "2026-02-28T...",
"updatedAt": "2026-02-28T..."
}/api/collaboration-rooms/:idGet a room with its expert details (slug, name, domain) and all collaboration sessions ordered by most recent.
/api/collaboration-rooms/:idDelete a collaboration room and all its sessions (cascade).
/api/collaboration-rooms/sandboxRun a collaboration query inside a room. Creates a new session, runs the multi-expert deliberation, and streams results as SSE. The session is persisted with rounds, consensus, and latency.
Request Body
roomId | string | Required | UUID of the collaboration room |
query | string | Required | The question to ask the expert panel |
Response
SSE stream with the same event types as /api/v1/collaborate — status, experts_resolved, round_start, expert_thinking, expert_response, round_complete, done.
API Keys
Manage API keys for authenticating external agent calls. Keys are prefixed with lx_ and stored as salted hashes. All endpoints require Clerk session auth.
/api/api-keysList all API keys for the authenticated user. Returns id, name, key prefix (first 8 chars), last used timestamp, and created timestamp. Never returns the full key.
/api/api-keysGenerate a new API key. The full key is returned only once in the response — store it securely.
Request Body
name | string | Required | A label for this key (e.g. "production", "my-agent") |
Response (201)
{
"key": "lx_a1b2c3d4e5f6g7h8i9j0...",
"prefix": "lx_a1b2c",
"name": "production"
}/api/api-keysDecrypt and reveal the full API key (requires ownership). Body: { "id": "key_uuid" }
/api/api-keys?id=...Delete an API key. Detaches it from query logs before removal. Requires id query param.
Sandbox
Test your plugin's query pipeline without publishing. Uses Clerk session auth — available from the dashboard only.
/api/sandbox/:pluginIdRun a test query against an unpublished (or published) plugin you own. Same pipeline as the production query endpoint, but bypasses the publish check. Returns SSE stream.
Request Body
query | string | Required | The question to test |
Response
SSE stream with the same event types as /api/v1/query — status, delta, done, error.
Plugin Export
Export a plugin as a JSON file containing the full plugin definition, all knowledge documents (with raw text), and all decision trees.
/api/plugins/:id/exportDownload a complete plugin export as a JSON file attachment. Requires Clerk session auth and plugin ownership.
Response Headers
Content-Type: application/json; charset=utf-8
Content-Disposition: attachment; filename="structural-eng-v1.json"Response Body
{
"version": 1,
"exportedAt": "2026-02-28T...",
"plugin": {
"id": "uuid",
"name": "Structural Engineering Expert",
"slug": "structural-eng-v1",
"description": "...",
"domain": "Structural Engineering",
"systemPrompt": "...",
"citationMode": "mandatory",
"isPublished": true,
"config": {},
"createdAt": "...",
"updatedAt": "..."
},
"documents": [
{
"id": "doc_uuid",
"fileName": "IS-456-2000.pdf",
"fileType": "pdf",
"rawText": "...",
"metadata": {},
"createdAt": "..."
}
],
"decisionTrees": [
{
"id": "tree_uuid",
"name": "Cover Determination",
"description": "...",
"treeData": { "rootNodeId": "q1", "nodes": {...} },
"isActive": true,
"createdAt": "..."
}
]
}Marketplace
Download shared plugins from the marketplace. Plugins must be published and have config.marketplaceShared set to true to be downloadable.
/api/marketplace/:slug/downloadDownload a marketplace-shared plugin as a JSON file. Requires Clerk session auth. Returns the same structure as plugin export, plus a source: "marketplace" field and the creator's display name.
Response (200)
{
"version": 1,
"exportedAt": "2026-02-28T...",
"source": "marketplace",
"plugin": {
"id": "uuid",
"name": "Structural Engineering Expert",
"slug": "structural-eng-v1",
"creator": "John Doe",
...
},
"documents": [...],
"decisionTrees": [...]
}SDK Reference
The TypeScript SDK wraps the REST API with type-safe methods, streaming support, conversation context, timeout handling, and framework adapters.
Installation
npm install lexic-sdkQuick Start
import { Lexic } from "lexic-sdk";
const lexic = new Lexic({
apiKey: "lx_your_api_key",
defaultPlugin: "structural-eng-v1",
});
const result = await lexic.query({
query: "Minimum cover for a beam in severe exposure?",
});
console.log(result.answer); // Cited expert answer
console.log(result.citations); // Source references
console.log(result.confidence); // "high" | "medium" | "low"
console.log(result.decisionPath); // Decision tree stepsConstructor: new Lexic(config)
| Param | Type | Required | Description |
|---|---|---|---|
apiKey | string | Required | Your Lexic API key (starts with lx_) |
baseUrl | string | Optional | Override the API base URL. Default: "https://dawk-ps2.vercel.app" |
defaultPlugin | string | Optional | Default plugin slug for all queries |
timeout | number | Optional | Request timeout in ms. Default: 30000 |
Methods
query(options): Promise<QueryResult>Send a question to an expert plugin. Returns a full result with answer, citations, decision path, and confidence.
options.plugin | string | Optional | Plugin slug (overrides activePlugin for this call) |
options.query | string | Required | The domain question |
options.context | array | Optional | Conversation history: [{ role: "user" | "assistant", content: string }] |
options.options | QueryRequestOptions | Optional | Per-request options (see below) |
queryStream(options): AsyncGenerator<StreamEvent>Stream a query response as an async generator. Yields status, delta (text chunks), and done events. Same options as query().
for await (const event of lexic.queryStream({ query: "..." })) {
if (event.type === "delta") process.stdout.write(event.text);
if (event.type === "done") console.log("\nConfidence:", event.confidence);
}queryStreamToResult(options, onEvent?): Promise<QueryResult>Streams a query but collects the final result as a QueryResult. Pass an optional onEvent callback to handle intermediate events (deltas, status updates).
const result = await lexic.queryStreamToResult(
{ query: "..." },
(event) => {
if (event.type === "delta") process.stdout.write(event.text);
},
);
console.log(result.citations);setActivePlugin(slug): voidHot-swap the active plugin. All subsequent query() calls will use this plugin unless overridden.
getActivePlugin(): string | nullReturns the currently active plugin slug, or null if none is set.
Query Request Options
| Param | Type | Description |
|---|---|---|
citationMode | "inline" | "footnote" | "off" | How citations appear in the answer text |
maxSources | number | Maximum number of knowledge chunks to retrieve |
includeDecisionPath | boolean | Whether to include the decision tree path in the response |
Hot-Swap Example
const lexic = new Lexic({ apiKey: "lx_..." });
// Query the structural engineering expert
lexic.setActivePlugin("structural-eng-v1");
const structResult = await lexic.query({
query: "Max allowable deflection for a cantilever?",
});
// Instantly switch to a different domain expert
lexic.setActivePlugin("electrical-code-v2");
const elecResult = await lexic.query({
query: "Wire sizing for a 30A circuit?",
});Multi-Turn Conversation
const result1 = await lexic.query({
query: "What is the minimum cover for a beam in severe exposure?",
});
const result2 = await lexic.query({
query: "What about for a column instead?",
context: [
{ role: "user", content: "What is the minimum cover for a beam in severe exposure?" },
{ role: "assistant", content: result1.answer },
],
});Error Handling
import { Lexic, LexicAPIError } from "lexic-sdk";
try {
const result = await lexic.query({ query: "..." });
} catch (err) {
if (err instanceof LexicAPIError) {
console.error(err.message); // "Plugin not found or access denied"
console.error(err.status); // 404
}
}SDK Collaboration
The SDK includes full support for multi-expert collaboration — the same adversarial reasoning available via the REST API, with typed methods and streaming.
Methods
collaborate(options): Promise<CollaborationResult>Run a multi-expert collaboration. Returns full results with all rounds, expert responses, and consensus synthesis.
options.experts | string[] | Required | Array of 2–5 expert plugin slugs |
options.query | string | Required | The domain question |
options.mode | string | Optional | "debate" (default), "consensus", or "review" |
options.maxRounds | number | Optional | Max deliberation rounds (1–3). Default: 3. |
const result = await lexic.collaborate({
experts: ["structural-eng-v1", "geotech-v1"],
query: "Best foundation for a 5-story building on clay?",
mode: "debate",
maxRounds: 2,
});
console.log(result.consensus.answer); // Synthesized answer
console.log(result.consensus.agreementLevel); // 0.0–1.0
console.log(result.consensus.conflicts); // Disagreements
console.log(result.rounds); // Full deliberation history
console.log(result.latencyMs); // Total timecollaborateStream(options): AsyncGenerator<CollaborationStreamEvent>Stream a collaboration as an async generator. Yields real-time events as experts deliberate.
for await (const event of lexic.collaborateStream({
experts: ["structural-eng-v1", "geotech-v1"],
query: "Best foundation for a 5-story building on clay?",
})) {
switch (event.type) {
case "experts_resolved":
console.log("Experts:", event.experts.map(e => e.name));
break;
case "expert_thinking":
console.log(`${event.expertName} is analyzing...`);
break;
case "expert_response":
console.log(`${event.expertName} (Round ${event.round}):`, event.answer);
break;
case "done":
console.log("Consensus:", event.consensus.answer);
break;
}
}collaborateStreamToResult(options, onEvent?): Promise<CollaborationResult>Streams a collaboration but collects the final result. Pass an optional onEvent callback for intermediate events.
const result = await lexic.collaborateStreamToResult(
{
experts: ["structural-eng-v1", "geotech-v1"],
query: "Best foundation for a 5-story building on clay?",
},
(event) => {
if (event.type === "expert_thinking") {
console.log(`${event.expertName}: ${event.message}`);
}
},
);
console.log(result.consensus);LangChain Adapter
Drop Lexic into any LangChain agent as a tool. Zero-dependency wrapper — doesn't require langchain as a peer dependency. Includes both single-expert and multi-expert collaboration tools.
Installation
npm install lexic-sdkSingle-Expert Tool
import { LexicTool } from "lexic-sdk/langchain";
const tool = new LexicTool({
apiKey: "lx_your_api_key",
plugin: "structural-eng-v1",
name: "structural_expert",
description: "Consult a structural engineering expert",
queryOptions: {
citationMode: "inline",
maxSources: 5,
includeDecisionPath: true,
},
});
// Add to any LangChain agent
const agent = createOpenAIToolsAgent({ llm, tools: [tool], prompt });
// Hot-swap to a different expert
tool.setPlugin("electrical-code-v2");Constructor: new LexicTool(config)
| Param | Type | Required | Description |
|---|---|---|---|
apiKey | string | Required | Lexic API key |
plugin | string | Required | Plugin slug to query |
baseUrl | string | Optional | Override API base URL |
name | string | Optional | LangChain tool name. Default: "lexic_{slug}" |
description | string | Optional | LangChain tool description shown to the LLM |
queryOptions | QueryRequestOptions | Optional | Default query options (citationMode, maxSources, includeDecisionPath) |
Methods
call(input: string): Promise<string>LangChain Tool interface. Takes the agent's string input, queries the plugin, and returns a JSON string with answer, citations, confidence, and decision path.
setPlugin(slug: string): voidHot-swap which plugin this tool queries.
Multi-Expert Collaboration Tool
import { LexicCollaborationTool } from "lexic-sdk/langchain";
const collabTool = new LexicCollaborationTool({
apiKey: "lx_your_api_key",
experts: ["structural-eng-v1", "geotech-v1"],
name: "expert_panel",
description: "Consult multiple domain experts for adversarial analysis",
mode: "debate",
maxRounds: 2,
onEvent: (event) => {
if (event.type === "expert_thinking") {
console.log(`${event.expertName}: ${event.message}`);
}
},
});
// Add to LangChain agent alongside single-expert tools
const agent = createOpenAIToolsAgent({
llm,
tools: [tool, collabTool],
prompt,
});
// Dynamically change experts or mode
collabTool.setExperts(["structural-eng-v1", "fire-safety-v1"]);
collabTool.setMode("consensus");Constructor: new LexicCollaborationTool(config)
| Param | Type | Required | Description |
|---|---|---|---|
apiKey | string | Required | Lexic API key |
experts | string[] | Required | Array of 2–5 expert plugin slugs |
baseUrl | string | Optional | Override API base URL |
name | string | Optional | LangChain tool name. Default: "lexic_collaboration" |
description | string | Optional | Tool description for the LLM agent |
mode | CollaborationMode | Optional | "debate" (default), "consensus", or "review" |
maxRounds | number | Optional | Max deliberation rounds (1–3). Default: 3. |
onEvent | function | Optional | Callback for streaming events during collaboration |
Collaboration Tool Methods
call(input: string): Promise<string>LangChain Tool interface. Returns JSON with consensus answer, conflicts, expert contributions, and agreement level.
setExperts(slugs: string[]): voidChange the panel of experts at runtime.
setMode(mode: CollaborationMode): voidSwitch between debate, consensus, and review modes.
AutoGPT Adapter
Register Lexic as an AutoGPT command with typed parameters and execution. Includes both single-expert and multi-expert collaboration adapters.
Single-Expert Usage
import { LexicAutoGPT } from "lexic-sdk/autogpt";
const adapter = new LexicAutoGPT({
apiKey: "lx_your_api_key",
plugin: "structural-eng-v1",
commandName: "consult_structural_expert",
commandDescription: "Ask the structural expert",
queryOptions: {
citationMode: "inline",
maxSources: 5,
includeDecisionPath: true,
},
});
// Register as an AutoGPT command
const command = adapter.asCommand();
// command.name, command.description, command.parameters, command.execute
// Or execute directly
const answer = await adapter.execute(
"What is the minimum reinforcement ratio for a slab?"
);Constructor: new LexicAutoGPT(config)
| Param | Type | Required | Description |
|---|---|---|---|
apiKey | string | Required | Lexic API key |
plugin | string | Required | Plugin slug to query |
baseUrl | string | Optional | Override API base URL |
commandName | string | Optional | AutoGPT command name. Default: "consult_{slug}" |
commandDescription | string | Optional | Command description for the agent |
queryOptions | QueryRequestOptions | Optional | Default query options (citationMode, maxSources, includeDecisionPath) |
Methods
asCommand(): AutoGPTCommandReturns an object with name, description, parameters, and execute — ready to register with AutoGPT.
execute(query: string): Promise<string>Execute a query directly. Returns a human-readable string with the answer, citations, and decision path.
setPlugin(slug: string): voidHot-swap which plugin this adapter queries.
Multi-Expert Collaboration
import { LexicCollaborationAutoGPT } from "lexic-sdk/autogpt";
const collabAdapter = new LexicCollaborationAutoGPT({
apiKey: "lx_your_api_key",
experts: ["structural-eng-v1", "geotech-v1"],
commandName: "consult_expert_panel",
commandDescription: "Ask multiple domain experts to debate and reach consensus",
mode: "debate",
maxRounds: 2,
onEvent: (event) => {
if (event.type === "expert_thinking") {
console.log(`${event.expertName}: ${event.message}`);
}
},
});
// Register as AutoGPT command
const command = collabAdapter.asCommand();
// Or execute directly
const answer = await collabAdapter.execute(
"Best foundation for a 5-story building on clay?"
);
// Change experts or mode at runtime
collabAdapter.setExperts(["structural-eng-v1", "fire-safety-v1"]);
collabAdapter.setMode("consensus");Constructor: new LexicCollaborationAutoGPT(config)
| Param | Type | Required | Description |
|---|---|---|---|
apiKey | string | Required | Lexic API key |
experts | string[] | Required | Array of 2–5 expert plugin slugs |
baseUrl | string | Optional | Override API base URL |
commandName | string | Optional | Command name. Default: "consult_expert_panel" |
commandDescription | string | Optional | Command description for the agent |
mode | CollaborationMode | Optional | "debate" (default), "consensus", or "review" |
maxRounds | number | Optional | Max deliberation rounds (1–3). Default: 3. |
onEvent | function | Optional | Callback for streaming events during collaboration |
Collaboration Methods
asCommand(): AutoGPTCommandReturns an AutoGPT command for the expert panel. Input is the query string.
execute(query: string): Promise<string>Execute collaboration directly. Returns human-readable text with consensus, conflicts, and per-expert contributions.
setExperts(slugs: string[]): voidChange the expert panel at runtime.
setMode(mode: CollaborationMode): voidSwitch between debate, consensus, and review modes.
TypeScript Types
All types are exported from lexic-sdk. Import them directly for type-safe integrations.
Configuration
interface LexicConfig {
apiKey: string;
baseUrl?: string;
defaultPlugin?: string;
timeout?: number;
}
interface QueryRequestOptions {
citationMode?: "inline" | "footnote" | "off";
maxSources?: number;
includeDecisionPath?: boolean;
}
interface QueryOptions {
plugin?: string;
query: string;
context?: Array<{ role: "user" | "assistant"; content: string }>;
options?: QueryRequestOptions;
}Query Response
interface QueryResult {
answer: string;
citations: Citation[];
decisionPath: DecisionStep[];
confidence: "high" | "medium" | "low";
pluginVersion: string;
}
interface Citation {
id: string;
document: string;
page?: number;
section?: string;
excerpt: string;
}
interface DecisionStep {
step: number;
node: string;
label: string;
value?: string;
result?: string;
}
interface LexicError {
error: string;
status?: number;
}Stream Events
type StreamEvent =
| { type: "status"; status: string; message: string; sourceCount?: number }
| { type: "delta"; text: string }
| { type: "done"; answer: string; citations: Citation[];
decisionPath: DecisionStep[];
confidence: "high" | "medium" | "low";
pluginVersion: string }
| { type: "error"; error: string };Collaboration
type CollaborationMode = "debate" | "consensus" | "review";
interface CollaborateOptions {
experts: string[];
query: string;
mode?: CollaborationMode;
maxRounds?: number;
}
interface ExpertResponse {
pluginSlug: string;
pluginName: string;
domain: string;
answer: string;
citations: Citation[];
confidence: "high" | "medium" | "low";
revised: boolean;
revisionNote?: string;
}
interface CollaborationRound {
roundNumber: number;
responses: ExpertResponse[];
}
interface ConflictEntry {
topic: string;
positions: Array<{ expert: string; stance: string }>;
resolved: boolean;
resolution?: string;
}
interface ConsensusResult {
answer: string;
confidence: "high" | "medium" | "low";
agreementLevel: number;
citations: Citation[];
conflicts: ConflictEntry[];
expertContributions: Array<{
expert: string;
domain: string;
keyPoints: string[];
}>;
}
interface CollaborationResult {
rounds: CollaborationRound[];
consensus: ConsensusResult;
latencyMs: number;
}Collaboration Stream Events
type CollaborationStreamEvent =
| { type: "status"; status: string; message: string }
| { type: "experts_resolved"; experts: Array<{
slug: string; name: string; domain: string;
sourceCount: number; hasDecisionTree: boolean
}> }
| { type: "round_start"; round: number; totalRounds: number }
| { type: "expert_thinking"; expert: string;
expertName: string; domain: string; message: string }
| { type: "expert_response"; round: number; expert: string;
expertName: string; domain: string; answer: string;
citations: Citation[];
confidence: "high" | "medium" | "low"; revised: boolean }
| { type: "round_complete"; round: number }
| { type: "done"; rounds: CollaborationRound[];
consensus: ConsensusResult; latencyMs: number }
| { type: "error"; error: string };Error Reference
All error responses follow the same shape. The SDK throws LexicAPIError with a status property.
{
"error": "Human-readable error message"
}Status Codes
| Code | Meaning | When |
|---|---|---|
| 200 | OK | Successful request |
| 201 | Created | Resource successfully created (plugin, document, key, tree, room) |
| 400 | Bad Request | Missing required fields, invalid JSON, query too long, <2 or >5 experts, invalid mode |
| 401 | Unauthorized | Missing/invalid API key or Clerk session |
| 403 | Forbidden | Plugin not published (for external query/collaborate endpoints) |
| 404 | Not Found | Plugin, document, tree, room, or API key not found |
| 408 | Timeout | SDK request exceeded timeout (default 30s) |
| 500 | Server Error | Internal error (LLM failure, database error, etc.) |
Ready to integrate?
Create your first plugin and start querying in under 5 minutes.