---
title: "Unified query with automatic routing"
method: POST
path: "/pots/{pot_id}/query"
tags: ["query", "query"]
---

# Unified query with automatic routing

`POST /pots/{pot_id}/query`

Execute a unified query against a POT with automatic strategy selection.

**How it works:**
1. Classifies query (factual → CAG, semantic → RAG, relational → GraphRAG)
2. Executes optimal strategy first
3. Automatically falls back to RAG if CAG insufficient
4. Returns results with routing metadata

**Strategies:**
- `auto` (default): Automatic selection based on query classification
- `cag`: Force CAG-only (fast, keyword-based)
- `rag`: Force RAG-only (semantic search with embeddings)
- `graph_rag`: Force GraphRAG (graph traversal for relational queries)

**Fallback Logic:**
When `enable_fallback=true` and `strategy=auto`:
- If CAG returns `suggestion != "sufficient"`, executes RAG
- If classification confidence is low, prefers RAG
- Metadata shows which strategy was actually used

**Latency:**
- CAG-only: ~50ms
- RAG: ~500ms
- CAG with fallback: ~550ms
- GraphRAG: ~200-800ms (depends on graph density)

## Path parameters

- `pot_id` string, required — POT identifier (UUID or slug)

## Request body

- QueryRequest — Request body for unified query endpoint.
  - `query` string, required — Query text for retrieval
  - `top_k` integer — Maximum results to return
  - `strategy` 'auto' | 'cag' | 'rag' | 'graph_rag' — Force strategy or auto-select based on query classification
  - `enable_fallback` boolean — Allow automatic fallback from CAG to RAG when results insufficient
  - `filters` ScipotApiSchemasQuerySearchFiltersRequest — Optional post-retrieval filters.
    - `domain` string, nullable — Filter by domain (exact match)
    - `levels` PotScoreLevel[], nullable — Filter by POT Index levels (any match)
    - `tags` string[], nullable — Must have ALL tags (AND logic)
  - `include_edges` boolean — Include edge context (contradictions, relationships) in response
  - `include_stances` boolean — Include stance summaries for contradiction edges (requires include_edges=True)

## Response `200`

Successful query

- QueryResponse — Full query response.
  - `data` QueryDataResponse, required — Results data wrapper.
    - `results` QueryResultItem[] — Ranked query results
      - `fact_id` string, required — Unique identifier of the fact
      - `content` string, required — Full fact content
      - `title` string, nullable — Short title for display (M19)
      - `score` number, required — Combined match score [0-1]
      - `pot_score` number, required — POT Index certainty score [0-1]
      - `original_pot_score` number, nullable — Pre-propagation POT Score (M19). None if not propagated.
      - `level` 'CONSTITUTION' | 'VERIFIED' | 'SUPPORTED' | 'INFERRED' | 'HYPOTHESIS' | 'SPECULATION', required — POT Index levels matching score ranges.
      - `source` 'cag' | 'rag' | 'graph_rag', required — Which retrieval strategy produced this result
      - `match_details` object, required — Strategy-specific match details
      - `domain` string, nullable — Fact domain classification
      - `tags` string[] — Classification tags
      - `document_id` string, nullable — Source document UUID (M19)
      - `edges` QueryEdgeItem[] — Edges connecting this fact to other returned facts
        - `from_fact_id` string, required — Source fact ID
        - `to_fact_id` string, required — Target fact ID
        - `type` string, required — Edge type (supports, contradicts, etc.)
        - `weight` number, required — Relationship strength
        - `rationale` string — Why this relationship exists
        - `peer_fact_id` string, nullable — The other fact's ID (the one NOT in this result item)
        - `peer_content_snippet` string, nullable — Snippet of the peer fact content (~150 chars) for context
        - `peer_pot_score` number, nullable — POT Score of the peer fact, for trust weighting
        - `resolution_type` string, nullable — Resolution type if edge is resolved (confirmed_a, confirmed_b, both_valid, etc.)
        - `resolution_notes` string, nullable — Notes about the resolution
    - `total_results` integer, required — Total results returned
    - `edges_context` QueryEdgesContext — Edge context for returned facts — contradictions, relationships, and type counts.
      - `total_edges` integer — Total relevant edges found
      - `edges` QueryEdgeItem[] — All edges connecting returned facts
        - `from_fact_id` string, required — Source fact ID
        - `to_fact_id` string, required — Target fact ID
        - `type` string, required — Edge type (supports, contradicts, etc.)
        - `weight` number, required — Relationship strength
        - `rationale` string — Why this relationship exists
        - `peer_fact_id` string, nullable — The other fact's ID (the one NOT in this result item)
        - `peer_content_snippet` string, nullable — Snippet of the peer fact content (~150 chars) for context
        - `peer_pot_score` number, nullable — POT Score of the peer fact, for trust weighting
        - `resolution_type` string, nullable — Resolution type if edge is resolved (confirmed_a, confirmed_b, both_valid, etc.)
        - `resolution_notes` string, nullable — Notes about the resolution
      - `contradictions` ContradictionPair[] — Contradiction pairs with POT scores for trust weighting
        - `fact_a_id` string, required — First fact ID
        - `fact_a_content_snippet` string, required — First ~150 chars of fact A
        - `fact_a_pot_score` number, required
        - `fact_b_id` string, required — Second fact ID
        - `fact_b_content_snippet` string, required — First ~150 chars of fact B
        - `fact_b_pot_score` number, required
        - `weight` number, required — Contradiction strength
        - `rationale` string — Why these facts contradict
        - `edge_id` string, nullable — Edge ID for stance/resolution operations
        - `stances_summary` StancesSummary — Summary of stances on a contradiction edge.
          - `confirm_a_count` integer — Stances confirming fact A (from_id)
          - `confirm_b_count` integer — Stances confirming fact B (to_id)
          - `dismiss_count` integer — Stances dismissing the contradiction
          - `total` integer — Total stances
          - `latest_stances` ContradictionStance[] — Most recent stances (up to 10)
            - `id` string, uuid — Unique stance record ID
            - `edge_id` string, required — Edge this stance is about
            - `pot_id` string, uuid, required — POT the edge belongs to
            - `stance` 'confirm_a' | 'confirm_b' | 'dismiss', required — Types of stances a user can take on a contradiction edge.
            - `contributor` ContributorProfile, required — Profile of a knowledge contributor or curator. Sent by the integrator (KB2B) alongside contributions and curations. SciPot does NOT store user profiles — it evaluates expertise per-request.
              - …
            - `contributor_id` string, uuid, nullable — Contributor registry ID (if registered)
            - `expertise_evaluation` ExpertiseEvaluation, required — Result of evaluating a contributor's expertise relative to a fact's domain.
              - …
            - `notes` string, nullable — Reasoning for the stance
            - `score_delta` number — Score change applied to affected fact
            - `score_before` number — POT Score before stance
            - `score_after` number — POT Score after stance
            - `affected_fact_id` string, uuid, nullable — Fact whose score was affected (None for dismiss)
            - `opposing_score_delta` number — Score change applied to opposing fact
            - `opposing_fact_id` string, uuid, nullable — Opposing fact whose score was penalized
            - `created_at` string, date-time — When stance was submitted
        - `resolution_type` string, nullable — Resolution type (confirmed_a, confirmed_b, both_valid, needs_update, dismissed)
        - `resolution_notes` string, nullable — Notes explaining the resolution
        - `winner_fact_id` string, nullable — The fact confirmed correct (convenience field derived from resolution_type)
      - `contradiction_count` integer — Number of active contradictions
      - `resolved_contradictions` ContradictionPair[] — Resolved contradiction pairs with resolution metadata
        - `fact_a_id` string, required — First fact ID
        - `fact_a_content_snippet` string, required — First ~150 chars of fact A
        - `fact_a_pot_score` number, required
        - `fact_b_id` string, required — Second fact ID
        - `fact_b_content_snippet` string, required — First ~150 chars of fact B
        - `fact_b_pot_score` number, required
        - `weight` number, required — Contradiction strength
        - `rationale` string — Why these facts contradict
        - `edge_id` string, nullable — Edge ID for stance/resolution operations
        - `stances_summary` StancesSummary — Summary of stances on a contradiction edge.
          - `confirm_a_count` integer — Stances confirming fact A (from_id)
          - `confirm_b_count` integer — Stances confirming fact B (to_id)
          - `dismiss_count` integer — Stances dismissing the contradiction
          - `total` integer — Total stances
          - `latest_stances` ContradictionStance[] — Most recent stances (up to 10)
            - `id` string, uuid — Unique stance record ID
            - `edge_id` string, required — Edge this stance is about
            - `pot_id` string, uuid, required — POT the edge belongs to
            - `stance` 'confirm_a' | 'confirm_b' | 'dismiss', required — Types of stances a user can take on a contradiction edge.
            - `contributor` ContributorProfile, required — Profile of a knowledge contributor or curator. Sent by the integrator (KB2B) alongside contributions and curations. SciPot does NOT store user profiles — it evaluates expertise per-request.
              - …
            - `contributor_id` string, uuid, nullable — Contributor registry ID (if registered)
            - `expertise_evaluation` ExpertiseEvaluation, required — Result of evaluating a contributor's expertise relative to a fact's domain.
              - …
            - `notes` string, nullable — Reasoning for the stance
            - `score_delta` number — Score change applied to affected fact
            - `score_before` number — POT Score before stance
            - `score_after` number — POT Score after stance
            - `affected_fact_id` string, uuid, nullable — Fact whose score was affected (None for dismiss)
            - `opposing_score_delta` number — Score change applied to opposing fact
            - `opposing_fact_id` string, uuid, nullable — Opposing fact whose score was penalized
            - `created_at` string, date-time — When stance was submitted
        - `resolution_type` string, nullable — Resolution type (confirmed_a, confirmed_b, both_valid, needs_update, dismissed)
        - `resolution_notes` string, nullable — Notes explaining the resolution
        - `winner_fact_id` string, nullable — The fact confirmed correct (convenience field derived from resolution_type)
      - `resolved_contradiction_count` integer — Number of resolved contradictions
      - `edges_by_type` object — Edge count by type (e.g. {'supports': 3, 'contradicts': 1})
  - `metadata` QueryMetadataResponse, required — Routing metadata - aligned with RoutingMetadata from router spec. Provides transparency into routing decisions for debugging/monitoring.
    - `strategy_used` 'cag' | 'rag' | 'cag_with_rag_fallback' | 'graph_rag', required — Final strategy used
    - `classification` union, required — Query classification details
      - ClassificationResponse — Query classification details.
        - `category` string, required — Query category (factual, semantic, relational, unknown)
        - `confidence` number, required — Classification confidence [0-1]
        - `suggested_strategy` string, required — Strategy suggested by classifier
        - `reasoning` string[] — Explanation of classification decision
      - object
    - `cag_attempted` boolean, required — Whether CAG was attempted
    - `cag_suggestion` string, nullable — CAG confidence suggestion (sufficient, consider_rag, no_match)
    - `cag_results_count` integer, required — Number of CAG results (before fallback)
    - `fallback_triggered` boolean, required — Whether fallback to RAG was triggered
    - `fallback_reason` string, nullable — Reason for fallback (if triggered)
    - `total_duration_ms` integer, required — Total request duration in milliseconds
    - `cag_duration_ms` integer, required — CAG retrieval duration in milliseconds
    - `rag_duration_ms` integer, required — RAG retrieval duration in milliseconds
    - `graphrag_duration_ms` integer — GraphRAG retrieval duration in milliseconds
    - `traversal_metadata` object, nullable — GraphRAG traversal statistics (seeds, nodes, edges)
  - `is_knowledge_gap` boolean, required — Convenience flag: true when retrieval likely hit a knowledge gap (gap_signal.confidence < threshold). The integrator decides whether to act on it.
  - `gap_signal` GapSignal, required — Structured gap signal attached to a synthesis response.
    - `version` string, required — Formula version; pin behaviour against this.
    - `confidence` number, required — Confidence the answer is grounded (higher = better).
    - `is_knowledge_gap` boolean, required — True when confidence < threshold — a candidate gap to escalate.
    - `threshold` number, required — Threshold applied to confidence.
    - `total_facts` integer, required — Facts retrieved for synthesis.
    - `high_certainty_facts` integer, required — Count of Constitution + Verified facts among them.
    - `average_score` number, required — Mean POT Score of retrieved facts.
    - `reasons` string[] — Human-readable factors behind the score.

## Other responses

- `400` — Invalid query parameters
- `403` — Access denied to POT
- `404` — POT not found
- `422` — Validation Error
- `500` — Internal error
- `501` — Strategy not available (e.g., graph_rag)

---

[API](https://skmtc.dev/scipot/apis/scipot-core-api.md) · [All operations](https://skmtc.dev/scipot/apis/scipot-core-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/scipot/scipot-core-api/revisions/e8712e9ffeae/schema)
