# ML Intern Interactive Mode vs Headless Mode: Complete Execution Guide

> Explore ML Intern interactive vs headless mode execution. Understand command-line interfaces animated output manual approvals auto approvals and automated workflows.

- Repository: [Hugging Face/ml-intern](https://github.com/huggingface/ml-intern)
- Tags: how-to-guide
- Published: 2026-04-24

---

**ML Intern's interactive mode provides a rich CLI with animated output and manual tool approvals, while headless mode runs single prompts programmatically with auto-approvals and instant, static output designed for automation.**

ML Intern, an open-source agent framework in the [huggingface/ml-intern](https://github.com/huggingface/ml-intern) repository, supports two distinct execution pathways through its unified entry point in [`agent/main.py`](https://github.com/huggingface/ml-intern/blob/main/agent/main.py). Understanding the difference between **interactive mode** and **headless mode execution** is essential for choosing the right approach for human-in-the-loop experimentation versus automated pipelines.

## Entry Point Architecture: main() vs headless_main()

In [`agent/main.py`](https://github.com/huggingface/ml-intern/blob/main/agent/main.py), the repository defines two primary async entry functions that determine execution behavior. The **interactive mode** invokes `async def main()` ([lines 809-828](https://github.com/huggingface/ml-intern/blob/main/agent/main.py#L809-L828)), which initializes a persistent REPL loop using **PromptSession** for line-by-line input. This function displays a startup banner, accepts `/commands` (such as `/help` or `/yolo`), and maintains state across multiple turns.

Conversely, **headless mode** triggers `async def headless_main(prompt, ...)` ([lines 1029-1060](https://github.com/huggingface/ml-intern/blob/main/agent/main.py#L1029-L1060)), accepting a prompt string as an argument and executing a single iteration before terminating. This function activates when passing a quoted string to the module: `python -m agent.main "your prompt"`.

## Display and Terminal Rendering Differences

The visual output differs significantly between modes. Interactive mode employs a rich **typewriter animation** implemented in [`agent/utils/terminal_display.py`](https://github.com/huggingface/ml-intern/blob/main/agent/utils/terminal_display.py) ([lines 372-380](https://github.com/huggingface/ml-intern/blob/main/agent/utils/terminal_display.py#L372-L380)), printing markdown character-by-character with a shimmering "Thinking..." indicator that requires TTY cursor control.

Headless mode bypasses animation entirely, setting `instant=True` to dump fully rendered markdown immediately ([lines 372-376](https://github.com/huggingface/ml-intern/blob/main/agent/utils/terminal_display.py#L372-L376)). This append-only output avoids cursor manipulation, making it suitable for log capture, pipe redirection, and non-terminal environments like CI pipelines or Jupyter notebooks.

## Tool Call Approval and Automation Behavior

User approval workflows represent a critical functional divergence. In interactive mode, the REPL pauses when tools require confirmation, prompting the user unless the `/yolo` command has enabled auto-approval.

Headless mode automatically enables `config.yolo_mode = True` (defined in [`agent/config.py`](https://github.com/huggingface/ml-intern/blob/main/agent/config.py), [lines 29-30](https://github.com/huggingface/ml-intern/blob/main/agent/config.py#L29-L30)), bypassing all confirmation prompts. According to the source code in [`agent/main.py`](https://github.com/huggingface/ml-intern/blob/main/agent/main.py) ([lines 1049-1055](https://github.com/huggingface/ml-intern/blob/main/agent/main.py#L1049-L1055)), the system automatically answers "approval_required" events, allowing tool chains to execute uninterrupted—essential for batch processing and API integrations.

## Concurrency and Sub-Agent Handling

Sub-agent execution demonstrates architectural differences in display handling. Interactive mode uses live cursor-movement tricks to render updating "research" overlays from sub-agents in real-time.

In headless mode, research outputs are buffered and emitted as static blocks upon completion ([lines 1039-1065](https://github.com/huggingface/ml-intern/blob/main/agent/main.py#L1039-L1065)), eliminating the need for terminal cursor control that would break in headless environments.

## Running ML Intern: Practical Examples

### Interactive Session

```bash
python -m agent.main

```

This launches the REPL with banner display, slash-command support, and animated response rendering. Use `Ctrl-C` twice to exit gracefully.

### Headless CLI Execution

```bash
python -m agent.main "find me bird datasets"

```

Loads the HF token, enables auto-approval via `yolo_mode`, streams instant output, and exits automatically upon completion.

### Programmatic Headless API

```python
import asyncio
from agent.main import headless_main

async def run():
    await headless_main(
        prompt="summarize the latest Hugging Face blog post",
        model="gpt-4o-mini",
        max_iterations=5,
        stream=False  # Set True to receive incremental chunks

    )

asyncio.run(run())

```

Both modes share the core submission logic in [`agent/core/agent_loop.py`](https://github.com/huggingface/ml-intern/blob/main/agent/core/agent_loop.py) ([lines 54-62](https://github.com/huggingface/ml-intern/blob/main/agent/core/agent_loop.py#L54-L62)), ensuring consistent agent behavior regardless of interface.

## Summary

- **Entry Functions**: Interactive uses `main()` for REPL loops; headless uses `headless_main()` for single execution
- **Visual Output**: Interactive shows animated typewriter effects; headless uses instant static rendering with `instant=True`
- **Tool Approvals**: Interactive prompts for confirmation; headless auto-approves all tools via `config.yolo_mode = True`
- **Sub-Agent Display**: Interactive updates live with cursor tricks; headless buffers and prints static blocks
- **Use Cases**: Interactive suits experimentation and debugging; headless serves automation, CI/CD, and API integration
- **Shutdown**: Interactive handles `Ctrl-C` gracefully with cancellation; headless exits automatically on completion

## Frequently Asked Questions

### Can I switch from interactive to headless mode without restarting ML Intern?

No, the execution mode is determined at startup by whether you invoke `python -m agent.main` without arguments (interactive) or with a prompt string (headless). The `headless_main()` and `main()` functions represent distinct entry points in [`agent/main.py`](https://github.com/huggingface/ml-intern/blob/main/agent/main.py) with different initialization logic, so you must restart the process to switch modes.

### Does headless mode support streaming output?

Yes, when using the programmatic API, set `stream=True` in the `headless_main()` call to receive incremental chunks. However, unlike interactive mode's character-by-character typewriter effect, headless streaming outputs raw markdown without cursor animation, making it safe for pipe redirection and log files.

### Why do tool calls auto-approve in headless mode but not interactive mode?

Headless execution sets `config.yolo_mode = True` automatically according to [`agent/main.py`](https://github.com/huggingface/ml-intern/blob/main/agent/main.py) (lines 1049-1055) because there is no TTY attached for user input. This prevents the agent from hanging indefinitely waiting for approval signals that cannot arrive in automated environments like Kubernetes pods or GitHub Actions runners.

### Can I use slash commands like /yolo in headless mode?

No, slash commands such as `/yolo`, `/help`, and `/reset` are features of the interactive PromptSession REPL implemented in `main()`. Headless mode accepts configuration only through function arguments and CLI flags, not through command intermediates, as it lacks the persistent input loop required to process such commands.