---
title: "Import bank template"
method: POST
path: "/v1/default/banks/{bank_id}/import"
tags: ["Bank Templates"]
---

# Import bank template

`POST /v1/default/banks/{bank_id}/import`

## Request

- Base URL: `https://hindsight.vectorize.io` (the document declares no server; this is the origin it was published from)
- URL: `https://hindsight.vectorize.io/v1/default/banks/{bank_id}/import`
- Auth: none declared
- TypeScript: <https://skmtc.dev/vectorize/apis/hindsight-http-api/docs/v1/default/banks/:bank_id/import/post.ts> (a function with typed inputs; its response is checked against the schema)

Import a bank template manifest to create or update a bank's configuration, mental models, and directives. If the bank does not exist it is created. Config fields are applied as per-bank overrides. Mental models are matched by id, directives by name — existing ones are updated, new ones are created. Use dry_run=true to validate the manifest without applying changes.

## Path parameters

- `bank_id` string, required

## Query parameters

- `dry_run` boolean: Validate only, do not apply changes

## Headers

- `authorization` string, nullable

## Request body

- BankTemplateManifest: A bank template manifest for import/export. Version field enables forward-compatible schema evolution: the API auto-upgrades older manifest versions to the current schema on import.
  - `version` string, required: Manifest schema version (currently '1')
  - `bank` BankTemplateConfig: Bank configuration fields within a template manifest. Only includes configurable (per-bank) fields. Credential fields (API keys, base URLs) are intentionally excluded for security.
    - `reflect_mission` string, nullable: Mission/context for Reflect operations
    - `retain_mission` string, nullable: Steers what gets extracted during retain
    - `retain_extraction_mode` string, nullable: Fact extraction mode: 'concise' (default), 'verbose', 'custom', 'verbatim', or 'chunks'
    - `retain_custom_instructions` string, nullable: Custom extraction prompt (when mode='custom')
    - `retain_chunk_size` integer, nullable: Target max characters for each content chunk
    - `retain_structured_chunk_size` integer, nullable: Max characters for a single JSONL line or conversation turn to keep whole; defaults to retain_chunk_size when unset
    - `enable_observations` boolean, nullable: Toggle observation consolidation
    - `observations_mission` string, nullable: Controls what gets synthesised
    - `enable_text_search` boolean, nullable: Toggle the keyword (BM25) arm during recall, leaving pure vector search
    - `enable_temporal_retrieval` boolean, nullable: Toggle the temporal arm (and its date-aware query analysis) during recall
    - `enable_graph_retrieval` boolean, nullable: Toggle the entity/link graph arm during recall
    - `enable_reranking` boolean, nullable: Toggle cross-encoder reranking during recall
    - `reflect_use_decision_model` boolean, nullable: When the server has a decision model, reflect lets it prune evidence and decide when to stop
    - `mental_model_refresh_use_decision_model` boolean, nullable: The same, for knowledge-page refreshes
    - `mental_model_delta_use_decision_model` boolean, nullable: When the server has a decision model, a delta knowledge-page refresh asks it which new memories could change the page instead of running reflect
    - `disposition_skepticism` integer, nullable: Skepticism trait (1-5)
    - `disposition_literalism` integer, nullable: Literalism trait (1-5)
    - `disposition_empathy` integer, nullable: Empathy trait (1-5)
    - `entity_labels` LabelGroupOutput[], nullable: Controlled vocabulary for entity labels
      - `key` string, required
      - `description` string
      - `type` 'value' | 'multi-values' | 'text' | 'multi-text' | 'map'
      - `optional` boolean
      - `tag` boolean
      - `values` LabelValue[]
        - `value` string, required
        - `description` string
      - `fields` object
    - `entities_allow_free_form` boolean, nullable: Allow entities outside the label vocabulary
    - `retain_default_strategy` string, nullable: Name of the default retain strategy (key into retain_strategies map)
    - `retain_strategies` object, nullable: Map of retain strategy name to per-strategy config dict
    - `retain_chunk_batch_size` integer, nullable: Max chunks per streaming batch (0 disables batching)
    - `retain_max_attachments_per_chunk` integer, nullable: Hard cap on inline images in a single extraction chunk
    - `mcp_enabled_tools` string[], nullable: MCP tool allowlist for this bank (None = all tools)
    - `consolidation_llm_batch_size` integer, nullable: LLM batch size for observation consolidation
    - `consolidation_source_facts_max_tokens` integer, nullable: Max tokens of source facts per consolidation batch
    - `consolidation_source_facts_max_tokens_per_observation` integer, nullable: Max tokens of source facts per observation
    - `max_observations_per_scope` integer, nullable: Max observations to retain per consolidation scope
    - `observation_scope_limits` object[], nullable: DEPRECATED — use consolidation_strategies, which carries the mission too. Still honoured, but consulted only after consolidation_strategies. Per-scope overrides of max_observations_per_scope: [{"scope": ["run_*", "shared"], "limit": 1}]. Each scope is a list of fnmatch tag-globs; a consolidation scope matches under exact cover (every tag matched by a glob and every glob matched by a tag). The first matching rule wins; unmatched scopes fall back to max_observations_per_scope.
    - `default_observation_scopes` union: observation_scopes applied at retain to items that send none ('combined' when unset). A list of tag lists may use globs, e.g. [['topic:*']] scopes each memory by its own topic tags.
      - 'per_tag' | 'combined' | 'all_combinations' | 'shared'
      - array[]
        - string[]
    - `consolidation_strategies` ConsolidationStrategySpec[], nullable: Per-scope consolidation settings: [{"scopes": [{"tags": ["company:*"]}], "observations_mission": "Record only generalized trends.", "max_observations_per_scope": 20}]. Each strategy lists the rules it claims scopes with — a rule's tags are fnmatch globs that must all be on the scope, and its "tags_match" decides whether the scope may carry others ("all", the default) or not ("exact"). The rules are alternatives: any one matching claims the scope. A strategy may set any of observations_mission, max_observations_per_scope, consolidation_source_facts_max_tokens and consolidation_source_facts_max_tokens_per_observation; each is optional. Exactly one strategy applies to a scope: the first in the list that claims it. Whatever that strategy leaves unset — and every scope no strategy claims — uses the bank-wide value; a later strategy never fills the gaps. Supersedes observation_scope_limits. Lets one bank be federated across user/team/company tag scopes, each consolidating under its own brief.
      - `scopes` ConsolidationScopePattern[]: Alternatives: the strategy claims a scope when any rule matches it
        - `tags` string[]: fnmatch tag patterns, e.g. company:*
        - `tags_match` string, nullable: "all" (the default when omitted): the scope has every tag in the rule, other tags allowed. "exact": exactly these tags and no others.
      - `observations_mission` string, nullable
      - `max_observations_per_scope` integer, nullable
      - `consolidation_source_facts_max_tokens` integer, nullable
      - `consolidation_source_facts_max_tokens_per_observation` integer, nullable
    - `reflect_source_facts_max_tokens` integer, nullable: Max tokens of source facts per reflect call
    - `knowledge_page_default_trigger` object, nullable: Trigger fields merged over the built-in knowledge-page default when a page is created (e.g. {"refresh_cron": "0 * * * *"}). A trigger sent with the create request still wins.
    - `reflect_default_options` object, nullable: Default reflect options for this bank (e.g. {"reflect_search_observations_max_tokens": 3000, "reflect_search_observations_include_entities": false}). Applied to every reflect request in the bank (API and MCP) that leaves the option unset. Mental-model refreshes do not read it: they take these options from their own trigger, defaulted per bank by knowledge_page_default_trigger.
    - `mental_model_min_refresh_interval_seconds` integer, nullable: Minimum seconds between two automatic refreshes of the same mental model in this bank. 0 (the default) means no floor. Overridable per model via the trigger's min_refresh_interval_seconds.
    - `llm_gemini_safety_settings` unknown[], nullable: Per-bank Gemini/VertexAI safety filter settings
      - unknown
    - `recall_budget_function` string, nullable: Recall budget mapping function: 'fixed' or 'adaptive'
    - `recall_budget_fixed_low` integer, nullable: Fixed thinking_budget for budget=low (function='fixed')
    - `recall_budget_fixed_mid` integer, nullable: Fixed thinking_budget for budget=mid (function='fixed')
    - `recall_budget_fixed_high` integer, nullable: Fixed thinking_budget for budget=high (function='fixed')
    - `recall_budget_adaptive_low` number, nullable: Ratio of max_tokens for budget=low (function='adaptive')
    - `recall_budget_adaptive_mid` number, nullable: Ratio of max_tokens for budget=mid (function='adaptive')
    - `recall_budget_adaptive_high` number, nullable: Ratio of max_tokens for budget=high (function='adaptive')
    - `recall_budget_min` integer, nullable: Floor for the adaptive function (after clamping)
    - `recall_budget_max` integer, nullable: Ceiling for the adaptive function (after clamping)
    - `audit_log_enabled` boolean, nullable: Enable audit logging for this bank (overrides the server default)
    - `store_document_text` boolean, nullable: Persist raw source text (documents.original_text / chunks.chunk_text). Set false to keep only derived facts.
    - `default_timezone` string, nullable: IANA zone (e.g. 'Europe/Rome') a retain timestamp, or a time the LLM extracts, is read in when it carries no UTC offset.
    - `enable_auto_consolidation` boolean, nullable: Automatically consolidate observations after retain
    - `consolidation_use_decision_model` boolean, nullable: When the server has a decision model, consolidation lets it settle restatements and chatter before the LLM call
    - `consolidation_max_memories_per_round` integer, nullable: Max memory units fed into a single consolidation round
    - `consolidation_llm_parallelism` integer, nullable: Number of consolidation LLM batches processed concurrently
    - `recall_include_chunks` boolean, nullable: Include raw chunks in recall results
    - `recall_prefer_observations` boolean, nullable: Default for recall prefer_observations when the request omits it
    - `recall_decision_model_prune` boolean, nullable: Default for recall prune when the request omits it (decision-model reranker only)
    - `recall_decision_model_dedup` boolean, nullable: Default for recall dedup when the request omits it (decision-model reranker only)
    - `recall_max_tokens` integer, nullable: Max tokens of results returned by recall
    - `recall_chunks_max_tokens` integer, nullable: Max tokens of raw chunks returned by recall (when recall_include_chunks is set)
    - `memory_defense` object, nullable: Memory Defense policy for this bank (validated against the DefensePolicy schema on write)
  - `mental_models` BankTemplateMentalModel[], nullable: Mental models to create or update (matched by id). Omit to leave unchanged.
    - `id` string, required: Unique ID for the mental model (same rules as a bank id: at most 192 bytes of UTF-8, no '/' and no control characters)
    - `name` string, required: Human-readable name for the mental model
    - `source_query` string, required: The query to run to generate content
    - `tags` string[]: Tags for scoped visibility
    - `max_tokens` integer: Maximum tokens for generated content
    - `trigger` MentalModelTriggerOutput: Trigger settings for a mental model. A refresh is not an ad-hoc reflect with different arguments: it synthesizes a whole document, so it wants its own retrieval and iteration settings. This trigger is therefore the only source for them — a bank's ``reflect_default_options`` deliberately does not reach a refresh. The per-bank default for these fields is ``knowledge_page_default_trigger``, which is merged over this same shape when a page is created.
      - `budget` 'low' | 'mid' | 'high': Budget levels for recall/reflect operations.
      - `mode` 'full' | 'delta': Refresh mode. 'full' (default) regenerates the mental model content from scratch on each refresh. 'delta' performs surgical edits against the existing content: unchanged sections are preserved byte-for-byte, stale content is removed, new content is added. If the mental model has no existing content, or if the source_query has changed since the last refresh, delta mode falls back to a full regeneration automatically.
      - `refresh_after_consolidation` boolean: If true, refresh this mental model after observations consolidation (real-time mode)
      - `refresh_cron` string, nullable: Cron expression (UTC, standard 5-field syntax, e.g. '0 3 * * *' for daily at 03:00 UTC) for refreshing this mental model on a fixed schedule. Mutually exclusive with refresh_after_consolidation — a model refreshes either after consolidation or on a cron schedule, not both. A scheduled refresh only runs when the model is stale (new memories in its scope since the last refresh); if nothing changed, the tick is skipped to avoid a wasted LLM call. null = no schedule.
      - `full_refresh_cron` string, nullable: Cron expression (UTC, standard 5-field syntax, e.g. '0 3 * * 0' for Sundays at 03:00 UTC) for a scheduled full refresh: on this schedule the model is refreshed in 'full' mode whatever its `mode` says, regenerating the content from scratch to clear the drift many delta edits accumulate. Independent of `refresh_cron` and `refresh_after_consolidation` — a delta model can refresh after consolidation and still get a weekly full refresh — and it does not change `mode`. A tick is skipped when no refresh has run since the last full one (there is nothing to correct). Like `refresh_cron`, it honours `min_refresh_interval_seconds` and pauses while the last refresh failed. null = no schedule.
      - `min_refresh_interval_seconds` integer, nullable: Minimum seconds between two automatic refreshes of this mental model. A triggered refresh that arrives sooner is not dropped: it is queued and parked until the window expires, and every further trigger in the meantime folds into that one queued refresh, so a burst of retains costs one refresh instead of one per retain. Applies to every automatic trigger: refresh_after_consolidation, refresh_cron and full_refresh_cron. Explicit refreshes (API, MCP, control plane) ignore it and run immediately. 0 disables the floor for this model; null falls back to the bank/global mental_model_min_refresh_interval_seconds setting (itself 0 by default, i.e. no floor).
      - `fact_types` string[], nullable: Filter which fact types are retrieved during reflect. None means all types (world, experience, observation).
      - `exclude_mental_models` boolean: If true, exclude all mental models from the reflect loop (skip search_mental_models tool).
      - `exclude_mental_model_ids` string[], nullable: Exclude specific mental models by ID from the reflect loop.
      - `tags_match` 'any' | 'all' | 'any_strict' | 'all_strict' | 'exact', nullable: Override how the model's tags filter memories during refresh. If not set, defaults to 'all_strict' when the model has tags (security isolation) or 'any' when the model has no tags. Under 'all_strict' a memory must carry EVERY one of the model's tags and untagged memories are excluded, which is why a model tagged with labels its memories do not carry refreshes to empty content. Set to 'all' to keep requiring the tags while including untagged memories, or to 'any' to include untagged memories alongside any single tag match. Staleness ignores that widening: an untagged write never marks a tagged model stale, in any mode — only a write that matches the model's tags does.
      - `tag_groups` union[], nullable: Compound boolean tag expressions to use during refresh instead of the model's own tags. When set, these tag groups are passed to reflect and the model's flat tags are NOT used for filtering. Supports nested and/or/not expressions for complex tag-based scoping.
        - union
          - TagGroupLeaf: A leaf tag filter: matches memories by tag list and match mode.
            - `tags` string[], required
            - `match` 'any' | 'all' | 'any_strict' | 'all_strict' | 'exact'
            - `resolve` 'exact' | 'fuzzy'
          - TagGroupAndOutput: Compound AND group: all child filters must match.
            - `and` union[], required
              - …
          - TagGroupOrOutput: Compound OR group: at least one child filter must match.
            - `or` union[], required
              - …
          - TagGroupNotOutput: Compound NOT group: child filter must NOT match.
            - `not` union, required
              - …
      - `include_chunks` boolean, nullable: Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks).
      - `recall_max_tokens` integer, nullable: Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens).
      - `recall_chunks_max_tokens` integer, nullable: Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens).
      - `reflect_search_observations_max_tokens` integer, nullable: Override the token budget for the refresh's search_observations calls. Observation evidence is often the largest contributor to the reflect context; lowering it trades the lowest-ranked observations for a smaller LLM context. null means the shipped 5000.
      - `reflect_search_observations_include_entities` boolean, nullable: Override whether search_observations attaches resolved entity names to each observation. Entities can be more than half the serialized tool payload; turning them off keeps the same observations and ranking with a much smaller context. null means enabled.
      - `response_schema` object, nullable: Optional JSON Schema for structured output. When set, each refresh runs the same structured-output extraction as reflect's response_schema and stores the parsed result under reflect_response.structured_output alongside the markdown content.
      - `keep_trace` boolean: If true, every refresh of this mental model records how it reached its result under reflect_response.trace: the mode it ran in and why, the resolved scope and time window, how many facts retrieval returned versus how many the agent used, the tool and LLM calls, and any delta operations. Only the latest refresh's trace is kept. This is the only way to diagnose a cron- or consolidation-driven refresh after the fact, since no human sees those run. Tool outputs are reduced to result counts to keep the stored trace bounded; use LLM request tracing for raw prompts and responses.
  - `directives` BankTemplateDirective[], nullable: Directives to create or update (matched by name). Omit to leave unchanged.
    - `name` string, required: Human-readable name for the directive (used as match key on re-import)
    - `content` string, required: The directive text to inject into prompts
    - `priority` integer: Higher priority directives are injected first
    - `is_active` boolean: Whether this directive is active
    - `tags` string[]: Tags for filtering

