Skip to content

Conversation

@hanouticelina
Copy link
Contributor

@hanouticelina hanouticelina commented May 21, 2025

This is an early version of Tiny Agents (https://huggingface.co/blog/tiny-agents) in Python, inspired by @julien-c's work in JS: https://github.com/huggingface/huggingface.js/tree/main/packages/tiny-agents.

What's in the PR?

  • tiny-agents run command (see src/huggingface_hub/inference/_mcp/cli.py) that mirros the JS CLI and supports: a folder, a single agent.json, or a builtin agent name.
  • Agent wrapper: src/huggingface_hub/inference/_mcp/tiny_agent.py – very small orchestrator that keeps a history, enforces a max-turn limit, and plugs MCP tools into the LLM.

What's missing?

  • - Only stdio MCP servers are handled right now, we need to add support for SSE and HTTP MCP servers. implemented in [MCP] add support for SSE + HTTP #3099
  • - Some possible refactoring: where and how do we want to implement the CLI? ✅

@HuggingFaceDocBuilderDev

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

setup.py Outdated

extras["mcp"] = [
"mcp>=1.8.0",
"colorama",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(probably not worth the extra dependency if all you need are a few colors characters sequences)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be bullish to switch to Typer instead of argparse to be honest...

It has a much greater UX, easier to maintain, auto-completion out of the box, etc. It adds a dependency but only an optional one (on huggingface_hub[mcp])

Copy link
Member

@julien-c julien-c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks super cool already! 🔥

@hanouticelina hanouticelina changed the title Tiny Agents in Python [MCP] Tiny Agents in Python May 21, 2025
@hanouticelina hanouticelina marked this pull request as ready for review May 21, 2025 13:55
Copy link
Contributor

@Wauplin Wauplin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! I'm pre-approving with some nits. Once we have SSE/HTTP servers implemented we should be on-par with the JS CLI to make some comms about it :)

(btw, is this a problem that we'll have two tiny-agents CLIs conflicting? Hopefully not but 🤷)

Comment on lines 58 to 59
else:
raise KeyboardInterrupt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't know how to solve that but when I launch the CLI + wait for the tools to be loaded, I need to type 4 times on CTRL+C to exit and it exits with a ton of messages. Would be good to improve DX, either here or in a follow-up PR:

> tiny-agents run julien-c/local-coder
Fetching 2 files: 100%|███████████████████████████████████████████████████████| 2/2 [00:00<00:00, 64527.75it/s]
Agent loaded with 25 tools:
 • browser_close
 • browser_resize
 • browser_console_messages
 • browser_handle_dialog
 • browser_file_upload
 • browser_install
 • browser_press_key
 • browser_navigate
 • browser_navigate_back
 • browser_navigate_forward
 • browser_network_requests
 • browser_pdf_save
 • browser_take_screenshot
 • browser_snapshot
 • browser_click
 • browser_drag
 • browser_hover
 • browser_type
 • browser_select_option
 • browser_tab_list
 • browser_tab_new
 • browser_tab_select
 • browser_tab_close
 • browser_generate_playwright_test
 • browser_wait_for
» ^CInterrupted – press Ctrl+C again to quit
^Cunhandled exception during asyncio.run() shutdown
task: <Task finished name='Task-1' coro=<run_agent() done, defined at /home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/cli.py:33> exception=ExceptionGroup('unhandled errors in a TaskGroup', [ProcessLookupError()])>
Traceback (most recent call last):
  File "/home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/cli.py", line 63, in run_agent
    async with Agent(
  File "/home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/mcp_client.py", line 65, in __aexit__
    await self.cleanup()
  File "/home/wauplin/projects/huggingface_hub/src/huggingface_hub/inference/_mcp/mcp_client.py", line 241, in cleanup
    await self.exit_stack.aclose()
  File "/usr/lib/python3.10/contextlib.py", line 656, in aclose
    await self.__aexit__(None, None, None)
  File "/usr/lib/python3.10/contextlib.py", line 714, in __aexit__
    raise exc_details[1]
  File "/usr/lib/python3.10/contextlib.py", line 697, in __aexit__
    cb_suppress = await cb(*exc_details)
  File "/usr/lib/python3.10/contextlib.py", line 206, in __aexit__
    await anext(self.gen)
  File "/home/wauplin/projects/huggingface_hub/.venv310/lib/python3.10/site-packages/mcp/client/stdio/__init__.py", line 170, in stdio_client
    async with (
  File "/home/wauplin/projects/huggingface_hub/.venv310/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 772, in __aexit__
    raise BaseExceptionGroup(
exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
^C^CException ignored in: <module 'threading' from '/usr/lib/python3.10/threading.py'>
Traceback (most recent call last):
  File "/usr/lib/python3.10/threading.py", line 1537, in _shutdown
    atexit_call()
  File "/usr/lib/python3.10/concurrent/futures/thread.py", line 31, in _python_exit
    t.join()
  File "/usr/lib/python3.10/threading.py", line 1096, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.10/threading.py", line 1116, in _wait_for_tstate_lock
    if lock.acquire(block, timeout):
KeyboardInterrupt:

(I do get similar output no matter when I exit but reporting this one is the most reproducible example)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed in private, it's a bit complicated to "exit" properly an asyncio script in this context 😕 I pushed a better way to exit in f09b70a using os._exit() but still, I believe it's not the best solution..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into it. Let's do that and leave it for a later PR then...

@julien-c
Copy link
Member

(btw, is this a problem that we'll have two tiny-agents CLIs conflicting? Hopefully not but 🤷)

I thought about it but i don't think so, given i doubt many people will install both globally.

@hanouticelina
Copy link
Contributor Author

let's merge! 🔥

Screen.Recording.2025-05-21.at.19.36.22.mov

@hanouticelina
Copy link
Contributor Author

(failing tests unrelated)

Copy link
Member

@julien-c julien-c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❗ 🔥 🚒

@hanouticelina hanouticelina merged commit aee73c4 into main May 21, 2025
25 checks passed
@hanouticelina hanouticelina deleted the tiny-agent branch May 21, 2025 17:49
Wauplin added a commit to huggingface/huggingface.js that referenced this pull request May 27, 2025
As discussed offline, this PR moves the curated collection of
tiny-agents to the Hub. Agents must now be contributed to
https://huggingface.co/datasets/huggingface/tiny-agents. This will be
helpful to maintain the collection independently from the
`@huggingface/tiny-agents` releases. It also makes them available for
the incoming Python equivalent
(huggingface/huggingface_hub#3098).

File resolution is still the same:
1. if agent_id is a file => load it as a `agent.json` file
2. if agent_id is a directory => load from it
3. if agent_id is a subdirectory in
https://huggingface.co/datasets/huggingface/tiny-agents/tree/main =>
load from it
4. otherwise raise exception

Usage is still:

```bash
npx @huggingface/tiny-agents run "julien-c/flux-schnell-generator"
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants