Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

English | 简体中文

MingAgent

A Java agent framework with Plan-and-Execute (Plan → Execute → Replan) capabilities and configurable LLMs, inspired by popular agents such as OpenManus / Hermes / LangChain Plan-and-Execute.

Core Features

  • Plan-and-Execute Loop: Breaks down tasks into steps, executes them one by one, and dynamically replans after each step, allowing the agent to adapt based on intermediate results.
  • Configurable LLMs: Built on the OpenAI-compatible protocol, one codebase works with DeepSeek / Qwen / Kimi / Zhipu / OpenAI — just change the config.
  • Role-level Model Config: Planner / Executor / Replanner can each use different models and temperatures.
  • Tool Calling (Function Calling): Built-in calculator, date/time, text analysis, web search, and more, with multi-round tool-calling loops.
  • MCP Protocol Support: Connects to external MCP servers via the standard Model Context Protocol, supporting both stdio and HTTP/SSE transports, with automatic tool discovery and registration.
  • Skills System: Follows the Agent Skills open standard. Drop a folder containing SKILL.md into skills/ and it's auto-loaded, with support for scripts and reference docs.
  • Extensible: Implement the Tool interface to add new tools; implement the LLMClient interface to integrate new model providers.

Architecture Overview

                ┌──────────────────────────────────────────┐
                │           PlanAndExecuteAgent            │
                │       (main orchestrator, loop control)   │
                └──────────────────────────────────────────┘
                  │ 1. Plan       │ 2. Execute     │ 3. Replan
                  ▼               ▼                ▼
            ┌─────────┐    ┌───────────┐    ┌───────────┐
            │ Planner │───▶│ Executor  │───▶│ Replanner │
            └─────────┘    └─────┬─────┘    └─────┬─────┘
                                 │                │
                           ┌─────▼─────┐  continue/replan/finish
                           │   Tools   │
                           │  Registry │
                           └───────────┘

Workflow

  1. Planner: Breaks the user's goal into 2–6 executable steps (JSON).
  2. Executor: Takes the next pending step and completes it via an LLM + tool-calling loop, producing the step's result.
  3. Replanner: Evaluates "goal + completed steps/results + remaining steps" to decide the next action:
    • continue: The plan is still valid; proceed to the next step.
    • replan: Adjust the remaining plan based on new findings.
    • finish: The goal is achieved; produce the final answer.
  4. Loop steps 2–3 until finish or the maximum replan count is reached, then synthesize the final answer.

Directory Structure

src/main/java/com/agent/
├── Main.java                  # Entry point (interactive / single-task mode)
├── config/                    # Configuration loading
│   ├── AgentConfig.java
│   └── ConfigLoader.java
├── llm/                       # LLM abstraction layer (configurable models)
│   ├── LLMClient.java         #   Interface
│   ├── LLMConfig.java
│   ├── LLMRequest/Response.java
│   ├── OpenAICompatibleClient.java  # OpenAI/DeepSeek/Qwen compatible impl
│   └── LLMFactory.java
├── model/                     # Data models
│   ├── Message / Plan / Step / StepResult / StepStatus
│   ├── AgentState.java        # Global state
│   └── ReplanDecision.java    # Replan decision
├── tools/                     # Tool framework
│   ├── Tool / ToolSpec / ToolResult / ToolRegistry
│   ├── SecurityPolicy.java    # Shared security policy (hazard detection + lock)
│   ├── AbstractFileTool.java  # File tool base (path validation / sandboxing)
│   ├── ReadFileTool.java      # Built-in: read file
│   ├── WriteFileTool.java     # Built-in: write file
│   ├── ListDirectoryTool.java # Built-in: list directory
│   ├── EditFileTool.java      # Built-in: edit file
│   ├── FetchUrlTool.java      # Built-in: fetch URL
│   ├── PythonInterpreterTool.java # Built-in: Python code execution
│   ├── ExecuteShellTool.java  # Built-in: shell execution (hazard detection)
│   ├── CalculatorTool.java    # Built-in: calculator
│   ├── DateTimeTool.java      # Built-in: date/time
│   ├── TextAnalyzerTool.java  # Built-in: text analysis
│   └── WebSearchTool.java     # Built-in: Tavily search
├── mcp/                       # MCP protocol client
│   ├── Transport.java         #   Transport layer abstraction
│   ├── StdioTransport.java    #   stdio transport (local subprocess)
│   ├── HttpSseTransport.java  #   HTTP/SSE transport (remote server)
│   ├── MCPClient.java         #   JSON-RPC client (based on Transport)
│   └── MCPToolWrapper.java    #   MCP tool adapter
├── skill/                     # Skills system
│   ├── Skill.java             #   Skill definition
│   ├── SkillLoader.java       #   Directory scan + SKILL.md parser
│   ├── SkillTool.java         #   Skill tool wrapper
│   └── SkillRegistry.java     #   Skill registry
├── core/                      # Plan-and-Execute core
│   ├── Planner.java           #   Planner
│   ├── Executor.java          #   Executor (with tool-calling loop)
│   ├── Replanner.java         #   Replanner
│   └── PlanAndExecuteAgent.java
├── prompt/                    # Prompt templates
│   └── PromptTemplates.java
└── util/                      # Utilities
    └── JsonUtil.java

