Semantic Layer

The semantic layer translates between your database schema and business concepts. It defines entities, relationships, dimensions, measures, metrics, and filters that enable accurate natural language querying.

Components

ComponentWhat it representsExample
EntityA core business object (table or view)customers, orders, products
RelationshipHow entities connect to each otherorders.customer_id -> customers.id
DimensionA way to group or segment dataregion, product_category, signup_month
MeasureA numeric value to aggregateorder_total, quantity, duration
MetricA calculated business KPI built from measuresmonthly_revenue, churn_rate
FilterA reusable data scoping ruleactive_customers, last_90_days

Generate components

Each component type has a streaming generation endpoint that uses AI to analyze your schema and suggest components.

Required scope: semantic:generate

POST /api/v1/semantic/{component}/generate/stream

Where {component} is one of: entities, relationships, dimensions, measures, metrics, filters.

Example: generate entities

curl -N -X POST https://app.answerlayer.io/api/v1/semantic/entities/generate/stream \
  -H "X-API-Key: $ANSWERLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
    "prompt": "Generate entities for our e-commerce database"
  }'

List components

Required scope: semantic:read

GET /api/v1/semantic/{component}?connection_id={uuid}

Returns all components of the given type for a connection.

CRUD operations

Required scope: semantic:write (create, update, delete) or semantic:read (get)

OperationMethodPath
CreatePOST/api/v1/semantic/{component}
Get by IDGET/api/v1/semantic/{component}/{id}
UpdatePUT/api/v1/semantic/{component}/{id}
DeleteDELETE/api/v1/semantic/{component}/{id}

Generation jobs

Generation is a long-running, interactive process. The agent analyzes your schema, but periodically needs human input to make decisions — for example, choosing which tables represent core entities, or clarifying business logic for a metric definition. This human-in-the-loop pattern is called guidance.

Job lifecycle

QUEUED → RUNNING → AWAITING_GUIDANCE → RUNNING → ... → COMPLETED
                                                    └→ FAILED
                                                    └→ CANCELLED
  1. Create a job — status starts as queued
  2. Stream the job — connects via SSE, agent starts running
  3. Agent hits a decision point — status moves to awaiting_guidance, the stream emits a guidance_needed event with questions
  4. Poll questions or read from the stream to get what the agent is asking
  5. Provide guidance — submit answers, agent unblocks and continues automatically
  6. Steps 3-5 repeat until the agent completes or fails

Endpoints

OperationMethodPathScope
Create jobPOST/api/v1/semantic/jobssemantic:generate
Stream jobGET/api/v1/semantic/jobs/{id}/streamsemantic:generate
Get pending questionsGET/api/v1/semantic/jobs/{id}/questionssemantic:read
Provide guidancePOST/api/v1/semantic/jobs/{id}/guidancesemantic:generate
Get job statusGET/api/v1/semantic/jobs/{id}/statussemantic:read
List jobsGET/api/v1/semantic/jobssemantic:read
Cancel jobPOST/api/v1/semantic/jobs/{id}/cancelsemantic:generate

Create a job

curl -X POST https://app.answerlayer.io/api/v1/semantic/jobs \
  -H "X-API-Key: $ANSWERLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
    "component_type": "entities",
    "prompt": "Focus on the e-commerce tables, ignore internal audit tables"
  }'

component_type is one of: entities, relationships, dimensions, measures, metrics, filters.

The optional prompt field provides business context that guides the agent’s decisions.

Returns 409 Conflict if an active job already exists for this connection and component type.

Stream a job

curl -N https://app.answerlayer.io/api/v1/semantic/jobs/{job_id}/stream \
  -H "X-API-Key: $ANSWERLAYER_API_KEY"

Returns an SSE stream. Event types include:

Event typeMeaning
progressAgent is working — includes a summary of what it’s doing
guidance_neededAgent is blocked and needs human input (see below)
completeGeneration finished successfully
errorGeneration failed

Handling guidance

When the stream emits a guidance_needed event, the job is paused. The event payload contains the questions:

{
  "type": "guidance_needed",
  "job_id": "abc-123",
  "questions": [
    {
      "question_id": "q1",
      "question": "Should 'audit_log' be treated as a core entity or excluded?",
      "context": "This table has 50M rows and is referenced by 3 other tables.",
      "options": ["Include as entity", "Exclude"],
      "allow_freeform": true
    }
  ]
}

You can also poll for pending questions:

curl https://app.answerlayer.io/api/v1/semantic/jobs/{job_id}/questions \
  -H "X-API-Key: $ANSWERLAYER_API_KEY"

Submit answers to resume the agent:

curl -X POST https://app.answerlayer.io/api/v1/semantic/jobs/{job_id}/guidance \
  -H "X-API-Key: $ANSWERLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "responses": [
      {"question_id": "q1", "answer": "Exclude -- this is an internal audit table"}
    ]
  }'

The agent unblocks immediately and continues. No restart or reconnect is needed — the SSE stream resumes with new progress events.

Integration patterns

Interactive UI: Surface the questions in your admin dashboard. An operator reviews and answers them. This is how the AnswerLayer dashboard works.

Automated: Use an LLM or rules engine to answer the guidance questions programmatically. The questions include context and often predefined options, so automated responses are feasible for many cases.