---
title: "Everything a client reads to answer one question, in one request"
method: POST
path: "/pots/{pot_id}/ask-context"
tags: ["search"]
---

# Everything a client reads to answer one question, in one request

`POST /pots/{pot_id}/ask-context`

## Request

- Base URL: `https://api.scipot.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.scipot.ai/pots/{pot_id}/ask-context`
- Auth: none declared
- TypeScript: <https://skmtc.dev/scipot/apis/scipot-core-api/docs/pots/:pot_id/ask-context/post.ts> (a function with typed inputs; its response is checked against the schema)

Search, each result's read and edges, the repeal listing, the counterparts of the
results' clashes and repeals, their documents (no text), the curations of each clash
side, the source types, the rules (in ``pot``) and the POT's related open gaps.

The engine gathers; it does not judge. Each section is the body of its standalone route.
A section whose reads fail is named in ``meta.partial``; only search failing fails this.

## Path parameters

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

## Request body

- AskContextRequest: ``/search``'s request, plus the template language and the limits. ``include_content`` is ignored: each fact's text is in ``facts``, never twice.
  - `query` string, required: Natural language search query
  - `top_k` integer: Maximum number of results to return
  - `min_pot_score` number: Minimum POT Index threshold for results
  - `min_similarity` number, nullable: Drop results whose raw similarity to the query is below this. Omitted = the server default (SEARCH_MIN_SIMILARITY, 0.20). 0 returns everything, as before.
  - `relative_cutoff` number, nullable: Also drop results whose similarity is below this fraction of the best result's (e.g. 0.6 keeps those at least 60% as similar as the top one). Omitted = off.
  - `filters` ScipotApiSchemasSearchSearchFiltersRequest: Optional post-retrieval filters. Filters are applied after vector search for flexibility: - domain: Exact match on domain - level: Any of these levels (OR logic) - tags: Must have ALL tags (AND logic)
    - `domain` string, nullable: Filter by domain (exact match)
    - `level` string[], nullable: Filter by POT Index levels (OR logic)
    - `tags` string[], nullable: Filter by tags (AND logic - must have ALL)
  - `as_of` string, date, nullable: Day to judge validity on (ISO 8601). Each result says whether it is in force that day (currency); nothing is excluded. Omitted = today (UTC). A future day answers what will be in force then.
  - `include_content` boolean: Include full fact content in results (set false for compact response)
  - `language` string, nullable: Language of the source-type template labels (es, en, ca; else en).
  - `limits` AskContextLimits: How much of each section the engine gathers (MaBrain's defaults).
    - `counterparts` integer: Other sides of clashes and repeals the results left out.
    - `gaps` integer: Related open gaps returned.
    - `curations` integer: Clash sides whose curations are read.

## Response `200`

Successful Response

- AskContextResponse
  - `pot` POTResponse, required: POT for API responses.
    - `id` string, uuid, required
    - `slug` string, required
    - `workspace_id` string, uuid, required
    - `name` string, required
    - `description` string, required
    - `domain` string: Knowledge domain of the POT (from config.pot.domain). Exposed so clients — e.g. `scipot pot export` — can round-trip it; the coverage-gap routing key derives from it.
    - `constitution` ConstitutionResponse, required: Constitution for API responses.
      - `facts` ConstitutionFactResponse[], required
        - `id` string, required
        - `content` string, required
        - `title` string, nullable
        - `pot_score` number, required
        - `level` string, required
        - `rationale` string, nullable
        - `keywords` string[]
        - `active` boolean: False when deactivated: operations skip the axiom
        - `deactivated_at` string, nullable
        - `deactivation_reason` string, nullable
        - `kind` 'fact' | 'rule' | 'scope': What a constitution axiom states, and so what edge detection does with it. ``fact`` (the default, and what every axiom stored before v0.7.53.0 is) and ``rule`` are claims about the POT's domain: a new fact can support or contradict them. ``scope`` axioms describe the POT itself ("This brain only knows about X", "Answers cite their source"): no fact can contradict them, so they never enter axiom↔fact edge detection and never move a POT Score.
      - `version` string
      - `last_updated` string, required
      - `approved_by` string, required
      - `fact_count` integer, required
      - `active_count` integer: Axioms operations take into account
    - `about` POTAboutView: The POT's «about» as everyone with access reads it (v0.7.106.0). One or two sentences that say what the POT knows, kept up to date by the engine after each ingestion (``generated``) or written by the owner (``manual``, never rewritten). Not the ``description`` (the extraction mission), which it never touches.
      - `text` string, nullable: None: nothing written yet
      - `source` 'generated' | 'manual', nullable
      - `updated_at` string, date-time, nullable
      - `suggestion_pending` boolean: A manual text whose POT has since gained a subject it does not cover: the owner may write it again or go back to the generated one.
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
  - `search` object, required: POST /pots/{id}/search's body (no content).
  - `facts` object, required: GET /pots/{id}/facts/{fid} for each result, then each counterpart.
  - `edges` Edge[], required: Every edge from or to a result (edges/from + edges/to), deduplicated.
    - `id` string, required: Unique edge identifier
    - `pot_id` string, uuid, required: POT this edge belongs to
    - `workspace_id` string, uuid, required: Workspace this edge belongs to
    - `from_id` string, uuid, required: Source fact ID (A in A → B)
    - `to_id` string, uuid, required: Target fact ID (B in A → B)
    - `type` 'supports' | 'contradicts' | 'resolved_contradiction' | 'refines' | 'derives_from' | 'is_part_of' | 'extends' | 'cites' | 'related_to' | 'supersedes' | 'restates', required: Types of semantic relationships between facts. M7 uses a simplified subset. Full taxonomy in edge-types.md will be implemented in M8+ when GraphRAG is introduced.
    - `weight` number, required: Confidence in relationship (0.0-1.0)
    - `rationale` string: Brief explanation of why this relationship exists
    - `detected_by` string: Detector/model that identified this edge
    - `companion_of` string, nullable: Supersedes edge id this contradicts edge was stored beside. Set only on the companion created with a repeal; a later run may rewrite that repeal's rationale without touching this tag.
    - `episode_id` string, nullable: The episode whose window created this edge (point 6, the seal): a POST /edges sent with X-Episode-ID, or the edges a sealed write's post-ingestion created. Set when the edge is created and never changed; a rerun that rewrites the edge keeps it. Never read by scoring or propagation.
    - `confidence` number: Detection confidence (0.0-1.0)
    - `judge` string, nullable: The near-duplicate judge that decided a restates edge, as <backend>:<model> (decisions:gpt-6-luna, bedrock:<model id>). Null on every other edge.
    - `partial` boolean, nullable: Restates edges since v0.7.105.0: true when the restating fact repeats only part of its target. The facts split from one passage were judged together against it, and the group repeats the target; each one alone gives only a piece. Still not independent evidence. Null on every other edge and on whole restatements.
    - `shared_figures` integer, nullable: Restates edges since v0.7.104.0: how many figures (amounts, dates, counts) the restating fact and its target both give. First key of the restates_all order. Null on every other edge and on older restates edges.
    - `similarity` number, nullable: Restates edges since v0.7.104.0: the similarity deduplication ranked the pair by (the higher of wording and meaning, 0-1). Second key of the restates_all order. Null on every other edge and on older restates edges.
    - `validation_status` string: Validation status (auto-approved, pending, validated, rejected)
    - `decided_by` string, nullable: Who approved or rejected a repeal: a contributor id, or integrator:<id>
    - `decided_at` string, date-time, nullable: When a curator approved or rejected a repeal
    - `resolution_type` string, nullable: Resolution type (confirmed_a, confirmed_b, both_valid, needs_update, dismissed)
    - `resolved_by_name` string, nullable: Name of the person who resolved the contradiction
    - `resolved_by_role` string, nullable: Role of the person who resolved the contradiction
    - `resolved_by_contributor_id` string, uuid, nullable: Contributor registry ID of the person who resolved the contradiction
    - `resolved_at` string, date-time, nullable: When the contradiction was resolved
    - `resolution_notes` string, nullable: Notes about the resolution
    - `resolution_score_shifts` object, nullable: POT Score delta actually applied to each fact by this resolution, keyed by fact id. Revert undoes these amounts.
    - `kind` 'express' | 'tacit' | 'partial' | 'hierarchy' | 'suspension' | 'extension' | 'manual', nullable: How the repeal came about: express, partial, tacit, hierarchy, manual, suspension or extension. An edge stored before 0.7.57.0 reads manual when a person created it (detected_by manual) and express otherwise.
    - `basis` string, nullable: What the repeal rests on: passage (the replacing fact's own text and document), curator, or rule:<id> (a precedence rule of the POT).
    - `scope_section` string, nullable: The section of the older document the repeal is limited to, when it cites one.
    - `effective_at` string, date, nullable: Day the repeal takes effect, when a person states it. Null = from the replacing fact's valid_from (or the day the edge was stored).
    - `resume_at` string, date, nullable: For a suspension: the day the older fact applies again. Null = open.
    - `applied_at` string, date-time, nullable: When the repeal started retiring its target in SciPot (transaction time). Written once: when the edge is stored as auto-approved, or when a curator first validates it. Never moved by a later decision.
    - `axiom_conflict` string[], nullable: Set when detection held this repeal for a curator because applying it may contradict an active constitution axiom or rule (the axiom veto, 0.7.88.0): the ids of those axioms, empty when the check could not name one (it failed or doubted). Null = never held. A re-detection never turns a held repeal back to auto-approved; a curator's validated lifts the hold.
    - `axiom_hold` 'conflict' | 'unverified', nullable: Why the axiom veto holds this repeal: `conflict` (an open contradiction with an axiom, or the check judged one, or doubted) stays until a curator validates the repeal; `unverified` (the check could not be completed: unreadable facts or edges, a timeout, an error, an ambiguous answer) is lifted by a later detection whose check answers clear. Null = never held; a hold stored without a reason reads as `conflict`.
    - `created_at` string, date-time, nullable
    - `updated_at` string, date-time, nullable
  - `counterparts` string[], required: Fact ids added beyond the results.
  - `supersedes` EdgeListResponse: Response for list edges endpoint.
    - `edges` Edge[], required
      - `id` string, required: Unique edge identifier
      - `pot_id` string, uuid, required: POT this edge belongs to
      - `workspace_id` string, uuid, required: Workspace this edge belongs to
      - `from_id` string, uuid, required: Source fact ID (A in A → B)
      - `to_id` string, uuid, required: Target fact ID (B in A → B)
      - `type` 'supports' | 'contradicts' | 'resolved_contradiction' | 'refines' | 'derives_from' | 'is_part_of' | 'extends' | 'cites' | 'related_to' | 'supersedes' | 'restates', required: Types of semantic relationships between facts. M7 uses a simplified subset. Full taxonomy in edge-types.md will be implemented in M8+ when GraphRAG is introduced.
      - `weight` number, required: Confidence in relationship (0.0-1.0)
      - `rationale` string: Brief explanation of why this relationship exists
      - `detected_by` string: Detector/model that identified this edge
      - `companion_of` string, nullable: Supersedes edge id this contradicts edge was stored beside. Set only on the companion created with a repeal; a later run may rewrite that repeal's rationale without touching this tag.
      - `episode_id` string, nullable: The episode whose window created this edge (point 6, the seal): a POST /edges sent with X-Episode-ID, or the edges a sealed write's post-ingestion created. Set when the edge is created and never changed; a rerun that rewrites the edge keeps it. Never read by scoring or propagation.
      - `confidence` number: Detection confidence (0.0-1.0)
      - `judge` string, nullable: The near-duplicate judge that decided a restates edge, as <backend>:<model> (decisions:gpt-6-luna, bedrock:<model id>). Null on every other edge.
      - `partial` boolean, nullable: Restates edges since v0.7.105.0: true when the restating fact repeats only part of its target. The facts split from one passage were judged together against it, and the group repeats the target; each one alone gives only a piece. Still not independent evidence. Null on every other edge and on whole restatements.
      - `shared_figures` integer, nullable: Restates edges since v0.7.104.0: how many figures (amounts, dates, counts) the restating fact and its target both give. First key of the restates_all order. Null on every other edge and on older restates edges.
      - `similarity` number, nullable: Restates edges since v0.7.104.0: the similarity deduplication ranked the pair by (the higher of wording and meaning, 0-1). Second key of the restates_all order. Null on every other edge and on older restates edges.
      - `validation_status` string: Validation status (auto-approved, pending, validated, rejected)
      - `decided_by` string, nullable: Who approved or rejected a repeal: a contributor id, or integrator:<id>
      - `decided_at` string, date-time, nullable: When a curator approved or rejected a repeal
      - `resolution_type` string, nullable: Resolution type (confirmed_a, confirmed_b, both_valid, needs_update, dismissed)
      - `resolved_by_name` string, nullable: Name of the person who resolved the contradiction
      - `resolved_by_role` string, nullable: Role of the person who resolved the contradiction
      - `resolved_by_contributor_id` string, uuid, nullable: Contributor registry ID of the person who resolved the contradiction
      - `resolved_at` string, date-time, nullable: When the contradiction was resolved
      - `resolution_notes` string, nullable: Notes about the resolution
      - `resolution_score_shifts` object, nullable: POT Score delta actually applied to each fact by this resolution, keyed by fact id. Revert undoes these amounts.
      - `kind` 'express' | 'tacit' | 'partial' | 'hierarchy' | 'suspension' | 'extension' | 'manual', nullable: How the repeal came about: express, partial, tacit, hierarchy, manual, suspension or extension. An edge stored before 0.7.57.0 reads manual when a person created it (detected_by manual) and express otherwise.
      - `basis` string, nullable: What the repeal rests on: passage (the replacing fact's own text and document), curator, or rule:<id> (a precedence rule of the POT).
      - `scope_section` string, nullable: The section of the older document the repeal is limited to, when it cites one.
      - `effective_at` string, date, nullable: Day the repeal takes effect, when a person states it. Null = from the replacing fact's valid_from (or the day the edge was stored).
      - `resume_at` string, date, nullable: For a suspension: the day the older fact applies again. Null = open.
      - `applied_at` string, date-time, nullable: When the repeal started retiring its target in SciPot (transaction time). Written once: when the edge is stored as auto-approved, or when a curator first validates it. Never moved by a later decision.
      - `axiom_conflict` string[], nullable: Set when detection held this repeal for a curator because applying it may contradict an active constitution axiom or rule (the axiom veto, 0.7.88.0): the ids of those axioms, empty when the check could not name one (it failed or doubted). Null = never held. A re-detection never turns a held repeal back to auto-approved; a curator's validated lifts the hold.
      - `axiom_hold` 'conflict' | 'unverified', nullable: Why the axiom veto holds this repeal: `conflict` (an open contradiction with an axiom, or the check judged one, or doubted) stays until a curator validates the repeal; `unverified` (the check could not be completed: unreadable facts or edges, a timeout, an error, an ambiguous answer) is lifted by a later detection whose check answers clear. Null = never held; a hold stored without a reason reads as `conflict`.
      - `created_at` string, date-time, nullable
      - `updated_at` string, date-time, nullable
    - `total` integer, required
    - `pot_id` string, uuid, required
    - `blocked_supersedes` BlockedSupersessionRef[]: Auto-approved repeals that do not retire, with the reason, so a curator can validate one past the Supported floor.
      - `edge_id` string, required
      - `from_id` string, required
      - `to_id` string, required
      - `validation_status` string, required
      - `reason` string, required
      - `from_pot_score` number, nullable
      - `to_pot_score` number, nullable
      - `axiom_conflict` string[]: With reason axiom_conflict: the active axioms the replacing fact contradicts.
  - `source_types` SourceTypeList
    - `source_types` SourceType[], required
      - `key` string, required: Stable key (never changes).
      - `label` string, required
      - `weight` number, required: Starting POT Score.
      - `description` string
      - `active` boolean
      - `priority` integer, nullable: The integrator's rank of this type, 1 (highest) to 15 (lowest); null = unranked. Metadata only: SciPot never reads it for a POT Score.
      - `updated_at` string, nullable
      - `updated_by` string, nullable
    - `template` boolean, required: True: the POT never edited them; these are the defaults.
    - `max_active` integer
    - `weight_min` number
    - `weight_max` number
  - `documents` object
  - `curations` object
  - `gaps` RelatedGaps
    - `related` RelatedGap[]
      - `gap` KnowledgeGap, required: Persisted gap item — repository row shape and API response body.
        - `gap_id` string, uuid: UUIDv7 — chronologically sortable.
        - `workspace_id` string, uuid, required: Owning workspace; multi-tenant isolation key.
        - `pot_id` string, uuid, required: POT the question was asked against.
        - `query_text` string, required
        - `context` string, nullable: The asker's case (where, what they see, what they tried); null when none was given. Gaps written before 0.7.24.0 have none.
        - `requester_id` string, required
        - `domain` string, required
        - `trigger` 'low_confidence' | 'no_coverage' | 'manual'
        - `trigger_score` number, nullable
        - `state` 'open' | 'routed' | 'ingested' | 'resolved' | 'expired' | 'dismissed' | 'duplicate' | 'reopened'
        - `assigned_to` string, nullable: Opaque id of the expert/DRI the integrator routed to. Core stores, never decides, this value.
        - `resolved_cluster_id` string, uuid, nullable: Deprecated, always null: a hook for a Knowledge Cluster that was never built. Kept so stored items and clients keep validating.
        - `capsule_id` string, uuid, nullable: Deprecated, always null in production: set only by the Capsules coverage evaluation, behind `capsules_enabled` (off). Marks the ORIGIN only; the trigger vocabulary is unchanged, so existing integrator payloads keep validating.
        - `idempotency_key` string, nullable
        - `transitions` GapTransition[]: Append-only transition history (actor + timestamp per state change).
          - `from_state` 'open' | 'routed' | 'ingested' | 'resolved' | 'expired' | 'dismissed' | 'duplicate' | 'reopened', required
          - `to_state` 'open' | 'routed' | 'ingested' | 'resolved' | 'expired' | 'dismissed' | 'duplicate' | 'reopened', required
          - `actor` string, required: Who/what performed the transition (opaque integrator id).
          - `at` string, date-time
          - `note` string, nullable
          - `evidence_ref` string, nullable: Optional link to the ingestion job / contribution that drove this transition.
        - `answers` GapAnswer[]: Append-only answers contributed toward the gap, partial or complete, oldest first.
          - `answer_id` string, uuid
          - `actor` string, required: Who answered (opaque integrator id).
          - `contributor_id` string, uuid, nullable: The registered contributor behind the facts, if any.
          - `completeness` 'partial' | 'complete', required
          - `fact_ids` string[], required
          - `note` string, nullable
          - `at` string, date-time
        - `timeout_at` string, date-time, nullable: Deprecated, always null: no route sets it and the core never expires a gap; an SLA is the integrator's, which drives the gap to 'expired' itself.
        - `created_at` string, date-time
        - `updated_at` string, date-time
        - `resolved_at` string, date-time, nullable
      - `score` number, required: Jaccard of the two questions' content words (0-1).
      - `exact` boolean, required: The same text up to case and spaces.
    - `min_score` number, required
    - `scanned` integer, required: Open gaps of the workspace evaluated (all POTs).
    - `complete` boolean, required: False: the workspace has more open gaps than the cap per state.
  - `meta` AskContextMeta, required
    - `partial` string[]: Sections whose reads failed and are empty or incomplete: gaps, supersedes, source_types, edges, currency, documents, curations. A client reads those on their own routes, or treats them as unknown.
    - `as_of` string, required
    - `latency_ms` integer, required
    - `limits` AskContextLimits, required: How much of each section the engine gathers (MaBrain's defaults).
      - `counterparts` integer: Other sides of clashes and repeals the results left out.
      - `gaps` integer: Related open gaps returned.
      - `curations` integer: Clash sides whose curations are read.

## Other responses

- `404`: POT not found
- `422`: Validation Error
- `500`: Search failed (vector store or embeddings)
- `503`: The POT could not be read

## Changes

- **2026-10-25** `7620af82156a`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/scipot/apis/scipot-core-api/changes/pots/:pot_id/ask-context/post.md)

---

[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.dev/scipot/apis/scipot-core-api/revisions/7620af82156a?raw)
