Skip to main content
Context is everything you give HydraDB so your AI can find it later. It comes in two types, and most applications use both: The two types work the same way. Both go to POST /context/ingest, both are saved in a collection, both are indexed in the background, and both come back from POST /query. Each item you ingest is a source; HydraDB splits it into searchable passages called chunks and builds a context graph from it. They are stored separately, so a query chooses what to read: type: "knowledge", type: "memory", or type: "all" for both in one ranked list. A support agent, for example, answers from the help center (knowledge) and from the fact that this customer already tried restarting (a memory).

1. Ingest knowledge

There are three ways to ingest knowledge:
  • Files: upload PDF, DOCX, Markdown, CSV, or TXT files, and HydraDB reads them for you.
  • App sources: send records your application already holds from an app, such as a Slack message or a Jira ticket.
  • Connectors: connect an app such as Slack, Google Drive, Notion, or GitHub once, and HydraDB keeps it in sync.

Upload files

The request is multipart/form-data with these fields:
Set up your SDK client before running the Python or TypeScript example.
The response lists each file in data.results with its id and a status of queued. The payload is wrapped in the standard envelope, so read it from response.data:
Each document_metadata item takes these properties: The key list is closed. Any other key, including title, type, url, and timestamp, returns 400. Ingest Context lists the supported file formats.

Send app sources

When your application already holds the text and fields of a Slack message, a Jira ticket, a Notion page, or a CRM record, send it as an app source instead of a file. HydraDB keeps the app’s structure: the author, the thread, the ticket’s status, and the links between records. The request goes to the same endpoint, with app_knowledge in place of documents. One request can carry both. kind says what the record is (email, message, ticket, knowledge_base, comment, meeting, or custom), and fields carries its content. An app source can also carry an acl, the list of principals allowed to retrieve it. The field reference lists the keys each kind takes in fields.
The response has the same shape as a file upload, with one entry per app source in data.results.

2. Save memories

HydraDB does not capture memories on its own: your application saves one when a user states a preference, makes a decision, finishes a task, or corrects the agent. Give each user their own collection, such as user_john_123, and send it on every ingest, status check, and query. Your backend picks it from the signed-in session; the name itself does not authenticate anyone. The request is the same as for knowledge, with type=memory and a memories list in place of files:
Set up your SDK client before running the Python or TypeScript example.
The response lists each memory in data.results with its id and a status of queued. The payload is wrapped in the standard envelope, so read it from response.data:

Let HydraDB infer the memory

infer controls whether HydraDB extracts the memory from what you send or stores it as written. custom_instructions takes effect only when infer: true. Use it to guide extraction, for example: "Focus on UI and notification preferences only".
A user has been toggling dark mode in your application. Instead of extracting the preference yourself, send the raw behavior log and let HydraDB infer the memory.
Later, when POST /query runs with type: "memory" and a query like "what UI settings does the user prefer?", HydraDB can return the inferred preference (for example, "prefers dark mode") rather than the raw event log.If you sent the same input with infer: false, HydraDB would index the event log verbatim. That is useful only when you want to retrieve the log itself.

Send text or a conversation

Each memory item takes either text or user_assistant_pairs, not both (sending both returns 400).
  • text: prose of any kind, such as observations, captured facts, meeting notes, or semi-structured records. Set is_markdown: true when the content uses Markdown (headings, lists, code blocks) so HydraDB keeps that structure during chunking and embedding.
  • user_assistant_pairs: dialogue, especially when the preference is implied rather than stated. Each pair is { "user": "...", "assistant": "..." }.
Markdown notes, stored as written:
A plain statement, with the preference extracted:
A conversation, with the preference extracted:

3. Wait for indexing

Knowledge and memories are indexed the same way, in the background: HydraDB parses each source, splits it into chunks, infers the memory if you asked it to, finds the people, teams, and topics it mentions and how they relate, and builds the search indexes. The ingest request returns 202 Accepted with each source’s id. Poll GET /context/status with those ids and the same collection every few seconds. A source’s indexing_status moves forward through queued, processing, graph_creation, and completed, or lands in errored on failure:
  • At graph_creation the source becomes searchable within a few seconds, while its graph is still building. A query sent the moment this status appears can miss the source, and a collection that is new can still be reported as not existing.
  • At completed the source and its graph are ready. Wait for completed when you query straight after ingesting. Most documents complete in 1 to 5 minutes.
Ingestion Status has the full status table. To skip polling, register a webhook.
Each status in the data payload looks like this:

4. Query knowledge and memories together

POST /query reaches each type through the type parameter:
  • type: "knowledge" (the default) searches files and app sources.
  • type: "memory" searches memories.
  • type: "all" searches both and returns one merged, ranked list.
Both types are read from the collections you name. Shared knowledge usually lives in one collection and each user’s memories in their own, so list both in collections. If some sources carry an acl, also send the caller’s identity as acl. Query covers the other parameters and how to pass the result to a model.
Knowledge and memories come back together in data.chunks, ranked as one list. To let the user’s memories outrank the shared documents, send weights instead of a list:

5. Update or delete context

To change a source or a memory, send it again with the same id. upsert defaults to true, so the saved one is replaced; include everything you want to keep. Wait for the previous ingestion to reach completed or errored before sending the next update for the same id. To remove one, call DELETE /context with its id and the same collection. Forceful relations are links you declare between knowledge sources when you ingest them. When a query matches a source that has forceful relations, HydraDB returns the linked sources in the additional_context field of the response, alongside the primary chunks. This is separate from the context graph HydraDB builds on its own. Use forceful relations for documents that belong together when the text does not say so: a contract and its addendum, or a runbook and its troubleshooting guide. They link whole sources. To declare the entity and relation graph within one document, replacing extraction for it, use Bring Your Own Graph. On a file, set relations.ids on its document_metadata item. On an app source, set relations.ids the same way, and name the relationship in app_relations so the link also carries a predicate. relations.ids is what makes the linked text come back with query results; a named relationship alone connects the sources without requesting their text.
query_forceful_relations defaults to true; set it to false to skip the linked sources.
Knowledge sources, thinking mode only: Forceful relations stay within one store, so pointing a knowledge source at a memory ID silently returns nothing. Linked context is fetched only when mode: "thinking" is set on the query, or when mode: "auto" routes to thinking. In fast mode, query_forceful_relations is ignored even if set to true.

Field reference

Set kind on the app source and repeat it as fields.kind. Every other key in fields is optional.
memories is a JSON string. Inside each item, metadata and additional_metadata are plain objects; do not stringify them again.

Common mistakes