Company Knowledgebase Assistant
Load your Confluence pages, Slack threads, JIRA tickets and Figma notes into one table, with an embedding for each. Give your agent one tool that searches it by meaning. The inillucent client library is a normal import and a normal query, in Rust with the driver crate and in TypeScript with the npm package.
- You
What changed in the last production deploy?
- Agent calls a tool
search_knowledgebase("latest production deploy notes")
- Inillucent returns
- slack#eng-releases2026-09-22
- confluenceRelease notes 4.122026-09-16
- confluenceChangelog, August2026-09-01
- Agent
4.13 went out to production on September 22 (#eng-releases). It includes the ledger migration, and the rollback plan is in the runbook if it misbehaves. The deploy before that was 4.12 on September 16, with the new checkout flow, faster search indexing and two fixes to the billing export (Release notes 4.12).
cargo add inillucent-driver inillucent-engine \ --git https://github.com/Black-Rainbow-Labs/Inillucent \ --features inillucent-engine/embed cargo add serde_json cargo add reqwest --features blocking,json
src/main.rs
use inillucent_driver::{Database, Value};
use serde_json::{json, Value as Json};
type Error = Box<dyn std::error::Error>;
/// Finds the five documents closest in meaning to the text.
fn search_knowledgebase(db: &Database, text: &str) -> Result<Json, Error> {
let rows = db.session().query(
"SELECT source, title, body, written
FROM doc
ORDER BY vector_distance_cos(v, embed('search_query: ' || ?1))
LIMIT 5",
&[Value::Text(text.into())],
5,
)?;
let docs: Vec<Json> = rows
.rows
.iter()
.map(|row| json!({ "source": row[0].text(), "title": row[1].text(), "body": row[2].text(), "written": row[3].text() }))
.collect();
Ok(json!(docs))
}
/// Answers a question, letting the model search as often as it needs.
fn ask(db: &Database, question: &str) -> Result<String, Error> {
let client = reqwest::blocking::Client::new();
let key = std::env::var("ANTHROPIC_API_KEY")?;
let tools = json!([{
"name": "search_knowledgebase",
"description": "Search Confluence, Slack, JIRA and Figma by meaning.",
"input_schema": {
"type": "object",
"properties": { "query": { "type": "string" } },
"required": ["query"]
}
}]);
let mut messages = vec![json!({ "role": "user", "content": question })];
loop {
let response: Json = client
.post("https://api.anthropic.com/v1/messages")
.header("x-api-key", &key)
.header("anthropic-version", "2023-06-01")
.json(&json!({
"model": "claude-opus-5",
"max_tokens": 16000,
"system": "Answer from the knowledge base. Cite your sources.",
"tools": tools,
"messages": messages,
}))
.send()?
.json()?;
let content = response["content"].as_array().cloned().unwrap_or_default();
if response["stop_reason"] != "tool_use" {
return Ok(content.iter().filter_map(|block| block["text"].as_str()).collect());
}
messages.push(json!({ "role": "assistant", "content": content }));
let mut results = Vec::new();
for block in content.iter().filter(|block| block["type"] == "tool_use") {
let text = block["input"]["query"].as_str().unwrap_or_default();
let rows = search_knowledgebase(db, text)?;
results.push(json!({ "type": "tool_result", "tool_use_id": block["id"], "content": rows.to_string() }));
}
messages.push(json!({ "role": "user", "content": results }));
}
}
fn main() -> Result<(), Error> {
let db = Database::open("company.rdb")?;
println!("{}", ask(&db, "What changed in the last production deploy?")?);
Ok(())
}npm install inillucent @anthropic-ai/sdk
knowledgebase.ts
import { query } from 'inillucent';
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const db = 'company.rdb';
const tools: Anthropic.Tool[] = [{
name: 'search_knowledgebase',
description: 'Search Confluence, Slack, JIRA and Figma by meaning.',
input_schema: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query'],
},
}];
/** Finds the five documents closest in meaning to the text. */
function searchKnowledgebase(text: string) {
return query(
`SELECT source, title, body, written
FROM doc
ORDER BY vector_distance_cos(v, embed('search_query: ' || ?1))
LIMIT 5`,
{ db, params: [text] },
);
}
/** Answers a question, letting the model search as often as it needs. */
export async function ask(question: string): Promise<string> {
const messages: Anthropic.MessageParam[] = [
{ role: 'user', content: question },
];
while (true) {
const response = await client.messages.create({
model: 'claude-opus-5',
max_tokens: 16000,
system: 'Answer from the knowledge base. Cite your sources.',
tools,
messages,
});
if (response.stop_reason !== 'tool_use') {
return response.content
.flatMap((block) => (block.type === 'text' ? [block.text] : []))
.join('');
}
messages.push({ role: 'assistant', content: response.content });
const results: Anthropic.ToolResultBlockParam[] = [];
for (const block of response.content) {
if (block.type !== 'tool_use') continue;
const { query: text } = block.input as { query: string };
const rows = await searchKnowledgebase(text);
results.push({
type: 'tool_result',
tool_use_id: block.id,
content: JSON.stringify(rows),
});
}
messages.push({ role: 'user', content: results });
}
}




