Skip to content

0ndrec/mellea-agent

Repository files navigation

mellea-agent

A terminal coding agent powered by mellea. Supports any OpenAI-compatible API (OpenRouter, OpenAI, local LM Studio/Ollama) and on-device inference via LiteRT LM.

Agent session: researching IBM Bob and comparing it with GitHub Copilot

The screenshot above shows a typical session (OpenRouter provider, qwen/qwen3.6-flash). Asked to "Find information about IBM Bob Partner and compare this solution with the GitHub copilot", the agent autonomously chains tool calls — duckduckgo_search to find sources, then scrape_webpage to pull detailed content from official pages — narrating its reasoning between each step before compiling the final comparison. Each tool invocation is printed inline with its arguments, so you can follow exactly what the agent is doing.


Architecture

This agent uses the mellea library as its core LLM orchestration framework:

  • Session management: mellea.start_session() creates chat sessions with configurable backends, system prompts, and model options
  • Tool integration: mellea's ModelOption.TOOLS enables function calling with automatic tool registration and execution via the @tool decorator
  • Requirements system: mellea's Requirement class provides validation hooks for safety checks (e.g., preventing writes to system directories)
  • Multi-backend support: mellea's backend abstraction handles OpenAI-compatible APIs; LiteRT uses its native litert_lm API directly
  • MCP integration: mellea's discover_mcp_tools() and http_connection() load tools from MCP servers at startup

The agent maintains two execution paths:

  1. API providers (local, openrouter, openai, anthropic): Uses mellea's session.instruct() with tool calling
  2. LiteRT provider: Uses litert_lm.Engine directly with a custom tool handler, since mellea doesn't yet wrap LiteRT's tool format

Key mellea imports used:

  • mellea.start_session — creates configured chat sessions
  • mellea.backends.ModelOption — configures tools, temperature, max tokens, system prompt
  • mellea.backends.tool — decorator for registering tool functions
  • mellea.core.Requirement — validation for tool arguments
  • mellea.stdlib.tools.mcp — MCP server discovery and tool loading
  • mellea.stdlib.tools.local_code_interpreter — safe Python execution for the python_exec tool

Requirements

  • Python 3.13+
  • uv package manager

Installation

git clone https://github.com/0ndrec/mellea-agent.git
cd mellea-agent
uv sync

The scrape_webpage tool drives a real Chromium browser via Patchright. Install the browser once:

uv run patchright install chromium

Everything else works without this step — the tool just returns an error message if Chromium is missing.


Running the agent

uv run python agent.py

The prompt supports command history (arrow keys) and exits on Ctrl+C, Ctrl+D, or typing exit.

The agent keeps conversation history across turns (the last 10 exchanges are fed back as context), so follow-up requests like "now add tests for that" work as expected.

Single-shot mode (no interactive loop):

uv run python agent.py "refactor main.py to use dataclasses"

Provider configuration

Set the LLM_PROVIDER environment variable to switch providers. The default is local.

LLM_PROVIDER What it connects to
local LM Studio / Ollama at http://127.0.0.1:1234/v1
openrouter openrouter.ai
openai OpenAI API
anthropic Anthropic models via OpenRouter
litert Local .litertlm model file (offline, no API key)

OpenRouter

export LLM_PROVIDER=openrouter
export OPENROUTER_API_KEY=sk-or-...
uv run python agent.py

Default model: qwen/qwen3.6-flash. Override:

export LLM_MODEL=deepseek/deepseek-r1

OpenAI

export LLM_PROVIDER=openai
export OPENAI_API_KEY=sk-...
uv run python agent.py

Local server (LM Studio / Ollama)

Start your local server, then:

export LLM_PROVIDER=local
export LLM_MODEL=your-model-name
uv run python agent.py

The default base URL is http://127.0.0.1:1234/v1. Override with LLM_BASE_URL if your server listens elsewhere.

Anthropic (via OpenRouter)

export LLM_PROVIDER=anthropic
export OPENROUTER_API_KEY=sk-or-...
uv run python agent.py

Default model: anthropic/claude-sonnet-4-6.


LiteRT — on-device inference

