Skip to content

eva-foundry/33-eva-brain-v2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

EVA Brain v2

EVA Ecosystem Integration

Tool Purpose How to Use
37-data-model Single source of truth for all project entities GET http://localhost:8010/model/projects/33-eva-brain-v2
29-foundry Agentic capabilities (search, RAG, eval, observability) C:\eva-foundry\eva-foundation\29-foundry
48-eva-veritas Trust score and coverage audit MCP tool: audit_repo / get_trust_score
07-foundation-layer Copilot instructions primer + governance templates MCP tool: apply_primer / audit_project

Agent rule: Query the data model API before reading source files.

Invoke-RestMethod "http://localhost:8010/model/agent-guide"   # complete protocol
Invoke-RestMethod "http://localhost:8010/model/agent-summary" # all layer counts

Enterprise Virtual Assistant - AI Brain Service
Domain: Jurisprudence, case law search, document ingestion
Stack: Python 3.10+, FastAPI, Azure OpenAI, Azure AI Search, Azure Cosmos DB
Status: Code complete ? Sprint 6 Deployment in progress | see STATUS.md
Last Updated: February 25, 2026 @ 09:00 ET


Architecture

EVA Brain v2 is composed of two FastAPI microservices:

Service Port Purpose
eva-brain-api 8001 Chat, RAG, document ingestion, sessions, assistants
eva-roles-api 8002 RBAC resolution, persona switching, cost tag evaluation

All protected eva-brain-api routes call eva-roles-api to validate the actor session and resolve features. Both services are fully present on disk (Sprint 0, Feb 19 ? see STATUS.md).

Azure Services Used

Service Resource Purpose
Azure OpenAI marco-sandbox-openai Chat completions, embeddings
Azure AI Foundry marco-sandbox-foundry Agent framework, model deployments (gpt-4o, gpt-4o-mini, text-embedding-ada-002)
Azure AI Search marco-sandbox-search Vector, keyword and hybrid search over jurisprudence indexes
Azure Cosmos DB marco-sandbox-cosmos Sessions, jobs, audit logs, documents
Azure Blob Storage marcosand20260203 Document upload (raw), processed content, audit trail
Azure Storage Queues marcosand20260203 9-queue pipeline for document processing
Azure Document Intelligence marco-sandbox-docint PDF parsing, layout and table extraction
Azure Computer Vision marco-sandbox-aisvc Image OCR and captioning
Azure Text Analytics (sandbox cognitive) Entity extraction, PII detection
Azure Translator (sandbox cognitive) EN/FR translation
Azure API Management marco-sandbox-apim Rate limiting, product tiers, auth gateway
Azure Monitor / App Insights marco-sandbox-appinsights Metrics, traces, logs (OpenTelemetry)

Key Patterns

Request Headers (all protected routes)

X-Actor-OID          -- AAD Object ID of the acting user
X-Correlation-ID     -- Request tracing ID (propagated through all services)
X-Acting-Session     -- Validated session token from eva-roles-api
X-Caller-App         -- Calling application identifier (default: "unknown")
X-Environment        -- Deployment environment (default: "dev")

RBAC

Every protected endpoint is decorated with @require_feature(FeatureID.*). The decorator calls eva-roles-api to validate the session and check feature access. A 403 is returned if the persona does not have the required feature. Public endpoints (config, health, translations) bypass RBAC.

Lane A Logging (no raw content)

No prompts, responses, or document text are ever stored in logs or audit records. Only hashes (SHA-256, 16-char), counts, scores, durations, and IDs are logged. Use hash_content() and create_safe_result_summary() from app.models.agent.

Cost Attribution

Every agent invocation includes CostTags (phase, task, project, costcenter, persona_id, actor_oid). These are used for FinOps charge-back and Azure cost management.


Personas

Defined in services/eva-brain-api/config/personas.yml:

