Thank you for your interest in contributing to AgentML! This guide will help you get started.
- Fork and clone the repository
- Follow the Setup Guide to install dependencies
- Start the backend with
--reloadfor hot reloading:cd backend python -m uvicorn main:app --reload --port 8002 - Start the frontend:
npm start
agentml/
backend/
agent/ # LangGraph pipeline core
prompts/ # System prompt TEXT only (fetched via get_prompt(stage))
__init__.py # lazy stage→prompt registry
base.py # shared BASE_INSTRUCTIONS + QUIRKY_PERSONA
general.py # free-form conversation + pipeline trigger
orchestrator.py # end-of-run evaluation decision prompt
eda.py preprocessing.py feature.py evaluation.py hungry.py
modeling.py # MODELING_A/B specialists (debate flow)
debate.py # debate personas + judge
pipeline.py # LangGraph topology, nodes, checkpointer
driver.py # run_agent_streaming entry point
common.py # shared building blocks (LLM factory, message utils)
routing.py # STAGES + get_next_stage (deterministic order)
schemas_llm.py # structured-output models (EvaluationDecision, DebateVerdict)
debate.py # debate kernel-code assets (scoreboard/viz/preflight)
tools.py # execute_code tool
ledger.py # ExecutionLedger for state tracking
parser.py # Agent output parsing (thinking, decisions, directives, findings)
events.py # EventEmitter for WebSocket streaming
hitl.py # Human-in-the-loop gate system
state.py # AgentState TypedDict
llm_utils.py # LLM retry with exponential backoff
api/routes/ # FastAPI endpoints
upload.py # CSV upload
chat.py # Legacy HTTP chat
ws.py # WebSocket streaming + HITL coordination
settings.py # LLM configuration
sessions.py # Session CRUD + rename
db/ # SQLite database layer
database.py # Sessions, messages, experiments tables
executor/ # Jupyter kernel management
notebook.py # Subprocess-isolated kernel execution
utils/ # Session manager
session_manager.py # ChatSession, locks, TTL cleanup, restore
config.py # Settings persistence
main.py # FastAPI app entry point
src/
api/ # API client (axios + WebSocket)
components/ # React components
chat/ # ChatLayout, ChatInput, MessageBubble
layout/ # AppLayout, Sidebar
shared/ # SettingsModal, PipelineProgress
store/ # Zustand state management
chatStore.js # All app state + WebSocket actions
utils/ # Frontend utilities
apiError.js # Error message normalization
docs/ # Documentation
- Use type hints where practical
- Use
logging(notprint) for all debug/info output - Write docstrings for public functions and classes
- Follow existing patterns in the codebase
- Keep functions focused and small
- Handle errors gracefully — the tool layer should never raise exceptions
- Use functional components with hooks
- State management via Zustand store
- TailwindCSS for styling
- Keep
console.errorin catch blocks, avoidconsole.logfor debugging
The backend has a fast, dependency-light test suite (no LLM or Jupyter kernel
required) plus ruff linting. Both run in CI (.github/workflows/ci.yml) on
every push and PR — please run them locally before opening a PR:
cd backend
pip install -r requirements-dev.txt # pytest + ruff (once)
ruff check . # lint (unused imports, undefined names)
pytest # unit testsTests live in backend/tests/. They cover the deterministic, security-relevant
pieces — code validator, prompt sanitizer, SSRF/session-id validators, stage
routing, the prompt registry, upload sanitization, and execution-context
assembly. New backend logic should come with a test; prefer testing pure
functions over spinning up the graph or kernel.
The frontend build (npm run build) also runs in CI.
- Create a feature branch:
git checkout -b feature/your-feature - Make your changes
- Run
ruff check .andpytestinbackend/; add tests for new logic - Test manually (upload a CSV, run the pipeline, check all stages)
- Commit with a clear message
- Push and open a pull request
Key principles to follow:
- Tools never raise: The
execute_codetool always returns a string, never throws - Ledger tracks state: Any variable created in the kernel should be discoverable via introspection
- Errors are recoverable: The agent should be told what went wrong and what state was lost
- Message history is bounded: Use windowing to prevent token explosion
- Frontend shows everything: Rich results (plots, tables) go to the frontend, truncated text goes to the LLM
- No checkpointer: Session state is managed by
session_manager, not LangGraph's MemorySaver - Process isolation: The kernel runs in a child process so crashes don't take down the server
- Create
backend/agent/prompts/your_stage.pyexporting a prompt constant (text only) - Add the stage name to
STAGESinagent/routing.py - Register the stage in the
_STAGE_PROMPTSmap inagent/prompts/__init__.py - If it needs a HITL gate, add an entry in
HITL_GATESinhitl.py - Update
EVAL_DECISION_PROMPT/ routing so the new stage is reachable
- Add the emitter method in
agent/events.py - Emit from the relevant node in
pipeline.py - Handle in
_handleWSEventinsrc/store/chatStore.js - Document in
docs/api.md
Please include:
- Steps to reproduce
- Expected vs actual behavior
- Backend logs (terminal output)
- Browser console errors (if frontend issue)
- Python and Node.js versions