Skip to main content

3. Knowledge

The tool from step 2 tells the model which documents exist. Now you give it their content: you ingest every document, and the pipeline adds the closest passages to the context of each request.

Add the crate​

docs-assistant/Cargo.toml
[dependencies]
beam_knowledge = { path = "../riverbeam/crates/beam_knowledge" }

Ingest at startup​

docs-assistant/src/knowledge.rs
use beam_knowledge::{build_knowledge_from_env, KnowledgeManager, KnowledgeScope};
use uuid::Uuid;

/// Build the knowledge manager from the environment and ingest every document under `docs/`.
pub async fn load(names: &[String]) -> Result<KnowledgeManager, Box<dyn std::error::Error>> {
let knowledge = build_knowledge_from_env(1536).await?;
for name in names {
let text = std::fs::read_to_string(format!("docs/{name}"))?;
// A stable id per file: ingesting it again replaces its chunks instead of adding copies.
let document_id = Uuid::new_v5(&Uuid::NAMESPACE_URL, name.as_bytes());
let result = knowledge
.ingest(&text, Some(document_id), Some(KnowledgeScope::system()), None, None, Some(name.clone()))
.await?;
println!("ingested {name}: {} chunks", result.chunk_count);
}
Ok(knowledge)
}

Uuid::new_v5 needs the v5 feature of uuid:

docs-assistant/Cargo.toml
uuid = { version = "1", features = ["v4", "v5", "serde"] }

Attach it to the pipeline in main:

docs-assistant/src/main.rs
mod knowledge;

// in main, after collecting the names:
let names = document_names()?;
let tools: Vec<Arc<dyn Tool>> = vec![Arc::new(tools::ListDocuments { names: names.clone() })];

let mut beam = RiverBeam::new(BeamConfig::default());
beam.set_knowledge(Arc::new(knowledge::load(&names).await?));
beam.register_agent(Arc::new(agents::assistant(tools)));

Which embedder you get​

With no environment set, the factory uses a hash embedder and an in-memory store: no network, good enough to see retrieval work. With BEAM_API_KEY set it calls an embeddings endpoint. To keep the vectors in Postgres, enable the crate's postgres feature and set BEAM_DATABASE_URL; the table needs 1536-dimension embeddings. All the options are in Knowledge.

What the model sees​

For a question such as "How do I reset my password?", the pipeline retrieves the four closest chunks from your documents and puts them first in the history:

Relevant knowledge:
[1] To reset your password, open Settings and …
[2] …

The agent does not need to change: retrieval is part of the pipeline, not the agent.

Knowledge is shared by every request

Retrieval in the pipeline is not filtered by user or scope, so every caller can be shown any ingested passage. That is fine for public documentation. Do not ingest private documents into this store.

Next: serve it over HTTP.