diff --git a/EvoScientist/cli/commands.py b/EvoScientist/cli/commands.py
index b74fcf0..a012f2b 100644
--- a/EvoScientist/cli/commands.py
+++ b/EvoScientist/cli/commands.py
@@ -87,6 +87,7 @@ def channel_setup():
def serve(
no_thinking: bool = typer.Option(False, "--no-thinking", help="Disable thinking relay to channels"),
workdir: Optional[str] = typer.Option(None, "--workdir", help="Override workspace directory"),
+ auto_approve: bool = typer.Option(False, "--auto-approve", help="Auto-approve all tool executions without prompting"),
):
"""Run EvoScientist in headless mode -- channels only, no interactive prompt.
@@ -102,7 +103,10 @@ def serve(
from ..config import get_effective_config, apply_config_to_env
- config = get_effective_config()
+ cli_overrides = {}
+ if auto_approve:
+ cli_overrides["auto_approve"] = True
+ config = get_effective_config(cli_overrides)
apply_config_to_env(config)
if not config.channel_enabled:
@@ -410,6 +414,7 @@ def _main_callback(
workdir: Optional[str] = typer.Option(None, "--workdir", help="Override workspace directory for this session"),
use_cwd: bool = typer.Option(False, "--use-cwd", help="Use current working directory as workspace"),
no_thinking: bool = typer.Option(False, "--no-thinking", help="Disable thinking display"),
+ auto_approve: bool = typer.Option(False, "--auto-approve", help="Auto-approve all tool executions without prompting"),
ui: Optional[str] = typer.Option(
None,
"--ui",
@@ -438,6 +443,8 @@ def _main_callback(
cli_overrides["show_thinking"] = False
if ui:
cli_overrides["ui_backend"] = ui
+ if auto_approve:
+ cli_overrides["auto_approve"] = True
config = get_effective_config(cli_overrides)
apply_config_to_env(config)
diff --git a/README.md b/README.md
index 6164645..586f99e 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,7 @@ Going beyond traditional human-in-the-loop systems, EvoScientist introduces an A
- [x] 📻 EvoMemory v1.0 shipped
- [x] ⚒️ 200+ predefined skills built in
- [x] 🧩 Built-in research-lifecycle skills shipped
+- [x] 👋 Human-in-the-loop action approval
- [ ] 📺 Web app with workspace UI
- [ ] 📑 Technical report on the way
- [ ] 📹 Demo and tutorial in the works
@@ -227,6 +228,27 @@ EvoSci serve # headless mode — channels only, no interact
+
+Action Approval (HITL)
+
+By default, shell commands (`execute` tool) require human approval before running. To skip approval prompts:
+
+```bash
+# Per-session: auto-approve via CLI flag
+EvoSci --auto-approve
+EvoSci -p "query" --auto-approve
+
+# Persistent: set in config (applies to all future sessions)
+EvoSci config set auto_approve true
+
+# Or allow only specific command prefixes
+EvoSci config set shell_allow_list "python,pip,pytest,ruff,git"
+```
+
+During a session you can also reply **3** (Approve all) at any approval prompt to auto-approve for the rest of that session.
+
+
+
In-session commands
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 4a3594c..2092782 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -69,6 +69,7 @@ EvoScientist 超越了传统的人在回路(Human-in-the-Loop)模式,引
- [x] 📻 EvoMemory v1.0 已上线
- [x] ⚒️ 200+ 预置技能已内置
- [x] 🧩 内置研究全流程技能已上线
+- [x] 👋 Human-in-the-loop 操作审批
- [ ] 📺 带工作区的 Web 应用界面
- [ ] 📑 技术报告即将发布
- [ ] 📹 Demo 与教程正在制作中
@@ -237,6 +238,27 @@ EvoSci serve # 无头模式——仅渠道,无交互提
+
+操作审批(HITL)
+
+默认情况下,Shell 命令(`execute` 工具)执行前需要人工审批。跳过审批提示的方式:
+
+```bash
+# 单次会话:通过 CLI 参数启用自动审批
+EvoSci --auto-approve
+EvoSci -p "query" --auto-approve
+
+# 持久化:写入配置(对所有后续会话生效)
+EvoSci config set auto_approve true
+
+# 或仅放行特定命令前缀
+EvoSci config set shell_allow_list "python,pip,pytest,ruff,git"
+```
+
+会话中也可以在审批提示时回复 **3**(Approve all),仅对当次会话自动审批后续所有操作。
+
+
+
会话内命令
diff --git a/tests/test_cli_serve.py b/tests/test_cli_serve.py
index 63c27d3..67481aa 100644
--- a/tests/test_cli_serve.py
+++ b/tests/test_cli_serve.py
@@ -61,7 +61,7 @@ def _run_serve_once(
monkeypatch.setattr(commands, "_start_channels_bus_mode", _fake_start_channels_bus_mode)
monkeypatch.setattr(commands, "_channels_stop", _fake_channels_stop)
- monkeypatch.setattr(config_mod, "get_effective_config", lambda: config)
+ monkeypatch.setattr(config_mod, "get_effective_config", lambda *_a, **_k: config)
monkeypatch.setattr(config_mod, "apply_config_to_env", lambda _cfg: None)
monkeypatch.setattr(dotenv, "load_dotenv", lambda *_a, **_k: None)