skills/                        # Skills directory (each subfolder is a skill)
├── translation/
│   └── SKILL.md
└── code-stats/
    ├── SKILL.md
    └── scripts/
        └── count_stats.py

Quick Start

1. Configure the Model

Edit src/main/resources/application.yml and fill in your API key, base URL, and model name:

llm:
  provider: "openai-compatible"
  apiKey: "sk-xxxxxxxx"
  baseUrl: "https://api.deepseek.com/v1"   # DeepSeek
  # baseUrl: "https://api.openai.com/v1"    # OpenAI
  # baseUrl: "https://dashscope.aliyuncs.com/compatible-mode/v1"  # Qwen
  model: "deepseek-chat"
  temperature: 0.2
  maxTokens: 2048

2. Build

mvn clean package

3. Run

# Interactive mode
java -jar target/plan-and-execute-agent-1.0.0.jar

# Single-task mode
java -jar target/plan-and-execute-agent-1.0.0.jar "Calculate (123 + 456) * 2 and tell me what day of the week it is"

# Specify an external config file
java -Dconfig.file=/path/to/my.yml -jar target/plan-and-execute-agent-1.0.0.jar

Note: The chosen model must support Function Calling (tool calling), otherwise the Executor cannot use tools and will fall back to plain text reasoning. Models like DeepSeek-Chat, GPT-4o, and Qwen-Max are recommended.

Configuration

agent:
  maxIterations: 10   # Max rounds of LLM-tool calling loop per step
  maxReplans: 8       # Max replan attempts (prevents infinite loops)
  verbose: true
  workspace: "./workspace"  # Working directory for file tools (sandbox root)

tools:
  pythonCmd: "python"  # Python executable (e.g. python / python3)

llm:                  # Global model config
  provider: "openai-compatible"
  apiKey: "..."
  baseUrl: "..."
  model: "..."

# Optional: specify different models/temperatures per role (blank = use global llm)
planner:    { model: "", temperature: 0.1 }
executor:   { model: "", temperature: 0.2 }
replanner:  { model: "", temperature: 0.2 }

Built-in Tools

Tool Name Description
Read File read_file Read a text file, supports line-range reading
Write File write_file Create/overwrite a file, auto-creates parent dirs
List Directory list_directory List directory contents, supports recursion
Edit File edit_file Find and replace file fragments, precise editing
Fetch URL fetch_url Fetch a URL's body and convert to plain text
Python Interpreter python_interpreter Execute Python code in a subprocess (30s timeout)
Execute Shell execute_shell Run shell commands in the workspace; hazardous commands require confirmation
Calculator calculator Precise arithmetic evaluation (parentheses, exponents)
Current Time get_current_time Get the current time in a specified timezone
Text Analyzer text_analyzer Count characters/words/lines
Web Search web_search Web search via Tavily API, returns summaries and results

