Enterprise Knowledge Agent
Build a permission-aware Q&A assistant over internal docs (Confluence, Drive, Jira, Slack) - users only see answers from docs they're allowed to read.
Last updated: September 2026
A Q&A assistant over internal company docs (Confluence, Drive, Jira, Slack) that enforces per-user permissions - users only get answers from docs they're allowed to read. The agent ingests documents from multiple sources, stores embeddings alongside ACL metadata, enforces pre-filter permission checks at query time, retrieves with hybrid search, and synthesizes grounded answers with source citations.
“Permission enforcement is non-negotiable and must be pre-filter. ACL lives with the embedding in the index - not applied after retrieval. Every query is bound to an authenticated identity. Agent says I don't know rather than synthesize beyond permitted corpus.”
Clarifying Questions (Ask These First ~5 min)
| Question | Why it matters |
|---|---|
| Which data sources? (Confluence, Drive, Jira, Slack) | One connector needed per source |
| Permission model - RBAC, ABAC, or source-system ACLs? | Most critical design decision |
| How stale can the index be? (hours vs. seconds) | Drives sync strategy |
| Regulated industry (HIPAA, SOX)? | Audit log + data residency requirements |
| On-prem / air-gapped or cloud? | Constrains LLM and vector DB choices |
| Should agent cite sources? Say 'I don't know'? | Defines answer grounding policy |
Architecture (Draw This)
[Confluence / Drive / Jira / Slack]
↓ (connectors, webhooks)
[1] Ingest → Parse → Chunk → Embed → Store with ACL metadata
↓
[2] Permission-Aware Vector Index ←── Identity Provider (Okta / Google Workspace)
↓
User Query → [3] Auth + Identity Resolution → Audit log entry created
↓
[4] Permission Enforcement (pre-filter: only permitted doc IDs enter search)
↓
[5] Hybrid Retrieval (vector + BM25) → Re-rank
↓
[6] Context Assembly (top-N chunks + source labels)
↓
[7] LLM Synthesis (grounded answer + citations)
↓
Answer → User + Audit log completedKey Components (30-second pitch each)
- 1Ingestion Pipeline - One connector per source (Confluence API, Drive API, Jira REST). Track last_synced_at per doc for incremental sync. Chunk at ~512 tokens with 50-token overlap. Store { doc_id, url, acl_list, last_modified } alongside each vector.
- 2Permission-Aware Index - Most Critical Component - At index time, fetch the doc's ACL from the source and store it with the embedding. Cache user_id → permitted_doc_ids with 15-min TTL. Invalidate on permission-change events from IdP.
- 3Permission Enforcement - Pre-filter vs Post-filter - Pre-filter (recommended): pass ACL filter to vector DB query - unauthorized docs never fetched. Post-filter is unacceptable in regulated environments because unauthorized docs enter memory. Use pre-filter always.
- 4Hybrid Retrieval - Dense vector (semantic) + sparse BM25 (keyword). Enterprise queries have exact terms (project codenames, ticket IDs) that pure vector search misses. Merge with Reciprocal Rank Fusion (RRF), then apply cross-encoder re-ranker.
- 5LLM Synthesis - Prompt: answer from context only, cite every claim with [Doc Title](url), say 'I don't know' if answer isn't in context. PII redaction pass before sending chunks to cloud LLM.
- 6Audit Log - Immutable, append-only (BigQuery / S3 Object Lock). Record: { user_id, query, sources_cited, answer_summary, timestamp }. Compliance dashboard: who asked what, which docs were surfaced.
Sync Strategy
| Method | When | Latency |
|---|---|---|
| Webhooks | Confluence, Drive, Jira support push events | Seconds |
| Polling fallback | Sources without webhooks | 5-15 min |
| Full re-index | Never - incremental only via last_synced_at | - |
Security Threat Model
| Threat | Mitigation |
|---|---|
| User retrieves unauthorized doc | Pre-filter ACL at query time |
| Stale ACL exposes newly restricted doc | Event-driven invalidation + short TTL |
| Prompt injection in a malicious doc | Retrieved chunks = data section, never instruction section |
| Insider iteratively querying sensitive data | Rate limiting + audit anomaly detection |
3 Biggest Risks
- 1Permission staleness - Doc goes private but served for 15 min → mitigated by event-driven invalidation from IdP on permission changes.
- 2Corpus quality - Wikis are outdated and contradictory → freshness boost on retrieval + 'I don't know' grounding when no relevant content exists.
- 3LLM grounding drift - Model synthesizes beyond retrieved context → strict context-only prompt instruction + mandatory source citation requirement.
Google Stack: Google Workspace (source) → Vertex AI Search with data store ACL integration → Gemini (synthesis LLM) → Vertex AI Vector Search (permission-filtered retrieval) → BigQuery (audit log) → Cloud Identity / Google Workspace IdP (identity resolution)
Azure Stack: SharePoint / OneDrive / Azure DevOps (sources) → Azure Data Factory (connectors) → Azure AI Search / Foundry IQ (hybrid BM25 + vector, native ACL pre-filter) → Azure Entra ID (identity + transitive group resolution) → Azure OpenAI GPT-4o (synthesis LLM) → Azure Cache for Redis (permission cache, 15-min TTL) → Azure Monitor (audit log)
AWS Stack: Confluence / SharePoint / S3 (sources) → AWS Glue (connectors) → Amazon Bedrock Knowledge Bases + OpenSearch Serverless (managed RAG, hybrid retrieval) → AWS IAM Identity Center (identity resolution) → Amazon Bedrock / Claude (synthesis LLM) → ElastiCache Redis (permission cache) → CloudTrail + CloudWatch Logs (audit log)
Other Options: Elasticsearch + Qdrant + OpenAI (open-source, full control over ACL logic) | Pinecone + LlamaIndex + Anthropic Claude (serverless vector DB path) | Microsoft 365 Copilot (if Microsoft-only stack, zero-integration, but limited customization)
Frequently asked questions
What if a doc's permissions change mid-session?
15-min TTL bounds the exposure window. For high-sensitivity changes (doc going private), source system pushes an event that immediately invalidates the cache - doesn't wait for TTL.
How do you handle nested group memberships (User → Team A → Org B)?
Flatten the full transitive group hierarchy at index time. At query time, resolve user's full transitive group membership from IdP and check intersection. Cache this - it's an expensive graph traversal.
500k internal docs across 10 systems - does the index scale?
500k docs × ~5 chunks = 2.5M vectors. At 768 dims = ~7GB raw vectors - well within Vertex AI Vector Search or Pinecone range. Bottleneck is ACL resolution + metadata filtering, not vector search.
No good match in corpus - what does the agent say?
Set a similarity score threshold. If top result is below threshold → 'I couldn't find relevant information' instead of hallucinating. Optionally route to a human expert.
How do you evaluate retrieval quality over time?
Track implicit feedback (was cited doc clicked?), explicit thumbs up/down, and offline golden Q&A test set from real queries. Monitor retrieval precision@K and answer grounding rate.
Merger - need to integrate another company's knowledge base?
Add connectors for acquired company's sources. Key challenge: identity federation - map users across two IdPs. Until identity is unified, keep knowledge bases isolated with separate ACL namespaces.