App-source search is enabled at recall time with
search_apps: true. In thinking mode, HydraDB can use app IDs, actors, threads, parent links, and explicit relations to expand the returned context.Page map
- Ingest app sources: what to send, which fields to use, and how to model IDs.
- Incremental ingestion: how to ingest new comments, replies, messages, and pages after the initial sync.
- How app sources affect search: what HydraDB does with those fields during Recall.
- Common scenarios: ready-to-adapt payloads for comments, attachments, threads, and CRM/support links.
- TLDR field reference: all allowed app-source fields, when to use them, and how they affect ingestion and search.
The mental model
Every app-source item becomes one HydraDB source. HydraDB stores three kinds of information:
Do not model every provider-specific field as a first-class field. Put app-specific scope values like Slack channel, Confluence space, Jira project, Salesforce pipeline, or HubSpot list in
metadata.
Ingest app sources
Send app sources in theapp_knowledge form field as a single JSON object or an array. Each item is one HydraDB source and must include the ingestion envelope fields id, tenant_id, and sub_tenant_id.
The app-specific part of each item uses the public app-source shape:
For typed app sources, put the main searchable item text in
fields (email.body, message.body, ticket.description, knowledge_base.body, comment.body, or custom.data). The top-level content object is the older generic knowledge payload and is not required for app-native search.
The example below is a valid app_knowledge item for a Slack message:
Field categories
Identity fields
Identity fields tell HydraDB what this item is.
Use
external_id for the item itself. For example:
Thread and parent fields
For hierarchy fields,
parent_id should be the parent’s provider external_id, not the HydraDB source id. The child and parent should use the same provider namespace so HydraDB can safely connect them. For example, a Salesforce deal with parent_id: "account_456" should have a parent account source with provider: "salesforce" and external_id: "account_456".
For Slack-like threads, it is OK for thread_id and parent_id to be the same when the replied-to parent is the thread root.
Incremental ingestion
Use the samePOST /ingestion/upload_knowledge endpoint for both initial sync and live updates. The important choice is whether the provider object is the same source being updated or a new source that arrived later.
First-class ticket comment
A first-class comment is one HydraDB source. Use a stable sourceid you can reproduce from the provider, and use the provider’s comment ID as external_id.
parent_id is present on a comment, HydraDB derives a comment_on relation to the parent source in the same provider namespace. In the example above, HydraDB links the comment to the source with provider: "linear" and external_id: "UI-001". If no parent is present, the comment is still indexed as a standalone source.
Use explicit relations when the parent is in a different provider namespace or when you already know the HydraDB source_id:
New Slack messages and email replies
Slack messages and email replies are not modeled as comments on an existing source. Ingest each new message or email as a new source:- For Slack or Teams, use
kind: "message", a newexternal_idfor the provider message ID,thread_idfor the thread root, andparent_idfor the replied-to message when available. - For Gmail or Outlook, use
kind: "email", a newexternal_idfor the provider message ID,thread_idfor the email thread, andreply_to_idfor the parent email when available.
New knowledge-base pages
A new Notion, Confluence, Google Docs, or CMS page is a newknowledge_base source. The space, workspace, collection, or database is container metadata, not the source identity.
Container metadata
Usemetadata for provider-specific scope and fields that help organize the source but do not identify the source itself.
A container is the place that holds many app items: a Slack channel contains many messages, a Jira project contains many tickets, a Confluence space contains many pages, and a CRM pipeline contains many deals.
Think of
metadata as a flexible bag for scope, grouping, and provider-specific details. HydraDB stores it with the source so results can show where the item came from and so your integration can keep provider context without forcing every app to have the same fields.
Do not use a container ID as external_id. external_id should identify the individual item being ingested; container IDs belong in metadata.
Put fields in
metadata when they describe where the item lives, such as channel, project, space, workspace, pipeline, region, or team. Put fields in fields when they are part of the item’s searchable content or structure, such as message body, ticket status, parent ID, assignee, or thread ID.Actors
Actors are people or bots involved with an app source. HydraDB infers actors from kind-specific fields:
Actors improve queries such as “emails from Alice”, “tickets assigned to Bob”, “messages mentioning Carol”, or “comments by the support team”.
Relations
Relations tell HydraDB how app sources connect. Userelations to explicitly connect two HydraDB sources when the relationship matters for search. For example, connect a ticket to a release it blocks, a CRM deal to a related support ticket, or a document page to a source it references.
linked_ticket_ids is not a first-class field. Use linked_issue_ids for ticket-like items, or use explicit relations with predicate: "linked_to" for generic links.Explicit relations
Userelations for source-to-source connections that are not already represented by typed fields:
The vocabulary is extensible. If you use a custom predicate, use a stable lowercase string and keep direction consistent.
In
thinking mode, related sources found through these connections can appear in additional_context.
Kind-specific fields
Kind-specific fields are the structured fields insidefields; they tell HydraDB how to read each app item as an email, message, ticket, knowledge-base page, or custom record.
email for individual email messages. Put the subject and body in fields, plus sender, recipients, thread, reply, and forward IDs when you have them.
Message
Usemessage for chat or collaboration messages from tools like Slack, Teams, Discord, or in-app comments that behave like messages.
metadata.
Ticket
Useticket for issue-tracker or support-case style records: Jira issues, Linear issues, Zendesk tickets, GitHub issues, support cases, and similar workflow items.
metadata.
Knowledge base
Useknowledge_base for wiki or documentation pages from tools like Notion, Confluence, Google Docs, or an internal CMS.
metadata.
Comment
Usecomment for incremental comments from ticketing, issue-tracking, support, CRM, or workflow systems. A first-class comment is its own source with its own stable id and external_id.
parent_id should point to the parent source’s provider external_id in the same provider namespace. HydraDB derives a comment_on relation from that field. If a comment belongs to a cross-provider source, use relations[] with predicate: "comment_on" instead.
Custom and CRM
Usecustom for records that do not fit the built-in kinds yet, especially CRM and business-system objects such as accounts, deals, contacts, renewals, invoices, or internal workflow records.
For CRM-style hierarchies, ingest both sides as app sources when you want traversal. For example, ingest the account as
provider: "salesforce", external_id: "account_456", then ingest the deal or contact with fields.parent_id: "account_456". During app search, HydraDB can use that link to bring the account and its children into context.
Attachments and comments
Attachments and embeddedcomments[] are indexed separately from the main source text, but remain connected to the source.
Use attachments[].content when you already have extracted text for the file. HydraDB indexes that text in attachment-specific vectors. A URL by itself is treated as metadata; HydraDB does not fetch and parse arbitrary attachment URLs from app-source payloads.
Use embedded comments[] for initial backfills or full snapshots where you already have the complete current comment list for the parent source. For live incremental webhooks, prefer first-class kind: "comment" sources so you can add, update, or delete a single comment without re-ingesting the parent ticket or page.
How app sources affect search
Whensearch_apps: true, HydraDB runs an app-aware search lane alongside normal retrieval.
The app-aware lane does more than search text. It first looks for app-specific clues in the query, such as a provider name, object type, exact ticket/message ID, person name, thread wording, or relation wording like “linked to”, “blocked by”, “parent”, or “reply”. It then uses those clues to build candidates and expand context around the best matches.
This means a query like “show me Slack replies from Alice about AUTH-123” can combine text relevance with Slack scoping, actor matching, exact ticket ID matching, and reply/thread expansion. A query like “what is blocking the release?” can use explicit
blocks or linked_to relations instead of relying only on whether the same words appear in both sources.
This helps because app search can retrieve the surrounding work context, not just the closest text match. If a ticket, Slack thread, and release note are connected by IDs or relations, HydraDB can bring them together even when they use different wording. The result is fewer missed sources, better answers for workflow questions, and more useful context for agents that need to explain why something happened or what to do next.
Parent and child search
Parent/child search is based on provider-scoped external IDs. When HydraDB ingests a child source withparent_id, it stores that value as a pointer to the parent’s external_id in the same provider namespace.
At recall time, search_apps: true lets the app-aware lane find an initial source by text, exact ID, actor, or provider/kind filters. In thinking mode, if the query asks for parents, children, ancestors, descendants, epics, subtasks, accounts, deals, or similar hierarchy wording, HydraDB expands around that matched source:
- To find a parent, HydraDB matches the source’s
parent_idto another source’sexternal_idwith the sameprovider. - To find children, HydraDB looks for sources whose
parent_idequals the matched source’sexternal_idwith the sameprovider. - Expansion is bounded and can include one more level, such as grandparent or grandchild context, when useful.
mode: "thinking" for best app-source behavior, because relation expansion and reranking have more room to improve context quality.
Common mistakes
End-to-end example
This example ingests a Jira ticket with a parent epic, linked issues, project metadata, embedded snapshot comments, and an explicit blocker relation. For new comments arriving after this ticket has already been indexed, use the first-classcomment example in Incremental ingestion.
At search time,
search_apps: true lets queries like “what is blocking the release?”, “children of AUTH-100”, or “tickets linked to AUTH-123” use those graph edges and IDs instead of relying only on text similarity.
Common scenarios
Use these payload patterns when app data contains comments, attachments, threads, or cross-app links. Each example is one item in theapp_knowledge array.
Slack message with an attachment
Model the Slack message askind: "message", keep channel/workspace details in metadata, and put extracted file text in attachments[].content.
Slack message attachment payload
Slack message attachment payload
Incremental Linear ticket comment with attachment
Represent the Linear issue itself as aticket. When a new comment arrives later, ingest the comment as a first-class comment source. Files mentioned or uploaded in that comment can go in the comment source’s attachments[].
Linear incremental comment payload
Linear incremental comment payload
Custom threaded record with comments and attachments
Usecustom for internal systems or CRM/workflow records outside the built-in email, message, ticket, and knowledge-base shapes. thread_id groups activity around the record, comments make discussion searchable, and attachments add independent file recall.
Custom threaded record payload
Custom threaded record payload
CRM deal linked to a support ticket
Useparent_id for account -> deal/contact hierarchy and relations[] for cross-app context, such as a Salesforce opportunity linked to a Linear or Jira support issue.
CRM deal linked to support ticket payload
CRM deal linked to support ticket payload
Relation fields
TLDR field reference
Use this as the compact contract for app-source ingestion. Thefields.kind value must match the top-level kind when you provide typed fields.