For example, use a cheaper model for planning and a stronger model for execution:

llm:
  model: "deepseek-chat"
planner:
  model: "deepseek-chat"
  temperature: 0.1
executor:
  model: "deepseek-reasoner"
  temperature: 0.2

MCP Protocol Support

The agent supports the Model Context Protocol (MCP), allowing it to connect to any external MCP server and automatically discover its tools. Once connected at startup, MCP server tools are registered alongside built-in tools in the ToolRegistry — the agent can call them just like built-in tools.

Supported Transports

The agent supports two MCP transports, auto-selected by config or explicitly set via the transport field:

Transport Use Case Config Description
stdio Local MCP servers command + args Launches a subprocess via ProcessBuilder, communicates over stdin/stdout
HTTP/SSE Remote MCP servers url Supports both Streamable HTTP and legacy SSE modes, auto-detected

Auto-inference rules:

  • url configured and no command → HTTP/SSE mode
  • command configured → stdio mode
  • Can also be explicitly set via transport (stdio / http / sse)

Configuring MCP Servers

Add an mcpServers section to application.yml:

stdio Mode (Local Servers)

For local MCP servers launched via npx/node/python:

mcpServers:
  - name: "filesystem"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-filesystem", "./workspace"]

  - name: "github"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-github"]
    env:
      GITHUB_TOKEN: "ghp_xxxxxxxxxxxx"

  - name: "sqlite"
    command: "npx"
    args: ["-y", "@modelcontextprotocol/server-sqlite", "--db-path", "./data.db"]

HTTP/SSE Mode (Remote Servers)

For MCP servers deployed remotely, communicating over HTTP:

mcpServers:
  - name: "remote-mcp"
    url: "http://some ip address:8000/mcp"
    transport: "http"                   # Optional: http / sse, auto-inferred if omitted
    headers:                            # Optional: custom request headers
      Authorization: "Bearer xxx"

  # Legacy SSE mode (URL ends with /sse)
  - name: "sse-mcp"
    url: "http://some ip address:3000/sse"
    transport: "sse"

HTTP/SSE auto-detection:

  • URL ends with /sse → Legacy SSE mode (GET to establish a long-lived SSE connection, then POST requests)
  • Other URLs → Streamable HTTP mode (direct POST, response may be JSON or SSE stream)

Streamable HTTP mode automatically handles the mcp-session-id returned by the server and sends it back in subsequent requests to maintain the session.

Configuration Fields

