Deep Agent

February 26, 2026 · View on GitHub

A Perplexity-style deep research platform combining Venice AI (LLM, web search, embeddings, vision) with a Neo4j knowledge graph, served via FastAPI and deployable to the Akash decentralized cloud.


Architecture Overview

graph TB
    subgraph Clients
        ST["Streamlit UI<br/>(streamlit_app.py)"]
        FE["React Frontend<br/>(frontend/)"]
        API_CLIENT["Any HTTP Client"]
    end

    subgraph "FastAPI Server (main.py :8123)"
        HEALTH["/health"]
        SEARCH["/search"]
        RESEARCH["/research"]
        INSIGHT["/insight"]
        INSIGHT_CHAT["/insight/chat"]
        INSIGHT_GRAPH["/insight/{case_id}/graph"]
        COPILOTKIT["/copilotkit<br/>(AG-UI LangGraph)"]
    end

    subgraph "Agent Layer (agent.py)"
        AGENT["LangGraph Agent<br/>ChatOpenAI + MemorySaver"]
        DISPATCH["dispatch_mode_request"]
    end

    subgraph "Tool Layer (tools.py)"
        WS["web_search_venice"]
        DR["deep_research"]
        DI["deep_insight"]
        IC["insight_chat"]
        SBC["search_and_build_corpus"]
        QC["query_case"]
        FER["find_entity_relationships"]
        BCB["build_case_brief"]
        AIV["analyze_image_venice"]
    end

    subgraph "Ingestion (ingestion.py)"
        INGEST["DocumentIngestor"]
        PDF["PDF extraction<br/>(PyMuPDF)"]
        IMG["Image OCR<br/>(Venice Vision)"]
        CHUNK["Text chunking"]
        EMBED["Batch embedding"]
        NER["Entity extraction<br/>(regex-based)"]
    end

    subgraph "Venice AI APIs"
        V_CHAT["Chat Completions<br/>deepseek-v3.2"]
        V_WEB["Web Search<br/>llama-3.3-70b<br/>:enable_web_search=on"]
        V_EMBED["Embeddings<br/>text-embedding-3-large"]
        V_VISION["Vision<br/>venice-v3-vision"]
    end

    subgraph "Neo4j Knowledge Graph"
        N4J["Neo4j Driver"]
        N_CASE["(:Case)"]
        N_DOC["(:Document)"]
        N_CHUNK["(:Chunk)<br/>+ vector index"]
        N_ENTITY["(:Entity)"]
    end

    ST & FE & API_CLIENT -->|HTTP| SEARCH & RESEARCH & INSIGHT & INSIGHT_CHAT & INSIGHT_GRAPH & HEALTH
    FE -->|AG-UI protocol| COPILOTKIT
    COPILOTKIT --> AGENT --> DISPATCH
    DISPATCH --> WS & DR & DI

    SEARCH --> WS
    RESEARCH --> DR
    INSIGHT --> DI
    INSIGHT_CHAT --> IC
    INSIGHT_GRAPH --> N4J

    WS --> V_WEB
    DR --> V_WEB & V_CHAT
    DI --> SBC --> WS
    DI --> QC & FER
    DI --> V_CHAT
    IC --> QC & FER --> V_CHAT
    BCB --> QC & FER --> V_CHAT

    SBC --> INGEST
    INGEST --> PDF & IMG & CHUNK & EMBED & NER
    IMG --> V_VISION
    EMBED --> V_EMBED
    INGEST --> N4J

    QC --> V_EMBED
    QC --> N4J
    FER --> N4J

    N4J --> N_CASE -->|HAS_DOCUMENT| N_DOC -->|HAS_CHUNK| N_CHUNK
    N_CHUNK -->|MENTIONS| N_ENTITY
    N_ENTITY -->|RELATED_TO| N_ENTITY

Venice AI Integration