## Response `200`

Successful Response

- BankTemplateImportResponse: Response model for the bank template import endpoint.
  - `bank_id` string, required: Bank that was imported into
  - `config_applied` boolean, required: Whether bank config was updated
  - `mental_models_created` string[]: IDs of newly created mental models
  - `mental_models_updated` string[]: IDs of updated mental models
  - `directives_created` string[]: Names of newly created directives
  - `directives_updated` string[]: Names of updated directives
  - `operation_ids` string[]: Operation IDs for mental model content generation (async)
  - `dry_run` boolean: True if this was a validation-only run

## Other responses

- `422`: Validation Error

## Changes

- **2026-11-07** `45e711cd0897`: 2 warning, 10 info
  - the `directives/anyOf[subschema #1]/items/priority` request property's max was set to `2147483647.00`
  - the `directives/anyOf[subschema #1]/items/priority` request property's min was set to `-2147483648.00`
  - added the new optional request property `bank/anyOf[subschema #1: BankTemplateConfig]/consolidation_use_decision_model`
  - added the new optional request property `bank/anyOf[subschema #1: BankTemplateConfig]/default_observation_scopes`
  - …8 more
- **2026-10-04** `4fda98b75f63`: 1 breaking, 1 warning
  - added required request body
  - removed the optional property `detail/items/url` from the response with the `422` status
- **2026-05-15** `0d08f271b9db`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/vectorize/apis/hindsight-http-api/changes/v1/default/banks/:bank_id/import/post.md)

---

[API](https://skmtc.dev/vectorize/apis/hindsight-http-api.md) - [All operations](https://skmtc.dev/vectorize/apis/hindsight-http-api/llms.txt) - [OpenAPI document](https://skmtc.dev/vectorize/apis/hindsight-http-api/revisions/45e711cd0897?raw)
