Demo API

Demo API

Public, unauthenticated endpoint for the landing page “Try it yourself” feature. Rate-limited per IP, restricted to the onboarding scenario only.

Endpoints

POST /api/v1/demo/chat

Send a natural-language query about the demo codebase (PostgreSQL 17.6).

Authentication: None (public endpoint) Rate limit: 30 requests/minute per IP

Request

{
  "query": "Where is the main function?",
  "language": "en"
}
Field Type Required Default Description
query string Yes Natural-language question (1-500 chars)
language string No "ru" Response language ("en" or "ru")

Response (200)

{
  "answer": "The main function is defined in src/backend/main/main.c at line 53...",
  "scenario_id": "onboarding",
  "processing_time_ms": 234.5
}
Field Type Description
answer string LLM-generated response
scenario_id string Always "onboarding" in demo mode
processing_time_ms float Server-side processing time

Error Responses

Status Cause Body
400 Query too long (>500 chars) {"detail": "Query exceeds maximum length"}
403 Off-topic or blocked query {"detail": "...", "examples": [...]}
429 Rate limit exceeded {"detail": "Too many requests"}
503 Demo mode disabled {"detail": "Demo endpoint is disabled"}

Off-Topic Response (403)

When a query is rejected as off-topic, the response includes helpful examples:

{
  "detail": "This query is outside the demo scope. Try questions about the codebase.",
  "examples": [
    "Where is heap_insert defined?",
    "Show the call graph for ExecProcNode",
    "How does MVCC work in PostgreSQL?"
  ]
}

GET /api/v1/demo/status

Check demo endpoint availability and configuration.

Authentication: None

Response (200)

{
  "enabled": true,
  "rate_limit": "30/minute",
  "max_query_length": 500,
  "allowed_scenarios": ["onboarding"]
}

Query Validation Pipeline

Incoming queries pass through a 4-stage validation pipeline:

1. HARD REJECT   explicit malicious content (regex patterns)
   └─ Returns 403 with blocked_content reason

2. WRONG SCENARIO  legitimate but outside onboarding scope
   └─ Returns 403 with scenario_name + examples

3. FAST ACCEPT  domain keywords detected (e.g., "function", "call graph")
   └─ Passes validation if keyword score  threshold

4. LLM JUDGE  ambiguous queries sent to YandexGPT Lite
   └─ Returns is_relevant + confidence score
   └─ Cached by MD5(query) for 1 hour

Caching

The demo endpoint caches responses to reduce LLM calls:

Cache Size TTL Key
Response cache 100 entries (LRU) 30 minutes normalize(query).lower()
LLM judge cache 1000 entries (LRU) 1 hour MD5(query.lower())

Configuration

config.yaml

api:
  demo:
    enabled: true                  # Enable/disable demo endpoint

Environment Variables

Variable Default Description
DEMO_ENABLED true Enable/disable demo endpoint
DEMO_RATE_LIMIT 30/minute Rate limit per IP

LLM Judge Settings

# Internal configuration (demo.py)
llm_judge:
  temperature: 0.1         # Low temperature for consistent decisions
  max_tokens: 50           # Short yes/no response
  model: yandexgpt-lite    # Lightweight model for fast decisions

Usage Examples

curl

# Valid query
curl -X POST http://localhost:8000/api/v1/demo/chat \
  -H "Content-Type: application/json" \
  -d '{"query": "How does MVCC work?", "language": "ru"}'

# Check status
curl http://localhost:8000/api/v1/demo/status

JavaScript (landing page)

const response = await fetch('/api/v1/demo/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    query: document.getElementById('demo-input').value,
    language: 'ru'
  })
});

if (response.ok) {
  const data = await response.json();
  showAnswer(data.answer);
} else if (response.status === 403) {
  const error = await response.json();
  showExamples(error.examples);
} else if (response.status === 429) {
  showRateLimit();
}

Security Considerations

  • No authentication — endpoint is publicly accessible
  • Rate limiting — 30 requests/minute per IP prevents abuse
  • Scenario restriction — only onboarding scenario allowed (no security analysis, file editing, etc.)
  • Query validation — 4-stage pipeline blocks malicious and off-topic queries
  • Read-only — no write operations possible through demo endpoint
  • Domain keywords — loaded from domain plugin, not hardcoded

Module: src/api/routers/demo.py Last updated: February 2026