Skip to content

Latest commit

 

History

History
155 lines (129 loc) · 6.31 KB

File metadata and controls

155 lines (129 loc) · 6.31 KB

Contributing to AgentML

Thank you for your interest in contributing to AgentML! This guide will help you get started.

Development Setup

  1. Fork and clone the repository
  2. Follow the Setup Guide to install dependencies
  3. Start the backend with --reload for hot reloading:
    cd backend
    python -m uvicorn main:app --reload --port 8002
  4. Start the frontend:
    npm start

Project Structure

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

Code Style

Python (Backend)

  • Use type hints where practical
  • Use logging (not print) 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

JavaScript (Frontend)

  • Use functional components with hooks
  • State management via Zustand store
  • TailwindCSS for styling
  • Keep console.error in catch blocks, avoid console.log for debugging

Tests & Linting

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 tests

Tests 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.

Making Changes

  1. Create a feature branch: git checkout -b feature/your-feature
  2. Make your changes
  3. Run ruff check . and pytest in backend/; add tests for new logic
  4. Test manually (upload a CSV, run the pipeline, check all stages)
  5. Commit with a clear message
  6. Push and open a pull request

Architecture Decisions

Key principles to follow:

  • Tools never raise: The execute_code tool 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

Adding a New Pipeline Stage

  1. Create backend/agent/prompts/your_stage.py exporting a prompt constant (text only)
  2. Add the stage name to STAGES in agent/routing.py
  3. Register the stage in the _STAGE_PROMPTS map in agent/prompts/__init__.py
  4. If it needs a HITL gate, add an entry in HITL_GATES in hitl.py
  5. Update EVAL_DECISION_PROMPT / routing so the new stage is reachable

Adding a New WebSocket Event

  1. Add the emitter method in agent/events.py
  2. Emit from the relevant node in pipeline.py
  3. Handle in _handleWSEvent in src/store/chatStore.js
  4. Document in docs/api.md

Reporting Issues

Please include:

  • Steps to reproduce
  • Expected vs actual behavior
  • Backend logs (terminal output)
  • Browser console errors (if frontend issue)
  • Python and Node.js versions