Internal knowledge base
One workspace per team, answering staff questions from internal policy documents.
Staff ask questions of the policies, handbooks and contracts their team owns — and cannot reach another team's.
Architecture
One workspace per team. Because retrieval never crosses a workspace, the access rule is enforced by the boundary itself rather than by a filter you have to remember to apply.
- Map each team to a workspace id in your own configuration.
- Resolve the signed-in employee's team before choosing the workspace.
- Pass their employee id as external_user_id, so history is per person.
Setup
Create one workspace per team and upload that team's documents into it. Keep the mapping in your own config rather than deriving it from workspace titles, which are editable.
The code
The team lookup happens before any request, so an unknown team fails fast instead of asking the wrong corpus:
const BASE = "https://api.daneshyar.info/api/v1";
const KEY = process.env.DANESHYAR_API_KEY;
/**
* One workspace per team. Staff in Engineering never retrieve HR's documents,
* because retrieval cannot cross a workspace boundary — you don't filter, the
* boundary does it.
*/
const TEAM_WORKSPACES = {
engineering: "8f14e45f-ceea-467a-9f4c-1a2b3c4d5e6f",
people: "1d4c7b90-3e58-4a21-bf06-9c2e5d8a7f43",
};
export async function askAsEmployee({ employeeId, team, question }) {
const workspaceId = TEAM_WORKSPACES[team];
if (!workspaceId) throw new Error(`Unknown team: ${team}`);
const res = await fetch(`${BASE}/workspaces/${workspaceId}/chat/`, {
method: "POST",
headers: { "X-API-Key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({
// A stable employee id — not an email, which changes on a name change.
external_user_id: employeeId,
message: question,
}),
});
if (!res.ok) {
const body = await res.json().catch(() => ({}));
throw new Error(body.message ?? body.detail ?? `HTTP ${res.status}`);
}
const { data } = await res.json();
return data.assistant_message;
}
/** Their own history, and only theirs. */
export async function historyFor({ employeeId, team }) {
const url = new URL(`${BASE}/workspaces/${TEAM_WORKSPACES[team]}/chat/sessions/`);
url.searchParams.set("external_user_id", employeeId);
const res = await fetch(url, { headers: { "X-API-Key": KEY } });
const { data } = await res.json();
return data.results;
}What you get
Every employee gets answers from exactly the documents their team is allowed to see, with their own conversation history — and adding a team is one workspace and one config line.