A governed organizational context layer built on Omnigraph with branch-isolated ingestion, human review, typed knowledge, role-aware MCP access and grounded AI agents.
| Service | URL |
|---|---|
| Dashboard | https://analytos-brain-dashboard-production.up.railway.app |
| Backend health | https://analytos-brain-api-production.up.railway.app/health |
| API documentation | https://analytos-brain-api-production.up.railway.app/docs |
| MCP endpoint | https://analytos-brain-api-production.up.railway.app/mcp |
| GitHub repository | https://github.com/Aswani1402/analytos-brain |
The dashboard and public read endpoints are accessible without secrets. Ingestion, reviews and MCP tools require role-appropriate bearer credentials. No credentials are stored in this repository.
Analytos Brain turns product documents, ICP notes and customer conversations into governed organizational knowledge. Documents are never written directly to main. Every ingestion creates a separate Omnigraph branch containing extracted typed entities and relationships. A reviewer inspects a branch-versus-main diff and either approves the branch into main or rejects it.
The dashboard, hosted MCP endpoint and agents read approved knowledge from Omnigraph main. SQLite stores workflow and audit metadata only; Omnigraph remains the knowledge system of record.
Important organizational context is often scattered across product documents, ICP documents and communication threads. Ungoverned AI systems can retrieve stale, unapproved or confidential information if they read directly from raw documents or conversations. Agents need structured, attributable and access-controlled knowledge so they can answer with evidence rather than memory.
- Typed extraction converts source documents into schema-backed nodes and edges.
- Branch-isolated ingestion loads each extraction into its own Omnigraph branch.
- HITL review shows reviewers what would be added or changed before merge.
- Governed main graph stores only approved organizational knowledge.
- Role-aware retrieval and agents serve approved context through the dashboard, MCP and grounded agent endpoints.
flowchart LR
Seeds["Seed documents"] --> Extract["Extraction pipeline"]
Extract --> Validate["Pydantic validation"]
Validate --> IDs["Deterministic business IDs"]
IDs --> Branch["Unique Omnigraph ingestion branch"]
Branch --> Diff["HITL review diff"]
Diff --> Decision{"Reviewer decision"}
Decision -->|approve| Main["Omnigraph main graph"]
Decision -->|reject| Discard["Discard pending branch"]
Diff <--> SQLite["SQLite workflow and audit metadata"]
Main --> Dashboard["Hosted dashboard"]
Main --> MCP["Hosted MCP JSON-RPC"]
Main --> Content["Content Agent"]
Main --> GTM["GTM Agent"]
Cedar["Cedar policy + API/MCP enforcement"] -.-> Branch
Cedar -.-> Main
Cedar -.-> MCP
Cedar -.-> Content
Cedar -.-> GTM
Volume["Railway persistent volume /var/lib/omnigraph"] --> Main
Volume --> SQLite
- Upload or select a document.
- Extract typed entities and edges.
- Validate the extraction through Pydantic models.
- Generate deterministic business identifiers.
- Create a unique Omnigraph branch.
- Load extraction results into that branch.
- Display a branch-versus-main diff.
- Reviewer approves or rejects.
- Approval merges with actor attribution.
- Rejection discards the pending branch.
- Approved knowledge becomes available to the dashboard, MCP and agents.
No ingestion path writes directly to main.
Implemented node types from omnigraph/schema.pg:
| Node type | Purpose |
|---|---|
Product |
Product or offering context such as Stockly and Inspectly. |
Feature |
Product capabilities, integrations and product areas. |
ProofPoint |
Approved metrics, outcomes and evidence. |
Persona |
Buyer or stakeholder persona context. |
ICPSegment |
Ideal customer profile segment details. |
Person |
People referenced in governed business context. |
EmailThread |
Summarized internal/customer conversation thread metadata. |
Decision |
Decisions extracted from documented conversations. |
SourceDocument |
Source file metadata and provenance. |
ExtractionRun |
Ingestion run metadata for provenance and idempotency. |
Implemented relationship types:
| Edge type | Connects | Purpose |
|---|---|---|
HasFeature |
Product -> Feature |
Associates products with capabilities. |
ProvenBy |
Product -> ProofPoint |
Connects products to supporting evidence. |
SupportedBy |
Feature -> ProofPoint |
Connects features to proof points. |
Targets |
Product -> ICPSegment |
Maps products to ICP segments. |
HasPersona |
ICPSegment -> Persona |
Maps ICP segments to personas. |
Discusses |
EmailThread -> Product |
Links conversation summaries to products. |
DiscussedIn |
Decision -> EmailThread |
Links decisions to source threads. |
DecidedBy |
Decision -> Person |
Links decisions to people. |
Processed |
ExtractionRun -> SourceDocument |
Records source documents processed by a run. |
The supplied seed documents live in seed-data/:
stockly-product-overview.mdinspectly-product-overview.mdicp-analytos.mdemail-01-stockly-pilot-thread.mdemail-02-inspectly-medical-thread.md
They were ingested through separate Omnigraph branches and approved through the HITL workflow.
| Entity | Count |
|---|---|
| Products | 2 |
| Features | 11 |
| Proof points | 8 |
| ICP segments | 2 |
| Personas | 4 |
| Decisions | 6 |
| People | 3 |
| Email threads | 2 |
Repeat Stockly ingestion did not change business-entity counts. Only provenance such as ExtractionRun and Processed records was added. Hosted persistence was verified after a backend restart.
Every extraction has a review record. Reviewers inspect added nodes, added edges and source information before merge. Self-approval is denied. Approvals record the reviewer actor. Rejection removes or discards the pending branch. Agents read approved main only and cannot read pending branches.
Relevant docs:
The Content Agent reads approved main only and requires the content-agent role. It uses at least three approved facts or proof points, returns graph slugs, source documents and evidence, excludes EmailThread and internal conversation content, and produces deterministic grounded drafts by default.
Sanitized response shape:
{
"topic": "reducing inventory risk",
"facts_used": ["..."],
"graph_slugs": ["..."],
"source_documents": ["..."],
"draft": "..."
}The GTM Agent reads approved ICP, persona, product, feature and safe proof-point context. It returns a target profile, persona, triggers, opening angle and evidence. It provides three companies explicitly labelled as illustrative and does not claim they are actual Analytos customers.
Sanitized response shape:
{
"target_company_profile": "...",
"persona_to_contact": "...",
"trigger_signals": ["..."],
"grounded_opening_angle": "...",
"illustrative_companies": ["..."],
"graph_evidence": ["..."]
}Hosted endpoint:
https://analytos-brain-api-production.up.railway.app/mcp
Local stdio command:
python -m mcp.serverImplemented hosted tools:
search_contextget_productget_product_featuresget_product_proof_pointsget_icp_segmentsget_personasget_recent_changes
Hosted MCP uses JSON-RPC methods initialize, tools/list and tools/call. Bearer tokens map server-side to actors, so client-supplied actors cannot impersonate another role. Tools read approved main; EmailThread retrieval is denied for content-agent.
| Role | Main responsibilities |
|---|---|
reviewer |
Inspect and approve/reject reviews. |
content-agent |
Approved content-safe graph reads. |
gtm-agent |
Approved GTM/ICP/persona graph reads. |
dashboard-reader |
Approved dashboard read access. |
ingestion-service |
Ingestion branch creation without direct main writes. |
Omnigraph native Cedar policy handles coarse graph and branch actions. API and MCP enforcement handles fine-grained node-type restrictions. content-agent cannot access EmailThread data. ingestion-service cannot write directly to main. dashboard-reader cannot invoke restricted agent actions. Protected hosted endpoints use bearer authentication.
Relevant files:
| Area | Technology |
|---|---|
| Knowledge graph | Omnigraph 0.8.1, .pg schema, typed .gq stored queries, Cedar policy |
| Backend | Python, FastAPI, Pydantic, SQLite for workflow metadata |
| Extraction | Deterministic rule-based extractor, optional Gemini structured-output adapter |
| Frontend | React, TypeScript, Vite |
| Deployment | Railway, Docker, persistent volume, GitHub Actions container smoke check |
agents/ Content and GTM agent implementations
apps/ FastAPI backend and React dashboard
api/ Hosted API, routers, services and auth logic
dashboard/ Vite/React dashboard
docs/ Architecture, API, access-control, deployment and demo docs
mcp/ Local MCP stdio wrapper and hosted tool implementation
omnigraph/ Schema, stored queries and cluster template
pipeline/ Extraction and normalization pipeline
policies/ Cedar policy
scripts/ Smoke tests, verification and hosted helpers
seed-data/ Five supplied assignment documents
tests/ API, pipeline, agent, auth and MCP tests
git clone https://github.com/Aswani1402/analytos-brain.git
Set-Location analytos-brainpython -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txtOmnigraph 0.8.1 CLI and server binaries must be available locally. On Windows, this repository expects the CLI at:
$HOME\.local\bin\omnigraph.exe
Copy-Item .env.example .envImportant variables:
OMNIGRAPH_BINOMNIGRAPH_GRAPH_URIANALYTOS_DB_PATHINGEST_OUTPUT_DIREXTRACTION_PROVIDERLLM_PROVIDERLLM_MODELLLM_API_KEYANALYTOS_API_TOKENANALYTOS_MCP_TOKENS_JSONANALYTOS_CORS_ORIGINS
.env must not be committed.
Get-ChildItem omnigraph\queries\*.gq | ForEach-Object {
& "$HOME\.local\bin\omnigraph.exe" lint --schema omnigraph\schema.pg --query $_.FullName
if ($LASTEXITCODE -ne 0) {
throw "Lint failed for $($_.FullName)"
}
}python -m uvicorn apps.api.main:app --host 127.0.0.1 --port 8000Set-Location apps\dashboard
npm.cmd install
npm.cmd run dev -- --host 127.0.0.1Invoke-RestMethod http://127.0.0.1:8000/healthEXTRACTION_PROVIDER=rule-based
Rule-based extraction is used for deterministic offline seed and demo flows.
EXTRACTION_PROVIDER=llm
LLM_PROVIDER=gemini
LLM_MODEL=<model>
LLM_API_KEY=<secret>
The Gemini adapter requests structured JSON output, validates with Pydantic, retries malformed output and rejects unsupported types. It does not silently fall back to rule-based extraction.
| Group | Endpoint | Auth |
|---|---|---|
| Health | GET /health |
Public |
| Ingestion | POST /ingestions |
API bearer |
| Ingestion | GET /ingestions |
Public |
| Ingestion | GET /ingestions/{run_id} |
Public |
| Reviews | GET /reviews |
API bearer |
| Reviews | GET /reviews/{run_id} |
API bearer |
| Reviews | POST /reviews/{run_id}/approve |
API bearer |
| Reviews | POST /reviews/{run_id}/reject |
API bearer |
| Entities/search | GET /entities/products |
Public |
| Entities/search | GET /entities/products/{slug} |
Public |
| Entities/search | GET /entities/features |
Public |
| Entities/search | GET /entities/proof-points |
Public |
| Entities/search | GET /entities/icp-segments |
Public |
| Entities/search | GET /entities/personas |
Public |
| Entities/search | GET /entities/people |
API bearer |
| Entities/search | GET /entities/email-threads |
API bearer |
| Entities/search | GET /entities/decisions |
Public |
| Entities/search | GET /search?q=<query> |
Public |
| Entities/search | GET /changes/recent |
Public |
| Agents | POST /agents/content |
Actor policy |
| Agents | POST /agents/gtm |
Actor policy |
| MCP | POST /mcp |
MCP bearer |
Python test suite:
python -m pytest -q --basetemp .tmp\pytest-readmeVerified result:
53 passed
Dashboard build:
Push-Location apps\dashboard
npm.cmd install
npm.cmd run build
Pop-LocationOmnigraph query lint:
Get-ChildItem omnigraph\queries\*.gq | ForEach-Object {
& "$HOME\.local\bin\omnigraph.exe" lint --schema omnigraph\schema.pg --query $_.FullName
if ($LASTEXITCODE -ne 0) {
throw "Lint failed for $($_.FullName)"
}
}Container configuration check:
python scripts\verify_container_config.pyThe hosted architecture uses a Railway backend service, a Railway dashboard service and a persistent volume. Dockerfile.api installs Omnigraph 0.8.1 CLI and server binaries in the backend image. SQLite and Omnigraph runtime data are stored on the Railway volume mounted at /var/lib/omnigraph. The governed bootstrap runs after deployment, and backend restart persistence was verified.
The current dashboard service was deployed from the verified apps/dashboard build archive after the repository-level Railway configuration conflicted with the separate dashboard Dockerfile. The hosted dashboard remains functional and uses the hosted API.
Relevant deployment files:
| Requirement | Implementation |
|---|---|
| Typed Omnigraph schema | completed |
| Five-document ingestion | completed |
| LLM extraction adapter | implemented/configurable |
| Separate ingestion branches | completed |
| HITL diff and review | completed |
| Approve/merge and reject/discard | completed |
| Actor attribution | completed |
| Dashboard | hosted |
| MCP | hosted |
| Cedar policy | configured |
| Content Agent | completed |
| GTM Agent | completed |
| Persistent hosted storage | verified |
| Idempotent re-ingestion | verified |
- Secrets are environment-based.
- Local deployment credentials are Git-ignored.
- Protected routes require bearer tokens.
- Actor identity is resolved server-side for hosted MCP.
- No ingestion path writes directly to
main. - Pending branches are invisible to agents.
- Client/internal
EmailThreaddetails are filtered fromcontent-agent. - Runtime
.dband.omnifiles are not committed.
- Hosted verification used deterministic rule-based extraction.
- Gemini extraction requires a valid external API key.
- Native Cedar support is coarse at graph/branch level in the tested Omnigraph version.
- Fine-grained node-type policy is implemented in API/MCP.
- Illustrative GTM companies are not claimed as real customers.
- This is an assignment POC, not a complete enterprise identity platform.
Aswani A. J
- GitHub: https://github.com/Aswani1402
- Email: aswiniayappan14@gmail.com
No license file is included. This project was developed as an Analytos internship take-home assignment.