DEV Community

Cover image for Bringing scattered sources into a single search — the unified knowledge workspace UseSources
uehara
uehara

Posted on

Bringing scattered sources into a single search — the unified knowledge workspace UseSources

Summary

  • What I built: a unified knowledge workspace called UseSources (usesources.com). It rests on two pillars. First, it unifies external sources (Notion, Slack, Confluence, Jira, Google Drive, and so on) together with internal wiki, tasks, and chat into a single RAG (a system that searches and then composes an answer), so an AI agent can return "where the correct answer lives." Second, it unifies the workspace itself around a single axis called project.
  • Why I built it: the fragments of an answer to a work question are scattered not only inside our own workspace but across external SaaS as well. The very structure of opening tools one at a time and searching each of them separately eats time and lets answers slip past you.
  • The point: UseSources has a two-layer design of "knowledge unification" and "workspace unification." Making search, permissions, and context come together in one place is the whole of this product's value.

Body (reading time ~13 min)

The actual UseSources site. A Notion-style page editor, a task board, chat, cross-source search, and an AI agent, brought together under one unit called project (a real screen from https://usesources.com)

The pieces of an answer are scattered inside and outside the company

"Now, where was that written?" How much of your workday goes to that one question?

There are actually two kinds of places where information scatters. The first is your own workspace: documents in the wiki, tasks on the board, the reasoning in chat. The second is the one that gets overlooked — external sources. The original draft of a spec still sits in an old Notion. The reason behind a decision is buried in a Slack thread. Exchanges with a customer live in Confluence or Jira. Old material is asleep in Google Drive.

When we search, we open the tools one at a time and type the same words into each search box. Notion only looks inside Notion. Slack only looks inside Slack. You cannot know where the answer lives until you have finished searching everywhere. That structure is the root of the problem.

And this hunt happens many times a day. Even at five minutes each, six times a day is thirty minutes. Multiply that by every person on the team. Worse still, searching becomes such a chore that "it is faster to just ask." Verbal questions to whoever might know the answer pile up, that person's time gets eaten, the answer sinks back into the chat stream, and the next person searching cannot find it either. Left alone, fragmentation reproduces itself.

In the age of AI, this problem shows up in another form too. To hand work to an AI you have to hand it context, but when the context is spread across five tools, it is not in a shape you can give to the AI. Information a person cannot find is information the AI cannot use either. Unifying information is at once about human efficiency and about laying the groundwork to make AI actually do the work.

The list of supported services. It reaches across information scattered across Notion, Google Docs/Sheets, ClickUp, Asana, Jira, and Confluence (a real screen from https://usesources.com)

The first pillar — unifying internal and external sources into a single RAG

The first pillar of UseSources is inverting this structure. It unifies internal and external sources into a single RAG, so that one search lets an AI agent return "where the correct answer lives."

  • External connectors: they ingest documents from external SaaS and add them to what search covers. The connector has actually synced about 3,000 documents from Notion and been verified end to end (E2E). Support is expanding to sources such as Slack, Confluence, Jira, and Google Docs/Drive.
  • A single index: ingested documents and the internal pages, tasks, and chat messages all land in the same index. Search is a hybrid method that combines vector search, which searches by meaning, with full-text search, which searches by words.
  • AI agent: rather than simply listing the search results, the agent answers a question in the form "the answer is right here in this document." Instead of a person opening and reading ten search results, the agent guides you to where it lives.

This "make every source into a single RAG" is also where the name UseSources comes from: put your sources into a usable state.

The Answer Agent screen. Ask an agent whose search scope is set (all Notion DBs, the #general channel, all pages) and it answers across the connected sources (development environment, demo data)

How search is built, and the cost decisions behind it

There were two decisions in the search foundation.

The first was the decision not to run a dedicated search engine. The initial architecture proposal included Elasticsearch (the standard software for large-scale search), but I removed it. Combining pgvector, the vector search feature of the Postgres database, with full-text search is more than fast enough at this scale, and it means one fewer kind of server to operate. At the scale of an individual developer, standing up a separate search engine lets its cost and operational load crowd out the product itself.

The second was the decision to make ingestion asynchronous. Full syncs from external connectors were originally synchronous, and for a large workspace no response would come back for 86–120 seconds and the request would time out. I switched to a design that inserts a queue and processes the work in the background, and the response dropped to 1.73 seconds. The change was made after estimating the extra cost at roughly $1–2 per month. I have written up the long slog of this fix in a separate article.

The second pillar — unifying the workspace around the project axis

Even with a single search, if the places where daily work lives are scattered, the fragmentation gets reproduced. That is why the second pillar is needed: unifying the workspace itself.

  • Creating a project produces a three-part set at once. A wiki page you can write in Notion-style, a task board, and a dedicated chat channel are all set up the moment the project is created.
  • Permissions are set once, at the project level. Adding a member and removing one are both a single operation on the project. Remove someone and their permissions across the pages, boards, and chat beneath it are revoked all at once. "We revoked their access everywhere but forgot one tool, so someone who left could still read the documents" cannot happen by construction.
  • A task is a kind of page. Rather than splitting tasks and documents into separate systems the way Jira and Confluence do, I unified them into a single entity. A task can hold the same body text as a document, and it rides the same search.
  • The team can write at the same time. Pages support real-time simultaneous editing by multiple people, and come with mentions, notifications, presence, comments, and sharing.

The knowledge unification (the first pillar) and the workspace unification (the second pillar) are two facets of the same idea. The external past is connected through RAG; the internal present turns around a single axis. Search, permissions, and context all come together in one place.

The workspace screen. Projects, agents, and channels on the left, a task board in the center, chat on the right. When a task moves, a bot automatically posts a notice to chat (development environment, demo data)

How we actually use it — how it runs inside the company

Abstractions alone do not land, so here are three ways we use it internally.

Example 1: "Where did we decide that again?" When I want to check a design decision from a few months ago, I used to search the wiki, then scroll back through chat if it was not there, then open the external Notion. Now I type into UseSources search: "why did we adopt X?" The agent returns the relevant thread from the chat at the time and the related wiki page, each with where it lives. The biggest difference is that time spent searching becomes time spent reading.

Example 2: onboarding a new hire. Add a new member to a project and from that moment they can read all of the wiki, board, and chat beneath it. There is no need for guidance like "for the history, please look at these five tools," and the load on the person being asked drops too. Past external documents can be reached through the same search via RAG, so branching guidance like "the history is in the old Notion workspace" disappears as well.

Example 3: the weekly review. Because a project's task board and pages sit on the same axis, you can look at "pages that moved this week" and "tasks that moved" side by side. Since a task is a kind of page, review notes can be written directly in the task body and pulled up later by search. The classic problem of meeting notes and tasks drifting apart in separate systems does not happen.

The page editor screen. Add blocks, headings, and checklists through a GUI, with round-trip conversion to and from Markdown. Board, document, table, and calendar are different views of the same data (development environment, demo data)

Behind permissions and simultaneous editing

Two footnotes on the structure.

Permissions are inherited from the project. Permissions are granted to people only at the project level, and the pages, boards, and channels beneath it inherit exactly what the project carries. That is why "removing" someone also takes a single operation. Deliberately not building a back door to attach permissions directly to individual pages has paid off later. Allow even one exception and you end up checking every page at every review.

Simultaneous editing is built on a mechanism that resolves edit conflicts automatically (CRDT). Even if two people edit the same paragraph at the same time, neither person's change disappears. To keep costs down, the real-time communication path leans on a lightweight server setup, and it has been verified end to end in production. This was a plain but important choice for having both a "Notion-grade editing experience" and "individual-developer cost."

It did not start out in this shape

UseSources has changed direction significantly twice.

It began as a tool for RAG search across multiple SaaS. Building search alone, I realized that search alone does not change where work lives. The root cause of the scatter — that daily work happens in separate tools — was still there.

So I pivoted toward unifying task management and chat, and while building it out I realized that "if tasks and pages are separate things, there are two places to put work again," and unified a task into a kind of page. Finally I arrived at the current shape, where project is a first-class axis. Thirty design decisions over four months, all recorded, made these pivots possible.

There is also a predecessor that once stalled. A year earlier I had started building it as an "integrated knowledge search" and it stopped as a prototype; the current UseSources is that prototype restarted with a spec-first development process (writing ADR/SDD/TDD documents together with AI). I stood up the development foundation in four days and got it to production in three months.

RAG is not magic — what it takes to make it work in practice

The word RAG (Retrieval-Augmented Generation, a method that gathers evidence by search before composing an answer) is fashionable, but making it work in practice takes plain, unglamorous engineering. Here are the elements that actually worked in UseSources.

First, the freshness of the index. Ingest external documents once and be done, and they go stale quickly. By making ingestion an asynchronous job through a queue, UseSources can re-sync large workspaces routinely. When syncing is heavy, you want to lower how often you re-sync, and the index gets old — asynchronous processing breaks that vicious cycle.

Second, using semantic search and word search together. Vector search (which searches by closeness of meaning) is strong on paraphrases but weak on exact matches for proper nouns and model numbers. Full-text search is the opposite. Making it a hybrid of both lets you pull up both a vague query like "that incident yesterday" and a specific identifier like "P2002."

Third, a design that returns where things live. When an agent returns only a summary, the reader has no way to verify it. The UseSources agent returns answers with a citation — "this part of this document." If you are building an internal RAG, I recommend starting with citations. Trust comes not from the fluency of a summary but from the certainty of its source.

Is it a replacement for Notion or Slack?

I get asked this often, so let me state the positioning plainly. UseSources is not a tool that says "let's stop using Notion, Slack, and Jira entirely, starting tomorrow."

A real organization has an accumulated history and habits built up in its existing tools. So UseSources takes two stages. The past is ingested into RAG through connectors and turned into a searchable asset. The current work starts turning on the project axis. Migration is not an overnight move; it starts with search getting a single entry point, and the everyday place work lives gradually converges from there.

We did not move everything at once ourselves either. We began by using it as a single entry point for search, then started running new projects on top of UseSources one at a time. Building a structure that does not force migration is, as it turns out, what made adoption stick faster.

A lesson from an accident

It was not all smooth sailing. Here is one memorable accident. We were building the screens first with mock data and then wiring them to real data later, but at the point of the switch we cut everything over without keeping the promise to "preserve the mock-data state as well." The demo data all got wiped, and we even shipped a bug where an internal string was exposed in the search box. It was a failure of moving ahead without preserving the state before the switch. After that we strengthened the discipline of fixing the spec before implementing. Turning a failure into a mechanism of discipline afterward is something we enforce across all of our development.

Behind the build — restarting a stalled prototype, spec-first

The build of UseSources shows off the "template for developing with AI" I have written about throughout this series.

Its predecessor was the "integrated knowledge search" prototype from a year earlier, which had stalled. When restarting it, the first thing I did was not write code but put the documents in order. Establish the formats for records of design decisions (ADR), the basic design (SDD), and the detailed design (TDD), and connect them to task management. This ramp-up took four days. From then on I proceeded while recording every design decision, and in four months the ADRs numbered thirty.

The volume of activity is on record too. Commits in the restart month: 12. The next month, 76; the month after that, a peak of 245; then 112. As the numbers show, the first two months were spent searching for direction, and the moment the axis was fixed, implementation exploded. The reason this pace holds up even through two pivots is that every decision is recorded in documents, so when you overturn one, "what exactly you are overturning" is clear.

One more thing established in this product: the practice of fixing the look of the screens before implementing. I built more than twelve screens up front with wireframes and mock data, got agreement on the look, and then wired in the substance. The demo-data-loss accident above happened at that switch, but the method itself is right, and after the accident I made preserving the pre-switch state mandatory and kept using it.

Where it is now

UseSources is running in production (app.usesources.com) and in daily use inside the company. The admin screen is isolated on a separate host, and the real-time editing communication runs on a cost-controlled setup. It is at the stage of broadening the sources that external connectors support and improving the agent's accuracy.

How to start

You can open the app from usesources.com. I recommend starting by creating a single project and putting your usual notes and tasks there. For external connectors, connecting the source with the worst scatter first (often an old Notion or a shared drive) makes the effect the easiest to see.

To the worry that "adding a tool will make things messier," I answer this way. UseSources is not a tool that adds one tool; it is a tool that cuts the places you search down to one. Even without throwing away your existing tools, just giving search a single entry point visibly reduces the daily "where was that?"

Lessons you can carry over

  • Information fragmentation comes in two kinds: fragmentation within the workspace, and fragmentation out into external SaaS. The former is solved by unifying the axis, the latter by unifying into RAG. Search alone does not fix the former.
  • An agent that "returns where the answer lives" is more trusted in real work than one that "returns the answer." People only feel safe once they see the source.
  • Ask first whether a separate search engine is worth the scale. If Postgres vector search plus full-text search is enough for your scale, keeping the number of things you operate down lowers total cost.
  • Make large ingestion from external sources asynchronous from the start. Synchronous timeouts surface only after a workspace has grown.
  • Splitting tasks and documents into separate systems brings back the split in where work lives. Unifying with "a task is a kind of page" pays off for both search and permissions.

Top comments (0)