Liya Engine
Guides

Custom Domain Walkthrough

End-to-end guide to building and deploying a custom AI domain pack.

This guide walks through creating a custom domain pack from scratch — defining the domain, adding intents, uploading knowledge sources, and making your first API call.

We'll build a legal_contracts domain as the example.


Step 1: Create the domain

POST https://api.liyaengine.ai/dashboard/custom-domains
Authorization: Bearer <jwt>
Content-Type: application/json
 
{
  "domainKey": "legal_contracts",
  "displayName": "Legal Contracts",
  "description": "Contract review, clause extraction, and risk analysis",
  "systemPrompt": "You are a legal assistant specialised in contract analysis. You help users review, summarise, and extract key clauses from commercial contracts. Always cite the relevant clause when making observations. Do not provide legal advice — present findings factually."
}

domainKey becomes the path segment in API calls: POST /v1/legal_contracts/{intent}.


Step 2: Define intents

Each intent maps a business action to a prompt template. Variables in {{double_braces}} become input fields.

Clause extraction

POST https://api.liyaengine.ai/dashboard/custom-domains/legal_contracts/intents
Authorization: Bearer <jwt>
Content-Type: application/json
 
{
  "intentKey": "clause_extraction",
  "displayName": "Clause Extraction",
  "promptTemplate": "Extract all {{clause_type}} clauses from the following contract. For each clause, provide:\n- The exact clause text\n- Section reference\n- Plain English summary\n\nContract:\n{{contract_text}}"
}

Contract summary

POST https://api.liyaengine.ai/dashboard/custom-domains/legal_contracts/intents
Authorization: Bearer <jwt>
Content-Type: application/json
 
{
  "intentKey": "contract_summary",
  "displayName": "Contract Summary",
  "promptTemplate": "Summarise the following {{contract_type}} contract. Include:\n- Parties involved\n- Key obligations of each party\n- Payment terms\n- Duration and termination conditions\n- Notable risks or unusual clauses\n\nContract:\n{{contract_text}}"
}

Risk analysis

POST https://api.liyaengine.ai/dashboard/custom-domains/legal_contracts/intents
Authorization: Bearer <jwt>
Content-Type: application/json
 
{
  "intentKey": "risk_analysis",
  "displayName": "Risk Analysis",
  "promptTemplate": "Analyse the following contract for potential risks from the perspective of {{party_role}}.\n\nIdentify:\n- High-risk clauses\n- Missing standard protections\n- Unusual or one-sided terms\n- Recommended amendments\n\nContract:\n{{contract_text}}"
}

Step 3: Upload knowledge sources (optional)

If you have a library of standard clauses, precedent contracts, or clause definitions, upload them as knowledge sources to enable RAG.

First, enable RAG for your account:

PATCH https://api.liyaengine.ai/dashboard/account/config
Authorization: Bearer <jwt>
Content-Type: application/json
 
{
  "featureConfig": { "enable_rag": true }
}

Then upload sources via the Knowledge dashboard section. Tag them with the legal_contracts domain so they're scoped correctly.


Step 4: Call your custom domain

Your custom intents are called exactly like built-in intents:

POST https://api.liyaengine.ai/v1/legal_contracts/clause_extraction
X-API-Key: liya_prod_...
Content-Type: application/json
 
{
  "input": {
    "clause_type": "indemnification",
    "contract_text": "INDEMNIFICATION. Each party (as 'Indemnifying Party') shall defend, indemnify, and hold harmless the other party..."
  },
  "options": {
    "session_id": "sess_01HZ..."
  }
}

Response:

{
  "success": true,
  "sessionId": "sess_01HZ...",
  "intent": "clause_extraction",
  "output": {
    "response": "I found 2 indemnification clauses:\n\n**Clause 1 — Section 8.1**\n> Each party shall defend, indemnify...\n\n**Plain English:** Both parties agree to protect each other from losses arising from their own actions."
  },
  "usage": {
    "inputTokens": 380,
    "outputTokens": 520,
    "totalTokens": 900,
    "costUsd": "0.000450"
  }
}

Step 5: Use sessions for multi-step review

Chain intents in a session for a complete review workflow:

# 1. Summary
POST /v1/legal_contracts/contract_summary
{ "input": { "contract_type": "SaaS", "contract_text": "..." } }
# → sessionId: "sess_review_01"
 
# 2. Extract key clauses (same session — engine has full summary context)
POST /v1/legal_contracts/clause_extraction
{ "input": { "clause_type": "termination", ... }, "options": { "session_id": "sess_review_01" } }
 
# 3. Risk analysis (engine knows what was extracted)
POST /v1/legal_contracts/risk_analysis
{ "input": { "party_role": "vendor", ... }, "options": { "session_id": "sess_review_01" } }

Tips

  • Keep system prompts focused — the domain system prompt applies to all intents. Intent-specific instructions go in the promptTemplate.
  • Variable names matter — use descriptive names (contract_text, not text) as they become self-documenting input fields.
  • Test with short contracts first — iterate on prompt quality before processing large documents.
  • Use sessions — the engine builds context across calls, making later intents in a review session smarter.

For full API reference see Custom Domains API.

On this page