Field Mode Required Description
name All Yes Server name (for log identification)
command stdio Yes Launch command (e.g. npx, node, python)
args stdio No Command arguments
env stdio No Environment variables
url HTTP/SSE Yes MCP server URL (e.g. http://host:port/mcp)
transport All No Transport type: stdio / http / sse, auto-inferred if omitted
headers HTTP/SSE No Custom request headers (e.g. Authorization: Bearer xxx)

How It Works

  1. At startup, the agent selects the transport based on config (stdio subprocess / HTTP connection)
  2. Completes the initialize handshake via JSON-RPC 2.0
  3. Calls tools/list to discover all tools provided by the server
  4. Wraps each tool as an MCPToolWrapper and registers it in the ToolRegistry
  5. When the agent calls a tool, it sends a tools/call request to the MCP server
  6. All MCP connections are automatically closed on program exit

Common MCP Servers

Server Type Install/Connect Description
filesystem stdio npx -y @modelcontextprotocol/server-filesystem <dir> File system read/write
github stdio npx -y @modelcontextprotocol/server-github GitHub API (requires GITHUB_TOKEN)
sqlite stdio npx -y @modelcontextprotocol/server-sqlite --db-path <path> SQLite database operations
postgres stdio npx -y @modelcontextprotocol/server-postgres <conn> PostgreSQL database
datetime HTTP url: http://host:8000/mcp Date/time tool (example)

See the MCP Servers directory for more.

Skills System

The agent supports the Agent Skills open standard, managing skills via folders. Place a folder containing SKILL.md into skills/ and the agent will auto-discover and load it as a usable tool at startup.

Directory Structure

Each skill is a self-contained directory:

skills/
├── my-skill/
│   ├── SKILL.md              # Required: skill definition (YAML frontmatter + Markdown instructions)
│   ├── scripts/              # Optional: executable scripts
│   │   ├── extract.py
│   │   └── process.sh
│   ├── references/           # Optional: on-demand reference docs
│   │   ├── REFERENCE.md
│   │   └── api_docs.md
│   └── assets/               # Optional: static resources (templates, data files, etc.)
│       └── template.json

SKILL.md Format

---
name: my-skill
description: Describe what the skill does and when to use it. Include keywords for agent matching.
license: Apache-2.0
compatibility: Requires Python 3.10+
---

# Skill Instructions

Tell the agent how to handle this type of task...

## Workflow

1. Step one
2. Step two
3. Step three

Frontmatter fields:

Field Required Description
name Yes Skill name (lowercase + hyphens, e.g. code-review)
description Yes What the skill does and when to use it (max 1024 chars)
license No License
compatibility No Environment requirements
allowed-tools No List of tools this skill is allowed to call

Three Invocation Modes

The agent supports three modes when calling a skill:

1. LLM Mode (default): Uses the SKILL.md instructions as an expert prompt, letting the LLM handle the task professionally.

{"task": "Review the quality of the following code..."}

2. Script Mode: Specify the script parameter to directly execute a script in the scripts/ directory. Supports .py, .sh, .js, .ps1.

{"task": "Stats for Main.java", "script": "count_stats.py", "script_args": "Main.java --lang java"}

3. Reference Doc Mode: Specify the reference parameter to load a document from references/ into context, then hand it to the LLM.

{"task": "Review the API design against the spec", "reference": "api_docs.md"}

Configuring the Skills Directory

Specify the skills directory path in application.yml:

skillsDir: "./skills"

Defaults to ./skills but can be any path. The agent scans all subdirectories containing SKILL.md at startup and loads them automatically.

Built-in Example Skills

The project ships with two example skills:

Skill Type Description
translation Pure LLM Multilingual translation skill, injects expert translation prompts
code-stats LLM + Script Code statistics skill, supports Python script for precise stats

Creating a Custom Skill

  1. Create a new folder under skills/ (the folder name is the skill name):
mkdir skills/my-skill
  1. Create SKILL.md:
---
name: my-skill
description: Describe what your skill does and when to use it
---

# Skill Instructions

You are a xxx expert. Follow these steps to process...
  1. (Optional) Add scripts, reference docs, or resources:
skills/my-skill/
├── SKILL.md
├── scripts/
│   └── process.py
└── references/
    └── guide.md
  1. Restart the agent — it will be auto-loaded and ready to use.

Extension Guide

Adding a Custom Tool

Implement the Tool interface and register it in the ToolRegistry:

public class WeatherTool implements Tool {
    @Override
    public String name() { return "get_weather"; }

    @Override
    public ToolSpec spec() {
        return new ToolSpec("get_weather", "Query the weather for a given city",
            "{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"]}");
    }

    @Override
    public ToolResult execute(String argumentsJson) {
        // Parse args, call weather API, return result
        return ToolResult.ok("Beijing, sunny, 25°C");
    }
}

Register it in Main.defaultTools():

return new ToolRegistry()
        .register(new CalculatorTool())
        .register(new WeatherTool());

Integrating a New Model Provider

Implement the LLMClient interface and add a branch in LLMFactory.create() (e.g. to integrate Anthropic Claude, local Ollama, etc.).

Design References

  • LangChain Plan-and-Execute Agent: The plan-then-execute-then-replan loop paradigm.
  • OpenManus / Hermes and similar agents: Role-based prompting, tool-calling loops, dynamic replanning.

About

A simplified Java implementation of desktop agents(OpenClaw,Hermes style), including plan and execute engine, tool execution, skill and mcp client.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages