ml-intern: an open-source ML engineer that reads papers, trains models, and ships ML models
ml-intern: an open-source ML engineer that reads papers, trains models, and ships ML models
## Historical documentation (unsupported) The documentation below is preserved for historical reference. The project is no longer supported or maintained. ML Intern was an agent that autonomously researched, wrote, and shipped ML-related code using the Hugging Face ecosystem, with deep access to documentation, papers, datasets, and cloud compute. ## Quick Start ### Installation ```bash git clone [email protected]:huggingface/ml-intern.git cd ml-intern uv sync uv tool install -e . ``` #### That's it. Now `ml-intern` works from any directory: ```bash ml-intern ``` Create a `.env` file in the project root (or export these in your shell): ```bash HF_TOKEN= # HF Router inference + Hub actions GITHUB_TOKEN= ``` All API-based model calls go through Hugging Face [Inference Providers](https://huggingface.co/docs/inference-providers/en/index), so your `HF_TOKEN` must be allowed to make Inference Provider calls. If no `HF_TOKEN` is set, the CLI will prompt you to paste one on first launch unless you start on a local model. To get a `GITHUB_TOKEN` follow the tutorial [here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token). See the [local models section below](#local-models) for instructions on using agents that run on your hardware. ### Usage #### Interactive mode (start a chat session): ```bash ml-intern ``` #### Headless mode (single prompt, auto-approve): ```bash ml-intern "fine-tune llama on my dataset" ``` **Options:** ```bash ml-intern --sandbox-tools "your prompt" # use HF Space sandbox tools ml-intern --max-iterations 100 "your prompt" ml-intern --no-stream "your prompt" # Change model ml-intern --model moonshotai/Kimi-K2.7-Code:novita "your prompt" ml-intern --model openai/gpt-5.5:fal-ai "your prompt" ``` Run `ml-intern` then `/model` to see the full list of suggested model ids (Claude, GPT, HF Router models like MiniMax, Kimi, GLM, DeepSeek, and local model prefixes). Hosted inference is billed to the active Hugging Face user. See below on how to run `ml-intern` with local models. #### Local models Local model support uses OpenAI-compatible HTTP endpoints through LiteLLM. The agent does not load model weights directly from disk; start your inference server first, then select it with a provider-specific model prefix: ```bash ml-intern --model ollama/llama3.1:8b "your prompt" ml-intern --model vllm/meta-llama/Llama-3.1-8B-Instruct "your prompt" ``` Inside interactive mode, switch with `/model`: ```text /model ollama/llama3.1:8b /model lm_studio/google/gemma-3-4b /model llamacpp/llama-3.1-8b-instruct ``` Supported local prefixes are `ollama/`, `vllm/`, `lm_studio/`, and `llamacpp/`. ```bash LOCAL_LLM_BASE_URL=http://localhost:8000 LOCAL_LLM_API_KEY= ``` Set `LOCAL_LLM_BASE_URL` and optional `LOCAL_LLM_API_KEY` to use one shared local endpoint, or override a specific provider with its matching `*_BASE_URL` / `*_API_KEY` variable, such as `OLLAMA_BASE_URL` or `VLLM_API_KEY`. Provider-specific variables take precedence over the shared local variables. Base URLs may include or omit `/v1`. **CLI tool runtime:** By default, the CLI runs `bash`, `read`, `write`, and `edit` on your local filesystem. To use HF Space sandbox tools instead, including `sandbox_create`, opt in with `--sandbox-tools`: ```bash ml-intern --sandbox-tools "test this training script in a GPU sandbox" ml-intern --model llamacpp/ggml-org/gemma-3-1b-it-GGUF --sandbox-tools ``` Sandbox tool runtime requires `HF_TOKEN`, even when the selected model is local, because it creates private HF Spaces. You can also make sandbox tools your CLI default in `~/.config/ml-intern/cli_agent_config.json`: ```json { "tool_runtime": "sandbox" } ``` Use the default local runtime when you want tools to inspect or edit files in your checkout. Use sandbox runtime when you want the agent to create or replace an HF Space sandbox, test code remotely, or request GPU sandbox hardware before launching larger HF Jobs. ## Sharing Traces Every session is auto-uploaded to your **own private Hugging Face dataset** in [Claude Code JSONL format](https://huggingface.co/changelog/agent-trace-viewer), which the HF Agent Trace Viewer auto-detects so you can browse turns, tool calls, and model responses directly on the Hub. By default the dataset is named `{your-hf-username}/ml-intern-sessions` and is **created private**. You can flip it to public from inside the CLI: ```bash /share-traces # show current visibility + dataset URL /share-traces public # publish (anyone can view) /share-traces private # lock it back down ``` You can also flip visibility from the dataset page on huggingface.co — the agent honours whatever you set there for subsequent uploads. To opt out entirely, set in your CLI config (e.g. `configs/cli_agent_config.json` or `~/.config/ml-intern/cli_agent_config.json`): ```json { "share_traces": false } ``` To override the destination repo, set: ```json { "personal_trace_repo_template": "{hf_user}/my-custom-traces" } ``` The shared `smolagents/ml-intern-sessions` dataset is unrelated and only receives anonymized telemetry rows used by the backend KPI scheduler. ## Supported Gateways ML Intern currently supports one-way notification gateways from CLI sessions. These gateways send out-of-band status updates; they do not accept inbound chat messages. ### Slack Slack notifications use the Slack Web API to post messages when the agent needs approval, hits an error, or completes a turn. Create a Slack app with a bot token that has `chat:write`, invite the bot to the target channel, then set: ```bash SLACK_BOT_TOKEN=xoxb-... SLACK_CHANNEL_ID=C... ``` The CLI automatically creates a `slack.default` destination when both variables are present. Optional environment variables for the env-only default: ```bash ML_INTERN_SLACK_NOTIFICATIONS=false ML_INTERN_SLACK_DESTINATION=slack.ops ML_INTERN_SLACK_AUTO_EVENTS=approval_required,error,turn_complete ML_INTERN_SLACK_ALLOW_AGENT_TOOL=true ML_INTERN_SLACK_ALLOW_AUTO_EVENTS=true ``` For a persistent user-level config, put overrides in `~/.config/ml-intern/cli_agent_config.json` or point `ML_INTERN_CLI_CONFIG` at a JSON file: ```json { "messaging": { "enabled": true, "auto_event_types": ["approval_required", "error", "turn_complete"], "destinations": { "slack.ops": { "provider": "slack", "token": "${SLACK_BOT_TOKEN}", "channel": "${SLACK_CHANNEL_ID}", "allow_agent_tool": true, "allow_auto_events": true } } } } ``` ## Architecture ### Component Overview ``` … ``` ### Agentic Loop Flow ``` … ``` ## Events The agent emits the following events via `event_queue`: - `processing` - Starting to process user input - `ready` - Agent is ready for input - `assistant_chunk` - Streaming token chunk - `assistant_message` - Complete LLM response text - `assistant_stream_end` - Token stream finished - `tool_call` - Tool being called with arguments - `tool_output` - Tool execution result - `tool_log` - Informational tool log message - `tool_state_change` - Tool execution state transition - `approval_required` - Requesting user approval for sensitive operations - `turn_complete` - Agent finished processing - `error` - Error occurred during processing - `interrupted` - Agent was interrupted - `compacted` - Context was compacted - `undo_complete` - Undo operation completed - `shutdown` - Agent shutting down ## Development ### Pre-commit Checks Run Ruff before every commit: ```bash uv run ruff check . uv run ruff format --check . ``` If the format check fails, run `uv run ruff format .` and re-run the checks before committing. ### Adding Built-in Tools Edit `agent/core/tools.py`: ```python def create_builtin_tools() -> list[ToolSpec]: return [ ToolSpec( name="your_tool", description="What your tool does", parameters={ "type": "object", "properties": { "param": {"type": "string", "description": "Parameter description"} }, "required": ["param"] }, handler=your_async_handler ), # ... existing tools ] ``` ### Adding MCP Servers Edit `configs/cli_agent_config.json` for CLI defaults, or `configs/frontend_agent_config.json` for web-session defaults: ```json { "model_name": "zai-org/GLM-5.2:novita", "mcpServers": { "your-server-name": { "transport": "http", "url": "https://example.com/mcp", "headers": { "Authorization": "Bearer ${YOUR_TOKEN}" } } } } ``` Note: Environment variables like `${YOUR_TOKEN}` are auto-substituted from `.env`. ## Cite ml-intern If you use `ml-intern` in your work, please cite it by using the following BibTeX entry or similar. ```bibtex @Misc{ml-intern, title = {ml-intern: an agent that autonomously researches, writes, and ships good quality ML related code using the Hugging Face ecosystem}, author = {Aksel Joonas Reedi, Henri Bonamy, Yoan Di Cosmo, Leandro von Werra, Lewis Tunstall}, howpublished = {\\url{https://github.com/huggingface/ml-intern}}, year = {2026} } ```
No open issues yet, or sync has not completed.