All AI capabilities are powered by the Venice AI OpenAI-compatible API (https://api.venice.ai/api/v1). No other LLM provider is used.

flowchart LR
    subgraph "Venice API Endpoints Used"
        direction TB
        CHAT["POST /chat/completions"]
        EMB["POST /embeddings"]
    end

    subgraph "Model Routing"
        direction TB
        M1["deepseek-v3.2<br/>— Agent reasoning<br/>— Report synthesis<br/>— JSON extraction"]
        M2["llama-3.3-70b<br/>:enable_web_search=on<br/>&enable_web_citations=true<br/>— Real-time web search"]
        M3["text-embedding-3-large<br/>— Chunk embeddings<br/>— Query embeddings"]
        M4["venice-v3-vision<br/>— Image OCR<br/>— Document scanning"]
    end

    CHAT --> M1 & M2 & M4
    EMB --> M3

Where each Venice model is called

Venice ModelEnv VarUsed InPurpose
deepseek-v3.2VENICE_MODEL_venice_chat(), _venice_chat_json(), agent.py (ChatOpenAI)LLM reasoning, report synthesis, query planning, entity analysis
llama-3.3-70bVENICE_WEBSEARCH_MODEL_venice_web_search()Real-time web search with citations (appends :enable_web_search=on&enable_web_citations=true to model name)
text-embedding-3-largeVENICE_EMBED_MODELingestion.py (_embed_text, _embed_texts)Text chunk embeddings for Neo4j vector index
venice-v3-visionVENICE_VISION_MODELingestion.py (_extract_text_from_image), analyze_image_venice toolImage-to-text OCR via multimodal chat

Agent Backend Flow

Mode Routing

The agent supports three investigation modes, each with a distinct pipeline:

flowchart TD
    USER["User Query"] --> ROUTER{"Mode?"}

    ROUTER -->|search| SEARCH_PIPE["web_search_venice"]
    ROUTER -->|research| RESEARCH_PIPE["deep_research"]
    ROUTER -->|insight| INSIGHT_PIPE["deep_insight"]

    SEARCH_PIPE --> V_WEB["Venice Web Search<br/>llama-3.3-70b"]
    V_WEB --> SEARCH_OUT["Search results<br/>+ citations"]

    RESEARCH_PIPE --> PLAN["Plan search queries<br/>(Venice LLM)"]
    PLAN --> PAR_SEARCH["Parallel web searches<br/>(ThreadPoolExecutor)"]
    PAR_SEARCH --> SYNTH["Synthesize report<br/>(Venice LLM)"]
    SYNTH --> RESEARCH_OUT["Research report<br/>+ timings + citations"]

    INSIGHT_PIPE --> CORPUS_CHECK{"Corpus exists<br/>for case+topic?"}
    CORPUS_CHECK -->|No| BUILD["search_and_build_corpus"]
    CORPUS_CHECK -->|Yes| SKIP["Skip — reuse corpus"]
    BUILD --> INGEST_FLOW["Web search → chunk →<br/>embed → NER → Neo4j"]
    INGEST_FLOW --> QUERY_PHASE
    SKIP --> QUERY_PHASE["query_case + find_entity_relationships<br/>(parallel)"]
    QUERY_PHASE --> INSIGHT_SYNTH["Synthesize insight report<br/>(Venice LLM)"]
    INSIGHT_SYNTH --> INSIGHT_OUT["Insight report + graph data<br/>+ entity summary"]

Deep Research Pipeline (web-only)

sequenceDiagram
    participant Client
    participant FastAPI as FastAPI /research
    participant Planner as Venice LLM (planning)
    participant WebSearch as Venice Web Search
    participant Synth as Venice LLM (synthesis)

    Client->>FastAPI: POST {case_id, topic, depth}
    FastAPI->>Planner: Plan N search queries (depth → N)
    Planner-->>FastAPI: ["query1", "query2", ...]
    par Parallel web searches (ThreadPoolExecutor)
        FastAPI->>WebSearch: Search query 1
        FastAPI->>WebSearch: Search query 2
        FastAPI->>WebSearch: Search query N
    end
    WebSearch-->>FastAPI: Raw web findings
    FastAPI->>Synth: Synthesize findings into report
    Synth-->>FastAPI: Research report
    FastAPI-->>Client: {report, timings_ms, citations}

Deep Insight Pipeline (Graph-RAG)

sequenceDiagram
    participant Client
    participant FastAPI as FastAPI /insight
    participant Neo4j
    participant Venice as Venice APIs
    participant Ingestor as DocumentIngestor

    Client->>FastAPI: POST {case_id, topic, question, depth}
    FastAPI->>Neo4j: check_corpus_exists(case_id, topic)
    alt No existing corpus
        FastAPI->>Venice: Plan & run web searches
        Venice-->>FastAPI: Web search results
        FastAPI->>Ingestor: chunk + embed + extract entities
        Ingestor->>Venice: Batch embed (text-embedding-3-large)
        Ingestor->>Neo4j: Bulk upsert chunks + entities
        FastAPI->>Neo4j: auto_link_related_entities
    end
    par Parallel retrieval
        FastAPI->>Venice: Embed question
        Venice-->>FastAPI: Query vector
        FastAPI->>Neo4j: query_similar_chunks (vector search)
        FastAPI->>Neo4j: get_all_entity_relationships
    end
    Neo4j-->>FastAPI: Evidence chunks + relationships
    FastAPI->>Venice: Synthesize insight report (deepseek-v3.2)
    Venice-->>FastAPI: Insight report
    FastAPI-->>Client: {insight_report, corpus_stats, entity_summary, timings_ms}

Neo4j Knowledge Graph Schema

graph LR
    CASE["(:Case)<br/>case_id, topic, status"] -->|HAS_DOCUMENT| DOC["(:Document)<br/>doc_id, filename, source"]
    DOC -->|HAS_CHUNK| CHUNK["(:Chunk)<br/>chunk_id, text, embedding<br/>(vector indexed)"]
    CHUNK -->|MENTIONS| ENTITY["(:Entity)<br/>entity_id, type, value,<br/>normalized, confidence"]
    ENTITY -->|RELATED_TO| ENTITY

    style CHUNK fill:#4A90D9,color:#fff
    style ENTITY fill:#E67E22,color:#fff

Entity types extracted: name, email, phone, org, money, date, url


Akash Deployment

The app is configured for deployment on the Akash Network decentralized cloud via akash.yaml (SDL v2.0).

flowchart TB
    subgraph "Akash Network (Decentralized Cloud)"
        subgraph "Container: python:3.11-slim"
            APP["Streamlit App<br/>(:8501 → :80 global)"]
            DATA["/app/data<br/>(persistent storage 10Gi)"]
        end
        COMPUTE["2 CPU / 4Gi RAM / 10Gi storage"]
    end

    subgraph "External Services"
        VENICE["Venice AI API<br/>(via VENICE_API_KEY env)"]
        NEO4J["Neo4j Instance<br/>(via NEO4J_URI env)"]
    end

    INTERNET["Internet"] -->|port 80| APP
    APP --> VENICE
    APP --> NEO4J
    APP --> DATA

Akash SDL highlights (akash.yaml)

SettingValue
Base imagepython:3.11-slim
Exposed port850180 (global)
CPU2 units
Memory4 Gi
Storage10 Gi (persistent mount at /app/data)
Pricing1000 uakt
Startup commandpip install uv && uv sync && uv run streamlit run app.py --server.port 8501
Env vars neededVENICE_API_KEY, NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD

Redis & Supabase — Akash Deployment

Redis and Supabase have been implemented as standalone modules ready to be wired into the platform when needed. They are deployed alongside the main application on the Akash decentralized cloud but are not connected to the live app yet — they exist as scaffolded services for upcoming features.

ServiceFileAkash ServiceStatus
Redisredis_store.pyredis (container on Akash)Implemented — not connected
Supabasesupabase_store.pyExternal service (env-configured)Implemented — not connected

Where Redis & Supabase Fit in the Architecture

graph TB


        subgraph "Redis Service"
            REDIS["Redis 7<br/>(:6379)<br/>🔒 not connected yet"]
            REDIS_CACHE["Response Cache<br/>(TTL-based)"]
            REDIS_PUBSUB["Pub/Sub<br/>(real-time events)"]
            REDIS_SESSION["Session Store<br/>(user sessions)"]
        end
    end

    subgraph "External Services"
        VENICE["Venice AI API"]
        NEO4J["Neo4j Knowledge Graph"]
        SUPABASE["Supabase<br/>(Postgres + Auth + Storage)<br/>🔒 not connected yet"]
    end

    subgraph "Supabase Planned Usage"
        SB_AUTH["Auth & User Management"]
        SB_DB["Postgres — case metadata,<br/>user history, audit logs"]
        SB_STORAGE["Object Storage —<br/>uploaded PDFs, images"]
        SB_REALTIME["Realtime subscriptions"]
    end

    FASTAPI --> VENICE
    FASTAPI --> NEO4J

    FASTAPI -.->|"future: cache LLM responses<br/>& search results"| REDIS
    REDIS --> REDIS_CACHE & REDIS_PUBSUB & REDIS_SESSION
    REDIS_PUBSUB -.->|"future: push updates<br/>to Streamlit"| STREAMLIT_FUTURE

    FASTAPI -.->|"future: auth, metadata,<br/>file storage"| SUPABASE
    SUPABASE --> SB_AUTH & SB_DB & SB_STORAGE & SB_REALTIME
    SB_REALTIME -.->|"future: live case<br/>notifications"| STREAMLIT_FUTURE

    style REDIS fill:#D32F2F,color:#fff
    style SUPABASE fill:#3ECF8E,color:#fff
    style REDIS_CACHE fill:#EF9A9A,color:#000
    style REDIS_PUBSUB fill:#EF9A9A,color:#000
    style REDIS_SESSION fill:#EF9A9A,color:#000
    style SB_AUTH fill:#A5D6A7,color:#000
    style SB_DB fill:#A5D6A7,color:#000
    style SB_STORAGE fill:#A5D6A7,color:#000
    style SB_REALTIME fill:#A5D6A7,color:#000

Akash Deployment — Updated SDL (with Redis & Supabase)

The akash.yaml is configured to deploy both the main application and Redis as co-located services on Akash:

ServiceImagePortResourcesPurpose
redaction-apppython:3.11-slim8501 → 802 CPU, 4Gi RAM, 10Gi diskMain app (FastAPI + Streamlit)
redisredis:7-alpine6379 (internal)0.5 CPU, 512Mi RAMResponse cache, pub/sub, sessions
SupabaseExternal hostedN/AManagedAuth, Postgres, Object Storage

Environment variables (add to .env when connecting):

VariablePurpose
REDIS_URLRedis connection string (default: redis://localhost:6379/0)
SUPABASE_URLSupabase project URL
SUPABASE_ANON_KEYSupabase anonymous/public key
SUPABASE_SERVICE_KEYSupabase service-role key (server-side only)

Project Structure

deep-agent/
├── agent/
│   ├── main.py              # FastAPI server + all REST endpoints + AG-UI
│   ├── agent.py             # LangGraph agent (ChatOpenAI + dispatch tool)
│   ├── tools.py             # All research tools (search, research, insight, etc.)
│   ├── ingestion.py         # PDF/image extraction, chunking, embedding, NER
│   ├── neo4j_store.py       # Neo4j driver, schema, CRUD, vector search
│   └── pyproject.toml       # Python dependencies
├── streamlit_app.py          # Streamlit console (3-tab UI)
├── streamlit_app_future.py   # Future Streamlit dashboard (placeholder, not connected)
├── redis_store_future.py     # Redis integration scaffold (placeholder, not connected)
├── supabase_store_future.py  # Supabase integration scaffold (placeholder, not connected)
├── spec.md                   # Implementation spec
└── README.md                 # This file

Environment

Set in agent/.env:

VariableRequiredDefaultPurpose
VENICE_API_KEYYesVenice AI authentication
VENICE_BASE_URLNohttps://api.venice.ai/api/v1API base URL
VENICE_MODELNodeepseek-v3.2LLM for reasoning/synthesis
VENICE_WEBSEARCH_MODELNollama-3.3-70bWeb search model
VENICE_EMBED_MODELNotext-embedding-3-largeEmbedding model
VENICE_VISION_MODELNovenice-v3-visionVision/OCR model
NEO4J_URIYesNeo4j connection URI
NEO4J_USERNAMEYesNeo4j username
NEO4J_PASSWORDYesNeo4j password
NEO4J_DATABASENoneo4jDatabase name

Run

cd agent
uv venv && source .venv/bin/activate
uv pip install -e .
uv run python main.py

Server default: http://localhost:8123

Frontend (new shell):

cd ../frontend
npm install
npm run dev

Frontend default: http://127.0.0.1:5173

API Endpoints

MethodPathDescription
GET/healthHealth check
POST/searchQuick web search via Venice
POST/researchDeep research pipeline (web-only, depth-scaled)
POST/insightDeep insight pipeline (Neo4j Graph-RAG)
POST/insight/chatFast follow-up against existing corpus
GET/insight/{case_id}/graphGraph data for visualization
POST/copilotkit/agent/{agent_id}/runAG-UI streaming run endpoint (CopilotKit useAgent)
POST/copilotkit/agent/{agent_id}/connectAG-UI connect endpoint (SSE stream)