LiteRT runs models locally from a .litertlm file with no API key, no network, and no server. Models run on CPU, GPU (Vulkan/Metal), or NPU.

1. Install the LiteRT extra

uv sync --extra litert

2. Download a model from Hugging Face

Models are distributed as .litertlm files. Download one using the huggingface_hub library:

uv add huggingface_hub   # one-time
from huggingface_hub import hf_hub_download

# ~2.8 GB — Qwen3 4B INT4, good general-purpose coding model
path = hf_hub_download(
    repo_id="DuoNeural/Qwen3-4B-LiteRT",
    filename="model.litertlm",
)
print(path)   # prints the local cache path

Run this once; hf_hub_download caches the file and returns the local path on subsequent calls.

Recommended models (all INT4 quantized):

Model Repo Size Notes
Qwen3 4B DuoNeural/Qwen3-4B-LiteRT ~2.8 GB Good coding, fast on CPU
DeepSeek-R1 7B litert-community/DeepSeek-R1-Distill-Qwen-7B ~4.2 GB Reasoning chains, needs GPU for speed
Granite 4.1 3B DuoNeural/Granite-4.1-3B-LiteRT ~2 GB IBM code model, small footprint
Llama 3.2 3B mlboydaisuke/Llama-3.2-3B-Instruct-LiteRT ~2 GB Versatile instruction model
DeepSeek-R1 1.5B mlboydaisuke/DeepSeek-R1-Distill-Qwen-1.5B-LiteRT ~1 GB Minimal footprint

Browse all 280+ models at huggingface.co/models?library=litert.

3. Run the agent

export LLM_PROVIDER=litert
export LITERT_MODEL_PATH=/path/to/model.litertlm   # path printed by hf_hub_download
uv run python agent.py

Or inline:

LLM_PROVIDER=litert LITERT_MODEL_PATH=$(python -c "
from huggingface_hub import hf_hub_download
print(hf_hub_download('DuoNeural/Qwen3-4B-LiteRT', 'model.litertlm'))
") uv run python agent.py

Backend selection

export LITERT_BACKEND=cpu    # default — works everywhere
export LITERT_BACKEND=gpu    # Vulkan (Linux/Android) or Metal (macOS)
export LITERT_BACKEND=npu    # Qualcomm Hexagon or similar

GPU is recommended for models ≥3 B parameters. On a Mac M-series, GPU gives ~60–70 tokens/second for a 7B model.


Tools

The agent has access to these built-in tools:

Tool Description
read_file(path) Read a file with line numbers
write_file(path, content) Write or overwrite a file
list_dir(path) List directory contents
run_command(command, cwd, timeout) Execute a shell command
search_text(pattern, path, file_glob) Regex search across files
python_exec(code) Run Python in the current directory
duckduckgo_search(query, max_results) Web search via DuckDuckGo
scrape_webpage(url, selector, wait_for, timeout, headless) Extract text from a web page with a stealth Chromium browser (Patchright) — handles JavaScript-rendered pages and basic bot detection. Optional CSS selector targets specific elements; wait_for waits for a selector before extracting
ask_user(question, options) Pause and ask the user a question
change_provider(provider, model) Switch the active LLM provider at runtime

The agent calls ask_user before making ambiguous decisions, and change_provider only when you explicitly request a different provider or model — for example: "switch to OpenAI" or "use deepseek/deepseek-r1".


MCP servers

Additional tools are loaded from MCP servers configured in config.py. The default config connects to the MDN documentation server. To add more servers, edit the MCP_SERVERS list.


Environment variable reference

Variable Default Description
LLM_PROVIDER local Active provider (local, openrouter, openai, anthropic, litert)
LLM_MODEL provider default Override the model ID or path
LLM_BASE_URL provider default Override the API base URL
LLM_API_KEY provider default Override the API key
OPENROUTER_API_KEY API key for OpenRouter and Anthropic providers
OPENAI_API_KEY API key for OpenAI provider
LITERT_MODEL_PATH model.litertlm Path to the .litertlm model file
LITERT_BACKEND cpu LiteRT compute backend (cpu, gpu, npu)

About

A terminal coding agent powered by mellea

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages