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
onboardingscenario 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
Related Documentation¶
- REST API — full API reference
- Configuration Guide — environment setup
- Scenarios — S01 Onboarding scenario details
Module: src/api/routers/demo.py
Last updated: February 2026