Persona Tools Indexes Max tokens/turn Autonomy
legal-researcher hybrid_search, semantic_search, keyword_search, chat_completion, log_audit, check_quality case-law, statutes 4,000 high
legal-clerk keyword_search, chat_completion case-law 1,000 low
admin all 7 tools case-law, statutes, policies 8,000 high

API Overview

Group Endpoints Status
Chat & RAG POST /v1/chat, /v1/chat/rrr, /v1/chat/rtr, /v1/chat/work, /v1/chat/hybrid, /v1/chat/ungrounded, /v1/chat/read-retrieve-read, GET /v1/chat/approaches ? Route present
Retrieve POST /v1/retrieve ? Route present
Sessions POST/GET/PATCH/DELETE /v1/sessions, /v1/sessions/{id} ? Route present
Documents GET/PATCH/DELETE /v1/documents/*, /v1/documents/{id}/chunks download
Ingest POST /v1/ingest/upload url, GET /v1/ingest/status/{id}
Tags GET /v1/tags, /v1/tags/{tag}, /v1/tags/{tag}/documents ? Route present
Search Saved searches and history ? Route present
Admin POST /v1/users, GET /v1/groups ? Route present
Config GET /v1/config/info features
Health GET /v1/health, /v1/health/background ? Route present
RBAC (roles) POST /v1/roles/acting-as, GET /v1/roles/context features
Assistants POST /v1/assistant/math/, /v1/assistant/tabular/ ? Implemented (Sprint 5)
Logs GET /v1/logs/audit/, /v1/logs/content/ ? Implemented (Sprint 5)
Translations (write) PUT/PATCH/DELETE /v1/config/translations/{lang} ? Implemented (Sprint 5)
Settings GET/PATCH /v1/settings ? Implemented (Sprint 5)
Apps Registry GET/POST/PATCH/DELETE /v1/apps, /v1/apps/{id}/disable export
Scrum (partial) GET /v1/scrum/dashboard, /v1/scrum/summary [CODED] on disk (Sprint 7, untested)
Projects Plane GET /v1/projects, /v1/projects/{id blocked
WBS / Critical Path GET /v1/wbs, /v1/wbs/{id critical-path
ADO Sync (pull) POST /v1/ado/sync, GET /v1/ado/sync/status [PLANNED] Sprint 7
ADO Sync (push) PATCH /v1/ado/wi/{tag}/state, POST /v1/ado/wi [PLANNED] Sprint 8
Evidence Proxy GET /v1/evidence/{id by-wi

Implemented: 60/60. Planned Sprint 7: +13. Planned Sprint 8: +12.


Document Ingestion Pipeline

Queue-based pipeline using 9 Azure Storage Queues, 11-step state machine:

Upload -> Route -> Parse -> Enrich Text -> Enrich Images -> Chunk -> Embed -> Index -> Update Status -> Log -> Notify

5 document processors: PDF (Azure Document Intelligence), DOCX, XLSX, TXT, Image (Azure Computer Vision)
3 enrichment services: Translation (EN/FR), Entity Extraction, PII Redaction
3 chunking strategies: semantic, fixed (750 tokens + 50 overlap), paragraph
Batch embedding: 16 texts per Azure OpenAI request
Performance target: <2 min upload-to-index for 10-page PDF

All pipeline service files are present on disk. The 6 ingest route endpoints are present in app/routes/ingest.py.


Agent Framework

The agent framework is in app/agents/. Three files are on disk:

  • conversation_agent.py -- ConversationAgent.invoke(), multi-turn orchestration, 8-hour TTL
  • tools.py -- AgentTools, 7 registered tools (hybrid_search, semantic_search, keyword_search, chat_completion, log_audit, check_quality, get_rbac_context)
  • persona_constraints.py -- PersonaConstraintsService, loads from config/personas.yml

Agent models are in app/models/agent.py (540 lines, fully present): ToolInvocation, ThoughtTrace, ReasoningTrace, ConversationTurn, ConversationContext, PersonaConstraints, AgentResponse

The Azure AI Foundry client is in app/clients/foundry_client.py.


Development Setup

Environment Variables

Copy and populate all 20+ variables. Required variables (see tests/conftest.py for full list):

# Azure OpenAI
AZURE_OPENAI_ENDPOINT=https://marco-sandbox-foundry.cognitiveservices.azure.com/
AZURE_OPENAI_DEPLOYMENT=gpt-4o
AZURE_OPENAI_API_KEY=...
AZURE_OPENAI_API_VERSION=2024-02-01

# Azure AI Search
AZURE_SEARCH_ENDPOINT=https://marco-sandbox-search.search.windows.net
AZURE_SEARCH_INDEX=case-law
AZURE_SEARCH_API_KEY=...

# Azure Cosmos DB
AZURE_COSMOS_ENDPOINT=https://marco-sandbox-cosmos.documents.azure.com:443/
AZURE_COSMOS_KEY=...
AZURE_COSMOS_DATABASE=statusdb

# Azure Storage
AZURE_STORAGE_ACCOUNT_NAME=marcosand20260203
AZURE_STORAGE_ACCOUNT_KEY=...
AZURE_STORAGE_CONTAINER=upload

# Azure Cognitive Services
AZURE_COMPUTER_VISION_ENDPOINT=...
AZURE_COMPUTER_VISION_KEY=...
AZURE_TRANSLATOR_ENDPOINT=...
AZURE_TRANSLATOR_KEY=...
AZURE_TRANSLATOR_REGION=canadacentral
AZURE_TEXT_ANALYTICS_ENDPOINT=...
AZURE_TEXT_ANALYTICS_KEY=...

# App
ROLES_API_URL=http://localhost:8002
ENVIRONMENT=dev
LOG_LEVEL=INFO
APPINSIGHTS_CONNECTION_STRING=...

Running Tests

cd services/eva-brain-api
pip install -r requirements.txt
pytest -v --cov=app tests/

Current state: 577/577 tests passing, 72% coverage.


Project Structure

33-eva-brain-v2/
  .github/
    copilot-instructions.md
  contracts/
    schemas/                      -- JSON Schema contracts (6 files)
  docs/
    agent-framework-guide.md
    api-migration-phase-2.md
    eva-faces-integration-guide.md
    performance-benchmarks.md
    runbooks/
  services/
    eva-brain-api/
      app/
        agents/                   -- ConversationAgent, AgentTools, PersonaConstraintsService
        clients/                  -- FoundryClient (Azure AI Projects SDK)
        decorators/               -- feature_guard.py (@require_feature)
        exceptions.py             -- EVAException hierarchy
        middleware/               -- rbac.py (RBACMiddleware)
        models/
          agent.py                -- All agent Pydantic models
          cost.py                 -- CostTags
          features.py             -- FeatureID enum
        routes/                   -- All 11 route files present
        services/                 -- All service files present
        utils/
      config/
        personas.yml
      openapi/
        agent-schemas.yaml
      tests/                      -- 577 tests, 72% coverage
    eva-roles-api/                -- Full service, port 8002
  translations/
    en.json
    fr.json
  README.md                       -- This file
  STATUS.md                       -- Current implementation status
  PLAN.md                         -- Sprint plan (Sprint 6 active)
  ACCEPTANCE.md                   -- Acceptance criteria and sign-off
  FOUNDRY-DEPLOYMENT-GUIDE.md     -- Sprint 6 deployment reference
  FOUNDRY-QUICK-REFERENCE.md      -- Azure CLI quick reference
  DEPLOY-VIA-CODESPACES.md        -- Deployment via GitHub Codespaces

37-data-model Integration ? Query It First, Every Session

The most expensive mistake a Copilot agent makes in this repo is reading source files to answer questions the model already knows.
Before grep_search, before file_search, before read_file ? check http://localhost:8010/model/{layer}/. That is a 3-line query. The alternative is a 10-turn spiral.

37-data-model (port 8010) is the semantic repository for the entire EVA ecosystem ? a Siebel-style object model with 27 layers, query-over-HTTP via FastAPI, and Siebel audit columns (modified_by, row_version, source_file) on every write. It already catalogs brain-v2's services, personas, feature flags, containers, and endpoints.

What it already knows about brain-v2

Layer What it tracks Objects
L0 services eva-brain-api (port 8001), eva-roles-api (port 8002) 2
L1 personas admin, legal-researcher, legal-clerk, machine-agent, auditor 5
L2 feature_flags action.chat, action.retrieve, action.ingest, action.search, action.admin.* 10
L3 containers sessions, jobs, audit_logs, documents, translations, settings, apps 13
L4 endpoints 60 brain-v2 endpoints (52 implemented, rest stub/planned) 60
L5 schemas Request/response shapes for all 60 endpoints 36
L9 infrastructure marco-sandbox-* Azure resources, APIM, Key Vault secrets 23
L25 projects 33-eva-brain-v2 project record (maturity, ADO epic, pbi_done/total, depends_on) 1
L26 wbs WBS deliverable nodes for brain-v2 sprints n

Note: The eva-brain-api service record was updated Feb 25 (row_version=5): status=running, notes=Sprint 5 complete (577/577 tests, 60/60 endpoints, POC trusted-subsystem verified Feb 24). Commit clean: violations=0, exported=3932.


Integration points ? current and planned

1. Feature flags and persona matrix (eva-roles-api, Sprint 6+)

Current state: app/models/features.py (FeatureID enum) and config/personas.yml are both maintained manually. If they diverge from 37-data-model/model/feature_flags.json, the authoritative source is unclear.

Integration: At eva-roles-api startup, rbac_service.py could call:

# Option: query 37-data-model at startup to build persona ? features map
GET http://localhost:8010/model/personas/   # ? list with feature_flags[]
GET http://localhost:8010/model/feature_flags/  # ? each with personas[]

This makes config/personas.yml and FeatureID the runtime cache and 37-data-model the source of truth, eliminating drift. The model already has the correct mapping.

When: Can be done in Sprint 6 or Sprint 7 ? no new endpoints needed in brain-v2.

2. New RBAC flags for PM Plane API (37-data-model must be updated first)

The three new feature flags that Sprint 7 and Sprint 8 require must be added to 37-data-model before @require_feature will work:

Flag Sprint Personas Write cycle
action.programme 7 pm_viewer, admin, auditor PUT /model/feature_flags/action.programme ? verify ? export ? assemble
action.ado_sync 7 admin, machine-agent same
action.ado_write 8 admin, machine-agent same

Block: brain-v2's @require_feature("action.programme") decorator will return 403 for everyone until this record exists in 37-data-model and is synced to eva-roles-api's feature map.

3. PM Plane API ? brain-v2 is the HTTP facade over 37-data-model L25/L26 (Sprint 7)

This is the most critical integration. The /v1/projects, /v1/wbs/*, and /v1/scrum/* endpoints that brain-v2 is building in Sprint 7 are APIM-facing proxies over 37-data-model's L25 and L26 layers. Brain-v2 does not own this data ? it reads from and writes back to 37-data-model.

APIM ? brain-v2 /v1/projects   ?  GET http://localhost:8010/model/projects/
APIM ? brain-v2 /v1/wbs        ?  GET http://localhost:8010/model/wbs/
APIM ? brain-v2 /v1/wbs/critical-path  ?  compute from model/wbs/ + GET /model/graph?...

The new service file project_plane_service.py (Sprint 7) must be a typed client over the model API, not over raw JSON files.

4. ADO sync write-back ? 4-step write cycle (Sprint 7?8)

Every ADO sync write from POST /v1/ado/sync or POST /v1/ado/wi must follow the API-first write protocol (captured in copilot-instructions.md):

1. PUT  /model/work_items/{wi_tag}      # stamps modified_at, modified_by, row_version
2. GET  /model/work_items/{wi_tag}      # verify field round-trips correctly
3. POST /model/admin/export             # materialize audit trail ? model/*.json
4. assemble-model.ps1                   # rebuild eva-model.json

Never write directly to model/*.json files ? doing so bypasses row_version and makes GET /model/admin/audit blind to the change. (This anti-pattern was recorded in 37-data-model/STATUS.md, Feb 22, 2026.)

5. Startup health check ? know if 37-data-model is available (Sprint 7)

Brain-v2's GET /v1/health/background should include a model_api field:

# In app/routes/health.py background health:
model_api_ok = await model_client.ping()  # GET http://localhost:8010/health
return { "status": "ok", "model_api": "ok" if model_api_ok else "unavailable" }

If 37-data-model is down, PM Plane endpoints should return 503 + Retry-After, not 500.

6. Impact analysis before any Cosmos schema change

Before modifying any container field in brain-v2 (e.g. adding a field to sessions, renaming a field in jobs):

# Which endpoints and screens break if I change the jobs container?
Invoke-RestMethod "http://localhost:8010/model/impact/?container=jobs"

This is the 37-data-model equivalent of a FK constraint check ? run it before every schema migration PR.


New service: model_api_client.py

Sprint 7 should introduce services/eva-brain-api/app/services/model_api_client.py ? a lightweight httpx.AsyncClient wrapper over port 8010:

class ModelAPIClient:
    base_url: str = "http://localhost:8010"

    async def get_projects(self, maturity: str | None = None, category: str | None = None) -> list[dict]
    async def get_wbs(self, level: str | None = None, project_id: str | None = None) -> list[dict]
    async def get_wbs_critical_path(self) -> list[dict]
    async def get_feature_flags(self) -> list[dict]
    async def put_work_item(self, wi_tag: str, payload: dict) -> dict  # write cycle step 1
    async def export(self) -> None                                      # write cycle step 3
    async def ping(self) -> bool

ROLES_API_URL already follows this pattern; add MODEL_API_URL=http://localhost:8010 as a new env var with the same fallback logic.


Related Projects

  • 31-eva-faces -- Frontend UI components (React/TypeScript) ? consumes brain-v2 API (see Downstream Dependencies below)
  • 29-foundry -- EVA Foundry Library: reusable agent skills, MCP servers, Python tools, Prompty templates ? consumes brain-v2 API as a proxy for PM agents (see Downstream Dependencies below)
  • 63-factory-context-auditor -- Workspace context auditing and repo-briefing

    Note: Project 63 is now the Factory Context Auditor, not a higher-level agent orchestration repo. Any future agent-orchestration assets should originate from 29-foundry rather than Project 63.

  • EVA-Jurisprudence-SecMode-Info-Assistant-v1.2 -- Production EVA JP deployment

Downstream Dependencies

31-eva-faces ? brain-v2

eva-faces is a consumer of brain-v2's REST API. The table below tracks which eva-faces pages depend on which brain-v2 endpoint group, and when brain-v2 will deliver them.

eva-faces Page / Component brain-v2 Endpoint(s) Brain Sprint Status
TranslationsPage PUT/PATCH/DELETE /v1/config/translations/{lang} Sprint 5 ? Done (Feb 20)
SettingsPage GET/PATCH /v1/settings Sprint 5 ? Done (Feb 20)
AppsPage GET/POST/PATCH/DELETE /v1/apps Sprint 5 WI-6 ? Done (Feb 20)
AuditLogsPage GET /v1/logs/audit/* Sprint 5 ? Done (Feb 20)
All data-plane pages (any live call) Both services deployed to Azure + APIM routing Sprint 6 ?? In progress (Feb 22 ?)
ProjectPortfolioPage (WI-F1?F6) GET /v1/projects, GET /v1/projects/{id}, GET /v1/projects/blocked, GET /v1/projects/by-stream Sprint 7 ?? Planned
WBSTreePage + CriticalPathPanel (WI-F10?F18) GET /v1/wbs, GET /v1/wbs/{id}, GET /v1/wbs/critical-path, GET /v1/wbs/by-sprint Sprint 7 ?? Planned
SprintBoardPage + SprintSummaryStrip + VelocityChart (WI-F19?F26) GET /v1/scrum/dashboard, GET /v1/scrum/summary, GET /v1/scrum/velocity, GET /v1/scrum/products Sprint 7 ?? Planned
DomainAssistantChatPage (Phase 3) POST /v1/chat (SSE streaming) + GET/POST/DELETE /v1/sessions + GET /v1/chat/approaches Sprint 6 (deploy) ?? Planned (live after Sprint 6 Azure deploy)
EvidenceViewerPanel (WI-F27+, Epic 4) GET /v1/evidence/{id}, GET /v1/evidence/by-wi/{tag}, GET /v1/runs, GET /v1/evidence/summary Sprint 8 ?? Planned
RbacPage / RbacRolesPage GET /v1/roles/personas, POST /v1/roles/acting-as, GET /v1/roles/features (eva-roles-api) Sprint 1 ? Done (Feb 19)

Roadmap for eva-faces unblocking:

Sprint 6  (active)  ? Both services deployed + APIM routing ? all live calls become possible
Sprint 7  (planned) ? PM Plane API live ? ProjectPortfolioPage, WBSTreePage, SprintBoardPage
Sprint 7  (planned) ? Scrum Dashboard + ADO Pull Sync ? SprintBoardPage live data
Sprint 8  (planned) ? Evidence Integration ? EvidenceViewerPanel live

RBAC flags that must be added to 37-data-model before eva-faces can use them: action.programme (Sprint 7), action.ado_sync (Sprint 7), action.ado_write (Sprint 8).


29-foundry ? brain-v2

29-foundry's PM agents use brain-v2 as a data proxy ? all PM Plane API calls from foundry agents go through brain-v2 rather than calling 37-data-model directly. The table below lists foundry's runtime tool calls.

29-foundry Agent / Tool brain-v2 Endpoint(s) Brain Sprint Status
pm-agent.py ? tool get_projects() (WI-A2) GET /v1/projects Sprint 7 ?? Planned
pm-agent.py ? tool get_wbs() (WI-A3) GET /v1/wbs Sprint 7 ?? Planned
pm-agent.py ? tool get_critical_path() (WI-A4) GET /v1/wbs/critical-path Sprint 7 ?? Planned
pm-agent.py ? tool get_sprint_status() (WI-A5) GET /v1/scrum/summary, GET /v1/scrum/dashboard Sprint 7 ?? Planned
pm-agent.py ? tool get_evidence_summary() (WI-A6) GET /v1/evidence/summary Sprint 8 ?? Planned
pm-agent-server.py HTTP wrapper (WI-A9) Full brain-v2 API on port 8001 (sandbox) Sprint 6 deploy ?? Planned
ado-sync-agent.py ? ADO pull sync (WI-A12) POST /v1/ado/sync, GET /v1/ado/sync/status Sprint 7 ?? Planned
sprint-planner-agent.py ? tool create_work_item() (WI-A22) POST /v1/ado/wi Sprint 8 ?? Planned

Structural (non-runtime) dependency: 29-foundry also imports ConversationAgent and AgentTools from brain-v2 as reference patterns into copilot-skills/azure-plane/eva-brain-v2/ and agent-framework/. This is a one-time code import, not a live call.

Roadmap for 29-foundry unblocking:

Sprint 6  (active)  ? brain-v2 deployed to sandbox ? pm-agent-server.py can point at real endpoint
Sprint 7  (planned) ? PM Plane API (/v1/projects, /v1/wbs, /v1/scrum/*) live ? WI-A2?A6, WI-A9, WI-A12 unblocked
Sprint 8  (planned) ? Evidence + ADO Push (/v1/evidence/*, /v1/ado/wi) live ? WI-A6 (evidence_summary), WI-A22 unblocked

About

EVA Brain v2 - Agentic backend (FastAPI)

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors