Specter is an advanced (legal focused) AI agent orchestration system built on the Elysia framework. It features intelligent routing, custom agent creation, and dynamic document management for legal-domain specific AI assistance.
- Get Started (Python from Github)
- Get started (App)
- Using the System
- Architecture
- Advanced Configuration
- Monitoring & Debugging
- Troubleshooting
- Best Practices
- Python 3.12 or higher
- Weaviate instance (local or cloud)
- OpenAI API key (or compatible LLM provider)
To get the latest development version, you can clone the github repo by running
git clone https://github.com/Siddharth-Khattar/specter-backend.gitmove to the working directory via
cd specter-backendCreate a virtual environment with Python (version 3.12+)
python3.12 -m venv .venv
source .venv/bin/activateand then install "Specter-version" of Elysia via pip
pip install -e .Done! You can now use the the python package
Create a .env file in the project root:
# Weaviate Configuration
WCD_URL=your_weaviate_cluster_url
WCD_API_KEY=your_weaviate_api_key
# OpenAI Configuration
OPENAI_API_KEY=your_openai_api_key
# Model Configuration
BASE_MODEL=gpt-5o-mini
COMPLEX_MODEL=gpt-5
# Logging
LOGGING_LEVEL=INFORun the app via
elysia startThen navigate to the settings page, add your required API keys, Weaviate cloud cluster details and specify your models.
Start frontend by opening specter-frontend repository and following instructions.
Documents can be uploaded to create agent-specific knowledge bases.
Form Data:
file: The document file (PDF, TXT, DOCX, etc.)user_id: User identifieragent_name: (Optional) Associate document with specific agentcollection_name: (Optional) Custom collection name
- Documents are automatically chunked for optimal retrieval
- Text is vectorized using OpenAI embeddings
- Metadata is preserved (filename, upload date, agent association)
- Documents are stored in agent-specific Weaviate collections
When you send a query through the chat interface, the system:
- Analyzes the query to determine domain/intent
- Routes to appropriate agent using the DomainRouter
- Executes agent-specific tools with access to relevant knowledge base
- Returns structured response with source citations
Response Stream:
{
"type": "tree_update",
"payload": {
"from_node": "domain_routing",
"to_node": "legal_advisor",
"reasoning": "Query requires legal expertise and document analysis"
}
}
{
"type": "text",
"payload": {
"text": "Based on the service agreement, the key obligations include..."
}
}User Query
↓
DomainRouter (analyzes query intent)
↓
┌─────────────────────────────────┐
│ Specialized Agent Selection │
├─────────────────────────────────┤
│ • Civil-law Agent │
│ • Immigration-law Agent │
│ • Work-law Agent │
│ • General Agent (fallback) │
└─────────────────────────────────┘
↓
Agent-Specific Knowledge Base
↓
Tool Execution (Query, Aggregate, etc.)
↓
Response with Citations
The system uses a branching decision tree that's visible in the UI:
- Root Node: Domain routing evaluation
- Branch Nodes: Agent selection and tool choice
- Leaf Nodes: Tool execution (query, aggregate, text response)
- Result: Comprehensive response with transparent reasoning
The CustomAgentRegistry class manages all custom agents:
from elysia.tools.domain.custom_agent_registry import CustomAgentRegistry
# Initialize registry
registry = CustomAgentRegistry(logger=logger)
# Load agents for a user
await registry.load_custom_agents(
user_id="user123",
client_manager=client_manager
)
# Get available agents
agent_names = registry.get_agent_names()
agent_descriptions = registry.get_agent_descriptions()Agents can be fine-tuned through several parameters:
tree.add_tool(
CustomAgentTool,
branch_id="domain_routing",
agent_config={
"temperature": 0.7,
"max_tokens": 2000,
"use_reasoning": True
}
)Each agent can have multiple associated collections:
# Create collection for agent
await create_agent_collection(
user_id="user123",
agent_name="legal_advisor",
collection_name="contracts_2024"
)
# Associate with agent
await update_agent_collections(
agent_id="agent_uuid",
collections=["contracts_2024", "legal_precedents"]
)The DomainRouter can be configured to adjust sensitivity:
domain_router = DomainRouter(
confidence_threshold=0.75, # Minimum confidence for agent selection
fallback_to_general=True, # Use general agent if confidence low
logger=logger
)View the decision tree structure:
tree.view() # Prints formatted tree structureAgent not being selected:
- Check agent description matches query domain
- Verify DomainRouter confidence threshold
- Review agent system prompt for clarity
Documents not being retrieved:
- Confirm document upload completed successfully
- Check collection names match agent configuration
- Verify Weaviate connection and indexing
Routing loops:
- Review
hidden_environmentstate (cleared on soft_reset) - Check for circular tool dependencies
- Adjust recursion_limit if needed
- Agent Specialization: Create focused agents for specific domains rather than general-purpose agents
- System Prompts: Write clear, detailed system prompts that define agent expertise and limitations
- Document Organization: Group related documents in dedicated collections per agent
- Regular Updates: Keep agent knowledge bases current by periodically updating documents
- Monitor Performance: Track agent selection accuracy and adjust confidence thresholds
