5.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
# Install dependencies
uv sync
# Install with PDF/HTML export support
uv sync --extra export
# Run the server (opens on http://localhost:8080)
uv run deepresearch
# Start Excalidraw canvas (separate terminal)
docker compose up -d excalidraw-canvas
# Run without Excalidraw
EXCALIDRAW_ENABLED=0 uv run deepresearch
No tests, linters, or formatters are configured in this project.
Environment
Copy .env.example to .env and configure:
OPENAI_API_KEYorANTHROPIC_API_KEY— LLM provider- At least one search API key:
TAVILY_API_KEY,BRAVE_API_KEY, orJINA_API_KEY - Default model is
openai-responses:o4-mini(override viaMODEL_NAME) - When
LLM_BASE_URLis set, uses a local OpenAI-compatible endpoint instead
Architecture
Stack: Python 3.12+ / FastAPI / WebSocket / pydantic-ai + pydantic-deep
Source Layout
src/deepresearch/
app.py # FastAPI server, WebSocket /ws/chat, REST endpoints
agent.py # Agent factory — assembles the research agent with all toolsets
config.py # MCP server creation, model config, path constants
prompts.py # System prompt for the research agent (~300 lines of instructions)
middleware.py # Three capabilities: AuditCapability, PermissionCapability, RateLimitRetryCapability
todo_toolset.py # ForgiveWriteTodosCapability — handles malformed tool calls from local LLMs
types.py # Pydantic models: Source, Finding, ReportSection, ResearchReport
static/
index.html # Single-page frontend
app.js # WebSocket client, tool rendering, file preview, Excalidraw iframe
styles.css # Dark theme UI
skills/
research-methodology/SKILL.md # Loaded agent skill: source evaluation, search strategy
report-writing/SKILL.md # Loaded agent skill: report structure, citation format
diagram-design/SKILL.md # Loaded agent skill: Excalidraw diagram best practices
workspace/
DEEP.md # Context file injected into every session (file organization conventions)
MEMORY.md # Persistent agent memory (written via `remember()` tool)
workspaces/ # Per-session data: history.json, meta.json, events.jsonl, canvas.json
Runtime Flow
-
Lifespan startup (
app.py:lifespan): Creates MCP servers (Tavily, Brave, Jina, Excalidraw, Playwright, Firecrawl per API keys in env) and the research agent. Retry loop drops failing MCP servers and restarts. -
WebSocket session (
/ws/chat): Each browser tab connects with a session UUID. A per-user Docker sandbox container is created (python-datascience runtime). Message history persists toworkspaces/<uuid>/history.json. -
Agent execution (
run_agent_with_streaming): Usesagent.iter()for streaming — processes nodes (ModelRequest → stream text deltas, CallTools → stream tool calls/results) and sends WebSocket JSON events to the frontend. -
Approval flow: Tools like
executetriggerDeferredToolRequests— the frontend shows an approval dialog, and the agent resumes withDeferredToolResults. -
Checkpointing: Auto-saves after every turn to
InMemoryCheckpointStore. Supportsrewindandforkvia REST endpoints.
Agent Architecture
The agent (create_research_agent in agent.py) uses pydantic-deep's create_deep_agent with:
- Toolsets: MCP servers (search/browser/diagrams) + filesystem + execute + subagents + teams + TODO + skills + checkpoints + agent-factory + remember
- Subagents:
general-purpose(research executor),planner(plan mode),code-reviewer, plus dynamic agents via factory - Hooks:
audit_logger(POST_TOOL_USE, background) +safety_gate(PRE_TOOL_USE onexecute, blocks rm -rf /, mkfs, dd, etc.) - Middleware stack:
ForgiveWriteTodosCapability→AuditCapability→PermissionCapability→ optionallyRateLimitRetryCapability - Context management: Sliding window (50 msg trigger, keep 30), token eviction (20k limit), context files from
/workspace/DEEP.mdand/workspace/MEMORY.md
MCP Servers (config.py)
All optional, enabled by API key presence:
- Tavily — AI search (
npx tavily-mcp) - Brave Search — web search (
npx @anthropic-ai/brave-search-mcp) - Jina — URL→markdown reader (HTTP MCP at
https://mcp.jina.ai/v1) - Excalidraw — live diagrams (Podman container, requires
podmanbinary) - Playwright — browser automation (requires
PLAYWRIGHT_MCP=1) - Firecrawl — web scraping/crawling (
npx firecrawl-mcp)
Research Workflow (prompts.py)
The system prompt encodes a detailed 7-step research workflow:
- Plan — dispatch planner subagent for complex topics
- Todo — create progress tracking with
write_todos - Parallel subagents — dispatch all research tasks async
- Wait —
wait_tasksfor results - Handle failures — never stop, use own knowledge as fallback
- Write iteratively — chapter by chapter via
edit_file - Present — summarize and offer deeper analysis
REST Endpoints
| Endpoint | Purpose |
|---|---|
GET / |
Serves static/index.html |
GET /health |
Health check with agent/session status |
GET /config |
Full feature configuration |
POST /upload |
File upload to sandbox |
GET /files?session_id= |
List files in sandbox |
GET /files/content/... |
Read file content |
GET /files/binary/... |
Read binary files (images) |
GET /todos?session_id= |
Get current TODOs |
GET /checkpoints?session_id= |
List checkpoints |
POST /checkpoints/:id/rewind |
Rewind to checkpoint |
POST /checkpoints/:id/fork |
Fork new session from checkpoint |
GET /history?session_id= |
Get conversation history |
GET /sessions |
List all sessions |
DELETE /sessions/:id |
Delete session |
GET /export/:fmt |
Export report (md/html/pdf) |
GET /preview/:session_id/... |
Serve raw files from container |