An agentic AI system that traverses realms of biomedical data to illuminate pathways toward drug discovery
Quick Start โข Documentation โข Examples โข Architecture
In Brandon Sanderson's Cosmere, a Perpendicularity is a rare phenomenon where the Physical, Cognitive, and Spiritual Realms intersectโa concentration of Investiture so powerful it allows passage between worlds, revealing truths invisible from any single realm.
This agent embodies that concept in drug discovery:
|
๐ THE PERPENDICULARITY ๐ Where Three Realms Converge |
||
|
GenomicOps-MCP
|
TxGemma-MCP
|
Therapeutic Discovery
|
|
โก Concentrated Investiture (AI Reasoning) โก Bridges domains โข Reveals hidden connections โข Enables discovery |
||
At the Perpendicularity, these realms touch. The agent serves as concentrated Investiture, enabling travel between distant domains of knowledge, revealing connections invisible from any single perspective.
Perpendicularity is an agentic AI system for drug discovery research that bridges genomic analysis, molecular evaluation, and therapeutic insights through intelligent tool orchestration.
Core Capabilities:
- ๐งฌ Genomic Analysis: Cross-species coordinate conversion, gene annotation, UCSC track queries
- ๐ Drug Evaluation: Toxicity assessment, safety profiling, literature search
- ๐ค Multi-Model Support: Gemini, Claude, Ollama (Qwen, Mistral, Llama), HuggingFace models
- ๐ Dual Agent Architectures: LangGraph (production) and ReAct (educational)
- ๐ Web & CLI Interfaces: React frontend + FastAPI backend + command-line tool
- ๐ง MCP Integration: Standards-based connection to genomics and therapeutics tools
Built For:
- Computational biologists analyzing genomic loci
- Drug discovery researchers evaluating compounds
- Translational scientists connecting genomics to therapeutics
- Teams needing reproducible, auditable AI-assisted analysis
# Clone repository
git clone https://github.com/t-neumann/perpendicularity.git
cd perpendicularity
# Install with uv (recommended)
uv sync --extra api
# Or with pip
pip install -e ".[api]"# 1. Set API keys (for cloud models)
export GOOGLE_API_KEY="your-gemini-key"
export ANTHROPIC_API_KEY="your-claude-key"
# 2. Configure MCP servers
nano config/agent_config.yaml
# Update MCP server URLs to your instances# Command-line interface
perpendicularity ask "Which drug is safer: aspirin or ibuprofen?"
# Start API server
perpendicularity api
# Start with custom config
perpendicularity api --config my_config.yaml --workers 4See Getting Started Guide for detailed setup instructions.
perpendicularity ask \
"For human locus chr8:127735434-127742951, find genes, \
evaluate therapeutic relevance, \
and suggest candidate drugs" \
--prompt genomics \
--max-steps 7What it does:
- Finds genes in human genomic region (Physical Realm)
- Evaluates therapeutic relevance (Cognitive Realm)
- Suggests drugs targeting those genes (Spiritual Realm)
perpendicularity ask \
"Compare toxicity: aspirin (CC(=O)OC1=CC=CC=C1C(=O)O) vs \
vorinostat (O=C(CCCCCCC(=O)Nc1ccccc1)NO). Which is safer?" \
--prompt conservative \
--model claudeWhat it does:
- Evaluates toxicity profiles for both compounds
- Searches literature for safety data
- Compares therapeutic windows
- Provides evidence-based recommendation
perpendicularity interactive --model ollama_qwen14bEnters conversational mode with:
- Rich terminal formatting (automatic in TTY)
- Step-by-step reasoning display
- Tool usage transparency
- Markdown-rendered responses
See more examples in the documentation.
| Document | Description |
|---|---|
| Getting Started | Installation, configuration, first queries |
| Architecture | System design, components, data flow |
| CLI Guide | Command-line interface complete reference |
| API Guide | REST API endpoints, streaming, integration |
| Frontend Guide | React app development and customization |
| Document | Description |
|---|---|
| Configuration Reference | Complete config file documentation |
| Agents Guide | LangGraph vs ReAct, when to use each |
| Models Guide | Model comparison, costs, recommendations |
| MCP Servers | Connecting to genomics & therapeutics tools |
| Document | Description |
|---|---|
| Deployment Guide | Docker, production best practices |
| EC2 Setup | AWS EC2 with Ollama deployment |
| Testing | Test suite, CI/CD, coverage reports |
| Troubleshooting | Common issues and solutions |
| Document | Description |
|---|---|
| Contributing | Development setup, code style, PRs |
Run locally or in the cloud - swap models without code changes:
# Cloud models (powerful but costs $)
perpendicularity ask "question" --model gemini # Fast, efficient
perpendicularity ask "question" --model claude # Best reasoning
# Local models (free but needs GPU)
perpendicularity ask "question" --model ollama_qwen14b # Best local
perpendicularity ask "question" --model ollama_deepseek # Reasoning specialist
perpendicularity ask "question" --model hf_qwen32b # Highest quality localSee Models Guide for detailed comparison.
LangGraph (Production):
- Autonomous reasoning until completion
- Sophisticated error handling
- Conversation memory
- Production-grade reliability
ReAct (Educational):
- Step-by-step reasoning (Thought โ Action โ Observation)
- Transparent decision-making
- Educational clarity
- Maximum interpretability
See Agents Guide for choosing the right agent.
Automatic mode detection:
- TTY (interactive): Rich formatting, syntax highlighting, progress spinners
- Pipe/script: Plain text, parseable output
# Rich mode (automatic in terminal)
perpendicularity ask "question"
# Shows: formatted steps, colored output, spinners
# Plain mode (automatic when piped)
perpendicularity ask "question" | tee log.txt
# Shows: plain text, no ANSI codes
# Force plain mode
perpendicularity ask "question" --plainSee CLI Guide for all options.
React + FastAPI application:
- Real-time streaming: See agent reasoning as it happens
- Model selection: Switch models in UI
- Agent selection: Choose LangGraph or ReAct
- Markdown rendering: Formatted responses with syntax highlighting
# Start server
perpendicularity api --workers 4
# Access at http://localhost:8000See API Guide and Frontend Guide.
Perpendicularity uses a modular architecture with clear separation of concerns:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ USER INTERFACES โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโค
โ CLI (Rich) โ API (FastAPI) โ Frontend (React) โ
โ โข Interactive โ โข REST โ โข Real-time UI โ
โ โข Batch โ โข Streaming โ โข Model selection โ
โ โข Plain mode โ โข SSE โ โข Agent selection โ
โโโโโโโโโโฌโโโโโโโโโโดโโโโโโโโโฌโโโโโโโโโโดโโโโโโโโโโโฌโโโโโโโโโโโโ
โ โ โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ AGENT FACTORY โ
โ โข Model selection โ
โ โข Agent instantiation โ
โ โข Config loading โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
โ โ
โโโโโโผโโโโโโ โโโโโโผโโโโโโ
โ LangGraphโ โ ReAct โ
โ Agent โ โ Agent โ
โ โ โ โ
โ โข Memory โ โ โข Steps โ
โ โข Async โ โ โข Clear โ
โโโโโโฌโโโโโโ โโโโโโฌโโโโโโ
โ โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ MODEL ABSTRACTION โ
โ โข Gemini โข Anthropic โ
โ โข OpenAI โข Transformers โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ MCP TOOL MANAGER โ
โ โข GenomicOps-MCP โ
โ โข TxGemma-MCP โ
โ โข Tool discovery โ
โ โข Error handling โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Key Components:
- Agent Layer: LangGraph (production) and ReAct (educational) implementations
- Model Layer: Unified interface for Gemini, Claude, Ollama, HuggingFace
- Tool Layer: MCP-based connection to genomics and therapeutics services
- Interface Layer: CLI (rich/plain), API (streaming), Frontend (React)
See Architecture Document for detailed design.
Test Coverage: 82% (427+ tests across unit, integration, CLI, and API)
# Run all tests
pytest
# Run with coverage
pytest --cov=agent --cov=cli --cov=api --cov-report=term-missing
# Run specific test suites
pytest tests/unit/ # Unit tests (fast)
pytest tests/integration/ # Integration tests (requires MCP servers)
pytest tests/cli/ # CLI tests
pytest tests/api/ # API testsCI/CD: GitHub Actions runs tests on every push:
- Python 3.11 and 3.12
- Linting (ruff)
- Full test suite
- Coverage reporting
See Testing Guide for detailed information.
# Build image
docker buildx build --platform linux/amd64 -t perpendicularity:0.1.0 .
# Run with custom config
docker run -d \
--name perpendicularity \
-p 8000:8000 \
-v $(pwd)/agent_config.yaml:/app/config/agent_config.yaml:ro \
-e GOOGLE_API_KEY=your-key \
perpendicularity:0.1.0Deploy on EC2 with local models for cost-effective operation:
# 1. Install Ollama on EC2
curl -fsSL https://ollama.com/install.sh | sh
# 2. Pull models you want to use
ollama pull qwen2.5:14b-instruct # Recommended: best balance
ollama pull deepseek-r1:8b # Reasoning specialist
ollama pull qwen2.5:32b-instruct # Highest quality (needs 24GB GPU)
# 3. Clone and deploy Perpendicularity
git clone https://github.com/t-neumann/perpendicularity.git
cd perpendicularity
# 4. Build Docker image
docker buildx build --platform linux/amd64 -t perpendicularity:0.1.0 .
# 5. Run with host network (allows access to Ollama at localhost:11434)
docker run -d --name perpendicularity --network host \
-v $(pwd)/agent_config.yaml:/app/config/agent_config.yaml:ro \
perpendicularity:0.1.0 \
perpendicularity api --config /app/config/agent_config.yamlEC2 Instance Recommendations:
- g5.xlarge (24GB GPU): Can run up to 32B models with quantization
- g5.2xlarge (48GB GPU): Can run larger models comfortably
- Ubuntu 22.04 or Amazon Linux 2023 AMI
See EC2 Setup Guide for complete instructions including security groups, cost optimization, and monitoring.
| Use Case | Recommended Model | Why |
|---|---|---|
| Production (Cloud) | gemini or claude |
High quality, reliable, fast |
| Cost-Sensitive | ollama_qwen14b |
Best local model, runs on 24GB GPU |
| Maximum Quality (Local) | ollama_qwen32b |
Best reasoning for 24GB hardware |
| Development/Testing | ollama_qwen14b |
Fast iteration, good quality |
| Reasoning Tasks | ollama_deepseek |
Shows thinking process explicitly |
Cost Comparison:
- Cloud (Gemini): ~$0.10-0.50 per complex query
- Local (Ollama): $0.00 per query (hardware cost only)
See Models Guide for detailed comparison.
All behavior is externally configured via YAML:
# config/agent_config.yaml
# Default model to use
default_model: "ollama_qwen14b"
# Model configuration
models:
# ============================================================
# MODEL CLASS DEFAULTS
# ============================================================
# Define common settings for each model type
defaults:
# Gemini class defaults
gemini:
api_key_env: "GOOGLE_API_KEY"
temperature: 0.4
max_tokens: 8192
top_p: 0.95
# Anthropic (Claude) class defaults
anthropic:
api_key_env: "ANTHROPIC_API_KEY"
temperature: 0.4
max_tokens: 8192
top_p: 0.95
# OpenAI-compatible (Ollama) class defaults
openai:
base_url: "http://localhost:11434/v1" # Ollama default
temperature: 0.4
max_tokens: 4096
top_p: 0.95
# HuggingFace Transformers class defaults
transformers:
device: "auto"
load_in_8bit: true
temperature: 0.4
max_tokens: 4096
# ============================================================
# MODEL INSTANCES
# ============================================================
# Only specify what differs from class defaults
# --- Cloud Models ---
gemini:
type: "gemini"
name: "gemini-2.5-flash"
# Inherits: api_key_env, temperature, max_tokens from defaults.gemini
claude:
type: "anthropic"
name: "claude-sonnet-4-20250514"
# Inherits: api_key_env, temperature, max_tokens from defaults.anthropic
# --- Ollama Models (via OpenAI-compatible API) ---
ollama_qwen14b:
type: "openai"
name: "qwen2.5:14b-instruct"
# Inherits: base_url, temperature from defaults.openai
ollama_qwen32b:
type: "openai"
name: "qwen2.5:32b-instruct"
# Inherits: base_url from defaults.openai
ollama_deepseek:
type: "openai"
name: "deepseek-r1:8b"
# Inherits: base_url from defaults.openai
# --- HuggingFace Models (direct loading) ---
hf_qwen14b:
type: "transformers"
model_name: "Qwen/Qwen2.5-14B-Instruct"
# Inherits: device, load_in_8bit from defaults.transformers
# Agent settings
agent:
type: "langgraph" # "langgraph" or "react"
max_steps: 5 # Maximum reasoning steps
verbose: true # Show step-by-step reasoning
recursion_limit: 25 # LangGraph recursion depth
system_prompt: "default" # From prompts.yaml
# MCP servers (genomics and therapeutics tools)
mcp_servers:
genomic_ops:
url: "http://your-genomic-server:8000/mcp"
transport: "streamable-http"
txgemma:
url: "http://your-txgemma-server:8000/mcp"
transport: "streamable-http"
# Logging
logging:
level: "INFO" # DEBUG, INFO, WARNING, ERRORKey Configuration Concepts:
- Model Class Defaults: Common settings for all models of a type (e.g., all Ollama models share
base_url) - Model Instances: Specific models that inherit defaults and override only what's different
- System Prompts: Separate
prompts.yamlfile for different reasoning strategies - MCP Servers: Connect to your genomics (GenomicOps) and therapeutics (TxGemma) services
See Configuration Reference for all options.
The name comes from Brandon Sanderson's Cosmere, where a Perpendicularity is a rare convergence point between realms. Our agent similarly:
- Bridges Domains: Genomics โ Molecular Data โ Therapeutic Insights
- Concentrated Power: AI reasoning as "Investiture"
- Reveals Hidden Truths: Connections invisible from single perspectives
- Enables Traversal: Between realms of biomedical knowledge
For non-Sanderson fans: Think of it as the intersection point where different dimensions of drug discovery data converge, powered by AI reasoning to reveal emergent insights.
If you use Perpendicularity in your research:
@software{perpendicularity2025,
title={Perpendicularity: Where Realms Converge for Therapeutic Discovery},
author={Neumann, Tobias},
year={2025},
version={0.1.0},
url={https://github.com/t-neumann/perpendicularity}
}- GenomicOps-MCP - Genomic analysis tools and UCSC integration
- TxGemma-MCP - Therapeutic evaluation and toxicity assessment
- Model Context Protocol - Standards-based tool integration
- LangChain & LangGraph - Agent framework foundation
- Brandon Sanderson's Cosmere - Inspiration for the metaphor and naming
MIT License - see LICENSE for details.
Contributions welcome! Please see Contributing Guide for:
- Development setup
- Code style guidelines
- Testing requirements
- Pull request process
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: tobias.neumann.at@gmail.com
๐ Where realms converge, discovery emerges.