Skip to content

huggingface/hf_agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

172 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

title emoji colorFrom colorTo sdk app_port hf_oauth hf_oauth_scopes
HF Agent
πŸ€–
blue
purple
docker
7860
true
read-repos
write-repos
inference-api

HF Agent

An MLE agent CLI with MCP (Model Context Protocol) integration and built-in tool support.

Quick Start

Installation

# Clone the repository
git clone git@github.com:huggingface/hf_agent.git
cd hf_agent

Install recommended dependencies

uv sync --extra agent # or uv sync --extra all

Interactive CLI

uv run python -m agent.main

This starts an interactive chat session with the agent. Type your messages and the agent will respond, using tools as needed.

The agent will automatically discover and register all tools from configured MCP servers.

Env Setup

ANTHROPIC_API_KEY=<one-key-to-rule-them-all>
HF_TOKEN=<hf-token-to-access-the-hub>
GITHUB_TOKEN=<gh-pat-key-for-not-reinventing-the-wheel>
HF_NAMESPACE=<hf-namespace-to-use>

Architecture

Component Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         User/CLI                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚ User request                                β”‚ Events
             ↓                                             ↑
      submission_queue                                   event_queue
             β”‚                                                 β”‚
             ↓                                                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚            submission_loop (agent_loop.py)         β”‚         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚         β”‚
β”‚  β”‚  1. Receive Operation from queue             β”‚  β”‚         β”‚
β”‚  β”‚  2. Route to Handler (run_agent/compact/...) β”‚  β”‚         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚         β”‚
β”‚                      ↓                             β”‚         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚         β”‚
β”‚  β”‚         Handlers.run_agent()                 β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  β”‚                                              β”‚  β”‚ Emit    β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚ Events  β”‚
β”‚  β”‚  β”‚  Agentic Loop (max 10 iterations)      β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚                                        β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚ Session                          β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚ ContextManager             β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚ β€’ Message history          β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚   (litellm.Message[])      β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚ β€’ Auto-compaction (180k)   β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚                                  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚ ToolRouter                 β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  β”œβ”€ explore_hf_docs        β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  β”œβ”€ fetch_hf_docs          β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  β”œβ”€ find_hf_api            β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  β”œβ”€ plan_tool              β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  β”œβ”€ hf_jobs*               β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  β”œβ”€ hf_private_repos*      β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  β”œβ”€ github_* (3 tools)     β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚  └─ MCP tools (e.g.,       β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β”‚      model_search, etc.)   β”‚  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚                                        β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚  Loop:                                 β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚    1. LLM call (litellm.acompletion)   β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚       ↓                                β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚    2. Parse tool_calls[]               β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚       ↓                                β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚    3. Execute via ToolRouter           β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚       ↓                                β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚    4. Add results to ContextManager    β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚       ↓                                β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β”‚    5. Repeat if tool_calls exist       β”‚  β”‚  β”‚         β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Agentic Loop Flow

User Message
     ↓
[Add to ContextManager]
     ↓
     ╔═══════════════════════════════════════╗
     β•‘      Iteration Loop (max 10)          β•‘
     β•‘                                       β•‘
     β•‘  Get messages + tool specs            β•‘
     β•‘         ↓                             β•‘
     β•‘  litellm.acompletion()                β•‘
     β•‘         ↓                             β•‘
     β•‘  Has tool_calls? ──No──> Done         β•‘
     β•‘         β”‚                             β•‘
     β•‘        Yes                            β•‘
     β•‘         ↓                             β•‘
     β•‘  Add assistant msg (with tool_calls)  β•‘
     β•‘         ↓                             β•‘
     β•‘  For each tool_call:                  β•‘
     β•‘    β€’ ToolRouter.execute_tool()        β•‘
     β•‘    β€’ Add result to ContextManager     β•‘
     β•‘         ↓                             β•‘
     β•‘  Continue loop ─────────────────┐     β•‘
     β•‘         ↑                       β”‚     β•‘
     β•šβ•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•§β•β•β•β•β•β•

Project Structure

agent/
β”œβ”€β”€ config.py                 # Configuration models
β”œβ”€β”€ main.py                   # Interactive CLI entry point
β”œβ”€β”€ prompts/
β”‚   └── system_prompt.yaml   # Agent behavior and personality
β”œβ”€β”€ context_manager/
β”‚   └── manager.py           # Message history & auto-compaction
└── core/
    β”œβ”€β”€ agent_loop.py        # Main agent loop and handlers
    β”œβ”€β”€ session.py           # Session management
    β”œβ”€β”€ mcp_client.py        # MCP SDK integration
    └── tools.py             # ToolRouter and built-in tools

configs/
└── main_agent_config.json   # Model and MCP server configuration

tests/                       # Integration and unit tests
eval/                        # Evaluation suite (see eval/README.md)

Events

The agent emits the following events via event_queue:

  • processing - Starting to process user input
  • assistant_message - LLM response text
  • tool_call - Tool being called with arguments
  • tool_output - Tool execution result
  • approval_request - 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:

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/main_agent_config.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.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •