---
title: ML Intern
emoji: π€
colorFrom: yellow
colorTo: blue
sdk: docker
app_port: 7860
---
> [!IMPORTANT]
> **ML Intern is no longer maintained.** Both the hosted web application and the `ml-intern` CLI have been retired. Continue with [HuggingChat](https://huggingface.co/chat/).
>
> This repository is retained for historical reference only. No support, bug fixes, or security updates will be provided.
# ML Intern (retired)
## 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 git@github.com: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
ANTHROPIC_API_KEY= # if using anthropic models
OPENAI_API_KEY= # if using openai models
HF_TOKEN=
GITHUB_TOKEN=
```
If no `HF_TOKEN` is set, the CLI will prompt you to paste one on first launch. 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).
### 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 --model anthropic/claude-opus-4-6 "your prompt"
ml-intern --model openai/gpt-5.5 "your prompt"
ml-intern --max-iterations 100 "your prompt"
ml-intern --no-stream "your prompt"
```
## 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
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β User/CLI β
ββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ¬βββββββββββ
β Operations β Events
β (user_input, exec_approval, β
submission_queue interrupt, compact, ...) event_queue
β β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β submission_loop (agent_loop.py) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β 1. Receive Operation from queue β β β
β β 2. Route to handler (run_agent/compact/...) β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β Handlers.run_agent() β ββββ€
β β β β β
β β ββββββββββββββββββββββββββββββββββββββββββ β β β
β β β Agentic Loop (max 300 iterations) β β β β
β β β β β β β
β β β ββββββββββββββββββββββββββββββββββββ β β β β
β β β β Session β β β β β
β β β β ββββββββββββββββββββββββββββββ β β β β β
β β β β β ContextManager β β β β β β
β β β β β β’ Message history β β β β β β
β β β β β (litellm.Message[]) β β β β β β
β β β β β β’ Auto-compaction (170k) β β β β β β
β β β β β β’ Session upload to HF β β β β β β
β β β β ββββββββββββββββββββββββββββββ β β β β β
β β β β β β β β β
β β β β ββββββββββββββββββββββββββββββ β β β β β
β β β β β ToolRouter β β β β β β
β β β β β ββ HF docs & research β β β β β β
β β β β β ββ HF repos, datasets, β β β β β β
β β β β β β jobs, papers β β β β β β
β β β β β ββ GitHub code search β β β β β β
β β β β β ββ Sandbox & local tools β β β β β β
β β β β β ββ Planning β β β β β β
β β β β β ββ MCP server tools β β β β β β
β β β β ββββββββββββββββββββββββββββββ β β β β β
β β β ββββββββββββββββββββββββββββββββββββ β β β β
β β β β β β β
β β β ββββββββββββββββββββββββββββββββββββ β β β β
β β β β Doom Loop Detector β β β β β
β β β β β’ Detects repeated tool patterns β β β β β
β β β β β’ Injects corrective prompts β β β β β
β β β ββββββββββββββββββββββββββββββββββββ β β β β
β β β β β β β
β β β Loop: β β β β
β β β 1. LLM call (litellm.acompletion) β β β β
β β β β β β β β
β β β 2. Parse tool_calls[] β β β β
β β β β β β β β
β β β 3. Approval check β β β β
β β β (jobs, sandbox, destructive ops) β β β β
β β β β β β β β
β β β 4. Execute via ToolRouter β β β β
β β β β β β β β
β β β 5. Add results to ContextManager β β β β
β β β β β β β β
β β β 6. Repeat if tool_calls exist β β β β
β β ββββββββββββββββββββββββββββββββββββββββββ β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ΄βββ
```
### Agentic Loop Flow
```
User Message
β
[Add to ContextManager]
β
βββββββββββββββββββββββββββββββββββββββββββββ
β Iteration Loop (max 300) β
β β
β Get messages + tool specs β
β β β
β litellm.acompletion() β
β β β
β Has tool_calls? ββNoββ> Done β
β β β
β Yes β
β β β
β Add assistant msg (with tool_calls) β
β β β
β Doom loop check β
β β β
β For each tool_call: β
β β’ Needs approval? ββYesββ> Wait for β
β β user confirm β
β No β
β β β
β β’ ToolRouter.execute_tool() β
β β’ Add result to ContextManager β
β β β
β Continue loop ββββββββββββββββββ β
β β β β
β βββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββ
```
## 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
### 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": "anthropic/claude-sonnet-4-5-20250929",
"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`.